r2333: check the script is not a 0 lenght string
[Samba/bb.git] / source / smbd / trans2.c
blobf3176940c2fc109b6d83e4044bffce32a8b589b6
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, False);
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);
621 if (bad_path) {
622 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
625 if (!check_name(fname,conn)) {
626 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
629 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
630 oplock_request, &rmode,&smb_action);
632 if (!fsp) {
633 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
634 /* We have re-scheduled this call. */
635 clear_cached_errors();
636 return -1;
638 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
641 size = get_file_size(sbuf);
642 fmode = dos_mode(conn,fname,&sbuf);
643 mtime = sbuf.st_mtime;
644 inode = sbuf.st_ino;
645 if (fmode & aDIR) {
646 close_file(fsp,False);
647 return(ERROR_DOS(ERRDOS,ERRnoaccess));
650 /* Realloc the size of parameters and data we will return */
651 params = Realloc(*pparams, 28);
652 if( params == NULL )
653 return(ERROR_DOS(ERRDOS,ERRnomem));
654 *pparams = params;
656 memset((char *)params,'\0',28);
657 SSVAL(params,0,fsp->fnum);
658 SSVAL(params,2,fmode);
659 put_dos_date2(params,4, mtime);
660 SIVAL(params,8, (uint32)size);
661 SSVAL(params,12,rmode);
663 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
664 smb_action |= EXTENDED_OPLOCK_GRANTED;
666 SSVAL(params,18,smb_action);
669 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
671 SIVAL(params,20,inode);
673 /* Send the required number of replies */
674 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
676 return -1;
679 /*********************************************************
680 Routine to check if a given string matches exactly.
681 as a special case a mask of "." does NOT match. That
682 is required for correct wildcard semantics
683 Case can be significant or not.
684 **********************************************************/
686 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
688 if (mask[0] == '.' && mask[1] == 0)
689 return False;
690 if (case_sig)
691 return strcmp(str,mask)==0;
692 if (StrCaseCmp(str,mask) != 0) {
693 return False;
695 if (ms_has_wild(str)) {
696 return False;
698 return True;
701 /****************************************************************************
702 Return the filetype for UNIX extensions.
703 ****************************************************************************/
705 static uint32 unix_filetype(mode_t mode)
707 if(S_ISREG(mode))
708 return UNIX_TYPE_FILE;
709 else if(S_ISDIR(mode))
710 return UNIX_TYPE_DIR;
711 #ifdef S_ISLNK
712 else if(S_ISLNK(mode))
713 return UNIX_TYPE_SYMLINK;
714 #endif
715 #ifdef S_ISCHR
716 else if(S_ISCHR(mode))
717 return UNIX_TYPE_CHARDEV;
718 #endif
719 #ifdef S_ISBLK
720 else if(S_ISBLK(mode))
721 return UNIX_TYPE_BLKDEV;
722 #endif
723 #ifdef S_ISFIFO
724 else if(S_ISFIFO(mode))
725 return UNIX_TYPE_FIFO;
726 #endif
727 #ifdef S_ISSOCK
728 else if(S_ISSOCK(mode))
729 return UNIX_TYPE_SOCKET;
730 #endif
732 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
733 return UNIX_TYPE_UNKNOWN;
736 /****************************************************************************
737 Return the major devicenumber for UNIX extensions.
738 ****************************************************************************/
740 static uint32 unix_dev_major(SMB_DEV_T dev)
742 #if defined(HAVE_DEVICE_MAJOR_FN)
743 return (uint32)major(dev);
744 #else
745 return (uint32)(dev >> 8);
746 #endif
749 /****************************************************************************
750 Return the minor devicenumber for UNIX extensions.
751 ****************************************************************************/
753 static uint32 unix_dev_minor(SMB_DEV_T dev)
755 #if defined(HAVE_DEVICE_MINOR_FN)
756 return (uint32)minor(dev);
757 #else
758 return (uint32)(dev & 0xff);
759 #endif
762 /****************************************************************************
763 Map wire perms onto standard UNIX permissions. Obey share restrictions.
764 ****************************************************************************/
766 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
768 mode_t ret = 0;
770 if (perms == SMB_MODE_NO_CHANGE)
771 return pst->st_mode;
773 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
774 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
775 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
776 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
777 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
778 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
779 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
780 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
781 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
782 #ifdef S_ISVTX
783 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
784 #endif
785 #ifdef S_ISGID
786 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
787 #endif
788 #ifdef S_ISUID
789 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
790 #endif
792 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
793 ret &= lp_dir_mask(SNUM(conn));
794 /* Add in force bits */
795 ret |= lp_force_dir_mode(SNUM(conn));
796 } else {
797 /* Apply mode mask */
798 ret &= lp_create_mask(SNUM(conn));
799 /* Add in force bits */
800 ret |= lp_force_create_mode(SNUM(conn));
803 return ret;
806 /****************************************************************************
807 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
808 ****************************************************************************/
810 time_t interpret_long_unix_date(char *p)
812 DEBUG(10,("interpret_long_unix_date\n"));
813 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
814 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
815 return -1;
816 } else {
817 return interpret_long_date(p);
821 /****************************************************************************
822 Get a level dependent lanman2 dir entry.
823 ****************************************************************************/
825 static BOOL get_lanman2_dir_entry(connection_struct *conn,
826 void *inbuf, void *outbuf,
827 char *path_mask,int dirtype,int info_level,
828 int requires_resume_key,
829 BOOL dont_descend,char **ppdata,
830 char *base_data, int space_remaining,
831 BOOL *out_of_space, BOOL *got_exact_match,
832 int *last_name_off)
834 const char *dname;
835 BOOL found = False;
836 SMB_STRUCT_STAT sbuf;
837 pstring mask;
838 pstring pathreal;
839 pstring fname;
840 char *p, *q, *pdata = *ppdata;
841 uint32 reskey=0;
842 int prev_dirpos=0;
843 int mode=0;
844 SMB_OFF_T file_size = 0;
845 SMB_BIG_UINT allocation_size = 0;
846 uint32 len;
847 time_t mdate=0, adate=0, cdate=0;
848 char *nameptr;
849 BOOL was_8_3;
850 int nt_extmode; /* Used for NT connections instead of mode */
851 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
853 *fname = 0;
854 *out_of_space = False;
855 *got_exact_match = False;
857 if (!conn->dirptr)
858 return(False);
860 p = strrchr_m(path_mask,'/');
861 if(p != NULL) {
862 if(p[1] == '\0')
863 pstrcpy(mask,"*.*");
864 else
865 pstrcpy(mask, p+1);
866 } else
867 pstrcpy(mask, path_mask);
869 while (!found) {
870 BOOL got_match;
872 /* Needed if we run out of space */
873 prev_dirpos = TellDir(conn->dirptr);
874 dname = ReadDirName(conn->dirptr);
877 * Due to bugs in NT client redirectors we are not using
878 * resume keys any more - set them to zero.
879 * Check out the related comments in findfirst/findnext.
880 * JRA.
883 reskey = 0;
885 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
886 (long)conn->dirptr,TellDir(conn->dirptr)));
888 if (!dname)
889 return(False);
891 pstrcpy(fname,dname);
893 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
894 got_match = mask_match(fname, mask, conn->case_sensitive);
896 if(!got_match && !mangle_is_8_3(fname, False)) {
899 * It turns out that NT matches wildcards against
900 * both long *and* short names. This may explain some
901 * of the wildcard wierdness from old DOS clients
902 * that some people have been seeing.... JRA.
905 pstring newname;
906 pstrcpy( newname, fname);
907 mangle_map( newname, True, False, SNUM(conn));
908 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
909 got_match = mask_match(newname, mask, conn->case_sensitive);
912 if(got_match) {
913 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
914 if (dont_descend && !isdots)
915 continue;
917 pstrcpy(pathreal,conn->dirpath);
918 if(needslash)
919 pstrcat(pathreal,"/");
920 pstrcat(pathreal,dname);
922 if (INFO_LEVEL_IS_UNIX(info_level)) {
923 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
924 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
925 pathreal,strerror(errno)));
926 continue;
928 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
930 /* Needed to show the msdfs symlinks as
931 * directories */
933 if(lp_host_msdfs() &&
934 lp_msdfs_root(SNUM(conn)) &&
935 is_msdfs_link(conn, pathreal, NULL, NULL,
936 &sbuf)) {
938 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
939 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
941 } else {
943 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
944 pathreal,strerror(errno)));
945 continue;
949 mode = dos_mode(conn,pathreal,&sbuf);
951 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
952 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
953 continue;
956 file_size = get_file_size(sbuf);
957 allocation_size = get_allocation_size(NULL,&sbuf);
958 mdate = sbuf.st_mtime;
959 adate = sbuf.st_atime;
960 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
962 if (lp_dos_filetime_resolution(SNUM(conn))) {
963 cdate &= ~1;
964 mdate &= ~1;
965 adate &= ~1;
968 if(mode & aDIR)
969 file_size = 0;
971 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
973 found = True;
977 mangle_map(fname,False,True,SNUM(conn));
979 p = pdata;
980 nameptr = p;
982 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
984 switch (info_level) {
985 case SMB_INFO_STANDARD:
986 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
987 if(requires_resume_key) {
988 SIVAL(p,0,reskey);
989 p += 4;
991 put_dos_date2(p,l1_fdateCreation,cdate);
992 put_dos_date2(p,l1_fdateLastAccess,adate);
993 put_dos_date2(p,l1_fdateLastWrite,mdate);
994 SIVAL(p,l1_cbFile,(uint32)file_size);
995 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
996 SSVAL(p,l1_attrFile,mode);
997 p += l1_achName;
998 nameptr = p;
999 p += align_string(outbuf, p, 0);
1000 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1001 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1002 if (len > 2) {
1003 SCVAL(nameptr, -1, len - 2);
1004 } else {
1005 SCVAL(nameptr, -1, 0);
1007 } else {
1008 if (len > 1) {
1009 SCVAL(nameptr, -1, len - 1);
1010 } else {
1011 SCVAL(nameptr, -1, 0);
1014 p += len;
1015 break;
1017 case SMB_INFO_QUERY_EA_SIZE:
1018 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1019 if(requires_resume_key) {
1020 SIVAL(p,0,reskey);
1021 p += 4;
1023 put_dos_date2(p,l2_fdateCreation,cdate);
1024 put_dos_date2(p,l2_fdateLastAccess,adate);
1025 put_dos_date2(p,l2_fdateLastWrite,mdate);
1026 SIVAL(p,l2_cbFile,(uint32)file_size);
1027 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1028 SSVAL(p,l2_attrFile,mode);
1030 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1031 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1033 p += l2_achName;
1034 nameptr = p - 1;
1035 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1036 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1037 if (len > 2) {
1038 len -= 2;
1039 } else {
1040 len = 0;
1042 } else {
1043 if (len > 1) {
1044 len -= 1;
1045 } else {
1046 len = 0;
1049 SCVAL(nameptr,0,len);
1050 p += len;
1051 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1052 break;
1054 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1055 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1056 was_8_3 = mangle_is_8_3(fname, True);
1057 p += 4;
1058 SIVAL(p,0,reskey); p += 4;
1059 put_long_date(p,cdate); p += 8;
1060 put_long_date(p,adate); p += 8;
1061 put_long_date(p,mdate); p += 8;
1062 put_long_date(p,mdate); p += 8;
1063 SOFF_T(p,0,file_size); p += 8;
1064 SOFF_T(p,0,allocation_size); p += 8;
1065 SIVAL(p,0,nt_extmode); p += 4;
1066 q = p; p += 4; /* q is placeholder for name length. */
1068 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1069 SIVAL(p,0,ea_size); /* Extended attributes */
1070 p += 4;
1072 /* Clear the short name buffer. This is
1073 * IMPORTANT as not doing so will trigger
1074 * a Win2k client bug. JRA.
1076 memset(p,'\0',26);
1077 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1078 pstring mangled_name;
1079 pstrcpy(mangled_name, fname);
1080 mangle_map(mangled_name,True,True,SNUM(conn));
1081 mangled_name[12] = 0;
1082 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1083 SSVAL(p, 0, len);
1084 } else {
1085 SSVAL(p,0,0);
1086 *(p+2) = 0;
1088 p += 2 + 24;
1089 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1090 SIVAL(q,0,len);
1091 p += len;
1092 len = PTR_DIFF(p, pdata);
1093 len = (len + 3) & ~3;
1094 SIVAL(pdata,0,len);
1095 p = pdata + len;
1096 break;
1098 case SMB_FIND_FILE_DIRECTORY_INFO:
1099 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1100 p += 4;
1101 SIVAL(p,0,reskey); p += 4;
1102 put_long_date(p,cdate); p += 8;
1103 put_long_date(p,adate); p += 8;
1104 put_long_date(p,mdate); p += 8;
1105 put_long_date(p,mdate); p += 8;
1106 SOFF_T(p,0,file_size); p += 8;
1107 SOFF_T(p,0,allocation_size); p += 8;
1108 SIVAL(p,0,nt_extmode); p += 4;
1109 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1110 SIVAL(p,0,len);
1111 p += 4 + len;
1112 len = PTR_DIFF(p, pdata);
1113 len = (len + 3) & ~3;
1114 SIVAL(pdata,0,len);
1115 p = pdata + len;
1116 break;
1118 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1119 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1120 p += 4;
1121 SIVAL(p,0,reskey); p += 4;
1122 put_long_date(p,cdate); p += 8;
1123 put_long_date(p,adate); p += 8;
1124 put_long_date(p,mdate); p += 8;
1125 put_long_date(p,mdate); p += 8;
1126 SOFF_T(p,0,file_size); p += 8;
1127 SOFF_T(p,0,allocation_size); p += 8;
1128 SIVAL(p,0,nt_extmode); p += 4;
1129 q = p; p += 4; /* q is placeholder for name length. */
1131 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1132 SIVAL(p,0,ea_size); /* Extended attributes */
1133 p +=4;
1135 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1136 SIVAL(q, 0, len);
1137 p += len;
1139 len = PTR_DIFF(p, pdata);
1140 len = (len + 3) & ~3;
1141 SIVAL(pdata,0,len);
1142 p = pdata + len;
1143 break;
1145 case SMB_FIND_FILE_NAMES_INFO:
1146 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1147 p += 4;
1148 SIVAL(p,0,reskey); p += 4;
1149 p += 4;
1150 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1151 acl on a dir (tridge) */
1152 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1153 SIVAL(p, -4, len);
1154 p += len;
1155 len = PTR_DIFF(p, pdata);
1156 len = (len + 3) & ~3;
1157 SIVAL(pdata,0,len);
1158 p = pdata + len;
1159 break;
1161 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1162 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1163 p += 4;
1164 SIVAL(p,0,reskey); p += 4;
1165 put_long_date(p,cdate); p += 8;
1166 put_long_date(p,adate); p += 8;
1167 put_long_date(p,mdate); p += 8;
1168 put_long_date(p,mdate); p += 8;
1169 SOFF_T(p,0,file_size); p += 8;
1170 SOFF_T(p,0,allocation_size); p += 8;
1171 SIVAL(p,0,nt_extmode); p += 4;
1172 q = p; p += 4; /* q is placeholder for name length. */
1174 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1175 SIVAL(p,0,ea_size); /* Extended attributes */
1176 p +=4;
1178 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1179 SIVAL(p,0,sbuf.st_dev); p += 4;
1180 SIVAL(p,0,sbuf.st_ino); p += 4;
1181 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1182 SIVAL(q, 0, len);
1183 p += len;
1184 len = PTR_DIFF(p, pdata);
1185 len = (len + 3) & ~3;
1186 SIVAL(pdata,0,len);
1187 p = pdata + len;
1188 break;
1190 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1191 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1192 was_8_3 = mangle_is_8_3(fname, True);
1193 p += 4;
1194 SIVAL(p,0,reskey); p += 4;
1195 put_long_date(p,cdate); p += 8;
1196 put_long_date(p,adate); p += 8;
1197 put_long_date(p,mdate); p += 8;
1198 put_long_date(p,mdate); p += 8;
1199 SOFF_T(p,0,file_size); p += 8;
1200 SOFF_T(p,0,allocation_size); p += 8;
1201 SIVAL(p,0,nt_extmode); p += 4;
1202 q = p; p += 4; /* q is placeholder for name length */
1204 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1205 SIVAL(p,0,ea_size); /* Extended attributes */
1206 p +=4;
1208 /* Clear the short name buffer. This is
1209 * IMPORTANT as not doing so will trigger
1210 * a Win2k client bug. JRA.
1212 memset(p,'\0',26);
1213 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1214 pstring mangled_name;
1215 pstrcpy(mangled_name, fname);
1216 mangle_map(mangled_name,True,True,SNUM(conn));
1217 mangled_name[12] = 0;
1218 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1219 SSVAL(p, 0, len);
1220 } else {
1221 SSVAL(p,0,0);
1222 *(p+2) = 0;
1224 p += 26;
1225 SSVAL(p,0,0); p += 2; /* Reserved ? */
1226 SIVAL(p,0,sbuf.st_dev); p += 4;
1227 SIVAL(p,0,sbuf.st_ino); p += 4;
1228 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1229 SIVAL(q,0,len);
1230 p += len;
1231 len = PTR_DIFF(p, pdata);
1232 len = (len + 3) & ~3;
1233 SIVAL(pdata,0,len);
1234 p = pdata + len;
1235 break;
1237 /* CIFS UNIX Extension. */
1239 case SMB_FIND_FILE_UNIX:
1240 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1241 p+= 4;
1242 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1244 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1245 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1246 p+= 8;
1248 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1249 p+= 8;
1251 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1252 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1253 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1254 p+= 24;
1256 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1257 SIVAL(p,4,0);
1258 p+= 8;
1260 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1261 SIVAL(p,4,0);
1262 p+= 8;
1264 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1265 p+= 4;
1267 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1268 SIVAL(p,4,0);
1269 p+= 8;
1271 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1272 SIVAL(p,4,0);
1273 p+= 8;
1275 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1276 p+= 8;
1278 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1279 SIVAL(p,4,0);
1280 p+= 8;
1282 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1283 SIVAL(p,4,0);
1284 p+= 8;
1286 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1287 p += len;
1289 len = PTR_DIFF(p, pdata);
1290 len = (len + 3) & ~3;
1291 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1292 p = pdata + len;
1293 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1295 break;
1297 default:
1298 return(False);
1302 if (PTR_DIFF(p,pdata) > space_remaining) {
1303 /* Move the dirptr back to prev_dirpos */
1304 SeekDir(conn->dirptr, prev_dirpos);
1305 *out_of_space = True;
1306 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1307 return False; /* Not finished - just out of space */
1310 /* Setup the last_filename pointer, as an offset from base_data */
1311 *last_name_off = PTR_DIFF(nameptr,base_data);
1312 /* Advance the data pointer to the next slot */
1313 *ppdata = p;
1315 return(found);
1318 /****************************************************************************
1319 Reply to a TRANS2_FINDFIRST.
1320 ****************************************************************************/
1322 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1323 char **pparams, int total_params, char **ppdata, int total_data)
1325 /* We must be careful here that we don't return more than the
1326 allowed number of data bytes. If this means returning fewer than
1327 maxentries then so be it. We assume that the redirector has
1328 enough room for the fixed number of parameter bytes it has
1329 requested. */
1330 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1331 char *params = *pparams;
1332 char *pdata = *ppdata;
1333 int dirtype = SVAL(params,0);
1334 int maxentries = SVAL(params,2);
1335 BOOL close_after_first = BITSETW(params+4,0);
1336 BOOL close_if_end = BITSETW(params+4,1);
1337 BOOL requires_resume_key = BITSETW(params+4,2);
1338 int info_level = SVAL(params,6);
1339 pstring directory;
1340 pstring mask;
1341 char *p, *wcard;
1342 int last_name_off=0;
1343 int dptr_num = -1;
1344 int numentries = 0;
1345 int i;
1346 BOOL finished = False;
1347 BOOL dont_descend = False;
1348 BOOL out_of_space = False;
1349 int space_remaining;
1350 BOOL bad_path = False;
1351 SMB_STRUCT_STAT sbuf;
1352 NTSTATUS ntstatus = NT_STATUS_OK;
1354 if (total_params < 12)
1355 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1357 *directory = *mask = 0;
1359 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1360 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1361 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1362 info_level, max_data_bytes));
1364 switch (info_level) {
1365 case SMB_INFO_STANDARD:
1366 case SMB_INFO_QUERY_EA_SIZE:
1367 case SMB_FIND_FILE_DIRECTORY_INFO:
1368 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1369 case SMB_FIND_FILE_NAMES_INFO:
1370 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1371 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1372 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1373 break;
1374 case SMB_FIND_FILE_UNIX:
1375 if (!lp_unix_extensions())
1376 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1377 break;
1378 default:
1379 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1382 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1383 if (!NT_STATUS_IS_OK(ntstatus)) {
1384 return ERROR_NT(ntstatus);
1387 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1389 unix_convert(directory,conn,0,&bad_path,&sbuf);
1390 if (bad_path) {
1391 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1393 if(!check_name(directory,conn)) {
1394 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1397 p = strrchr_m(directory,'/');
1398 if(p == NULL) {
1399 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1400 if((directory[0] == '.') && (directory[1] == '\0'))
1401 pstrcpy(mask,"*");
1402 else
1403 pstrcpy(mask,directory);
1404 pstrcpy(directory,"./");
1405 } else {
1406 pstrcpy(mask,p+1);
1407 *p = 0;
1410 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1412 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1413 if( pdata == NULL )
1414 return(ERROR_DOS(ERRDOS,ERRnomem));
1416 *ppdata = pdata;
1417 memset((char *)pdata,'\0',max_data_bytes + 1024);
1419 /* Realloc the params space */
1420 params = Realloc(*pparams, 10);
1421 if (params == NULL)
1422 return ERROR_DOS(ERRDOS,ERRnomem);
1423 *pparams = params;
1425 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1426 if (dptr_num < 0)
1427 return(UNIXERROR(ERRDOS,ERRbadfile));
1429 /* Save the wildcard match and attribs we are using on this directory -
1430 needed as lanman2 assumes these are being saved between calls */
1432 if(!(wcard = strdup(mask))) {
1433 dptr_close(&dptr_num);
1434 return ERROR_DOS(ERRDOS,ERRnomem);
1437 dptr_set_wcard(dptr_num, wcard);
1438 dptr_set_attr(dptr_num, dirtype);
1440 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1442 /* We don't need to check for VOL here as this is returned by
1443 a different TRANS2 call. */
1445 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1446 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1447 dont_descend = True;
1449 p = pdata;
1450 space_remaining = max_data_bytes;
1451 out_of_space = False;
1453 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1454 BOOL got_exact_match = False;
1456 /* this is a heuristic to avoid seeking the dirptr except when
1457 absolutely necessary. It allows for a filename of about 40 chars */
1458 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1459 out_of_space = True;
1460 finished = False;
1461 } else {
1462 finished = !get_lanman2_dir_entry(conn,
1463 inbuf, outbuf,
1464 mask,dirtype,info_level,
1465 requires_resume_key,dont_descend,
1466 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1467 &last_name_off);
1470 if (finished && out_of_space)
1471 finished = False;
1473 if (!finished && !out_of_space)
1474 numentries++;
1477 * As an optimisation if we know we aren't looking
1478 * for a wildcard name (ie. the name matches the wildcard exactly)
1479 * then we can finish on any (first) match.
1480 * This speeds up large directory searches. JRA.
1483 if(got_exact_match)
1484 finished = True;
1486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1489 /* Check if we can close the dirptr */
1490 if(close_after_first || (finished && close_if_end)) {
1491 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1492 dptr_close(&dptr_num);
1496 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1497 * from observation of NT.
1500 if(numentries == 0) {
1501 dptr_close(&dptr_num);
1502 return ERROR_DOS(ERRDOS,ERRbadfile);
1505 /* At this point pdata points to numentries directory entries. */
1507 /* Set up the return parameter block */
1508 SSVAL(params,0,dptr_num);
1509 SSVAL(params,2,numentries);
1510 SSVAL(params,4,finished);
1511 SSVAL(params,6,0); /* Never an EA error */
1512 SSVAL(params,8,last_name_off);
1514 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1516 if ((! *directory) && dptr_path(dptr_num))
1517 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1519 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1520 smb_fn_name(CVAL(inbuf,smb_com)),
1521 mask, directory, dirtype, numentries ) );
1524 * Force a name mangle here to ensure that the
1525 * mask as an 8.3 name is top of the mangled cache.
1526 * The reasons for this are subtle. Don't remove
1527 * this code unless you know what you are doing
1528 * (see PR#13758). JRA.
1531 if(!mangle_is_8_3_wildcards( mask, False))
1532 mangle_map(mask, True, True, SNUM(conn));
1534 return(-1);
1537 /****************************************************************************
1538 Reply to a TRANS2_FINDNEXT.
1539 ****************************************************************************/
1541 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1542 char **pparams, int total_params, char **ppdata, int total_data)
1544 /* We must be careful here that we don't return more than the
1545 allowed number of data bytes. If this means returning fewer than
1546 maxentries then so be it. We assume that the redirector has
1547 enough room for the fixed number of parameter bytes it has
1548 requested. */
1549 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1550 char *params = *pparams;
1551 char *pdata = *ppdata;
1552 int dptr_num = SVAL(params,0);
1553 int maxentries = SVAL(params,2);
1554 uint16 info_level = SVAL(params,4);
1555 uint32 resume_key = IVAL(params,6);
1556 BOOL close_after_request = BITSETW(params+10,0);
1557 BOOL close_if_end = BITSETW(params+10,1);
1558 BOOL requires_resume_key = BITSETW(params+10,2);
1559 BOOL continue_bit = BITSETW(params+10,3);
1560 pstring resume_name;
1561 pstring mask;
1562 pstring directory;
1563 char *p;
1564 uint16 dirtype;
1565 int numentries = 0;
1566 int i, last_name_off=0;
1567 BOOL finished = False;
1568 BOOL dont_descend = False;
1569 BOOL out_of_space = False;
1570 int space_remaining;
1571 NTSTATUS ntstatus = NT_STATUS_OK;
1573 if (total_params < 12)
1574 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1576 *mask = *directory = *resume_name = 0;
1578 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1579 if (!NT_STATUS_IS_OK(ntstatus)) {
1580 return ERROR_NT(ntstatus);
1583 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1584 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1585 resume_key = %d resume name = %s continue=%d level = %d\n",
1586 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1587 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1589 switch (info_level) {
1590 case SMB_INFO_STANDARD:
1591 case SMB_INFO_QUERY_EA_SIZE:
1592 case SMB_FIND_FILE_DIRECTORY_INFO:
1593 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1594 case SMB_FIND_FILE_NAMES_INFO:
1595 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1596 break;
1597 case SMB_FIND_FILE_UNIX:
1598 if (!lp_unix_extensions())
1599 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1600 break;
1601 default:
1602 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1605 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1606 if(pdata == NULL)
1607 return ERROR_DOS(ERRDOS,ERRnomem);
1609 *ppdata = pdata;
1610 memset((char *)pdata,'\0',max_data_bytes + 1024);
1612 /* Realloc the params space */
1613 params = Realloc(*pparams, 6*SIZEOFWORD);
1614 if( params == NULL )
1615 return ERROR_DOS(ERRDOS,ERRnomem);
1617 *pparams = params;
1619 /* Check that the dptr is valid */
1620 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1621 return ERROR_DOS(ERRDOS,ERRnofiles);
1623 string_set(&conn->dirpath,dptr_path(dptr_num));
1625 /* Get the wildcard mask from the dptr */
1626 if((p = dptr_wcard(dptr_num))== NULL) {
1627 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1628 return ERROR_DOS(ERRDOS,ERRnofiles);
1631 pstrcpy(mask, p);
1632 pstrcpy(directory,conn->dirpath);
1634 /* Get the attr mask from the dptr */
1635 dirtype = dptr_attr(dptr_num);
1637 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1638 dptr_num, mask, dirtype,
1639 (long)conn->dirptr,
1640 TellDir(conn->dirptr)));
1642 /* We don't need to check for VOL here as this is returned by
1643 a different TRANS2 call. */
1645 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1646 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1647 dont_descend = True;
1649 p = pdata;
1650 space_remaining = max_data_bytes;
1651 out_of_space = False;
1654 * Seek to the correct position. We no longer use the resume key but
1655 * depend on the last file name instead.
1658 if(requires_resume_key && *resume_name && !continue_bit) {
1661 * Fix for NT redirector problem triggered by resume key indexes
1662 * changing between directory scans. We now return a resume key of 0
1663 * and instead look for the filename to continue from (also given
1664 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1665 * findfirst/findnext (as is usual) then the directory pointer
1666 * should already be at the correct place. Check this by scanning
1667 * backwards looking for an exact (ie. case sensitive) filename match.
1668 * If we get to the beginning of the directory and haven't found it then scan
1669 * forwards again looking for a match. JRA.
1672 int current_pos, start_pos;
1673 const char *dname = NULL;
1674 pstring dname_pstring;
1675 void *dirptr = conn->dirptr;
1676 start_pos = TellDir(dirptr);
1677 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1678 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1680 SeekDir(dirptr, current_pos);
1681 dname = ReadDirName(dirptr);
1682 if (dname) {
1684 * Remember, mangle_map is called by
1685 * get_lanman2_dir_entry(), so the resume name
1686 * could be mangled. Ensure we do the same
1687 * here.
1690 /* make sure we get a copy that mangle_map can modify */
1692 pstrcpy(dname_pstring, dname);
1693 mangle_map( dname_pstring, False, True, SNUM(conn));
1695 if(strcsequal( resume_name, dname_pstring)) {
1696 SeekDir(dirptr, current_pos+1);
1697 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1698 break;
1704 * Scan forward from start if not found going backwards.
1707 if(current_pos < 0) {
1708 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1709 SeekDir(dirptr, start_pos);
1710 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1713 * Remember, mangle_map is called by
1714 * get_lanman2_dir_entry(), so the resume name
1715 * could be mangled. Ensure we do the same
1716 * here.
1719 if(dname) {
1720 /* make sure we get a copy that mangle_map can modify */
1722 pstrcpy(dname_pstring, dname);
1723 mangle_map(dname_pstring, False, True, SNUM(conn));
1725 if(strcsequal( resume_name, dname_pstring)) {
1726 SeekDir(dirptr, current_pos+1);
1727 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1728 break;
1731 } /* end for */
1732 } /* end if current_pos */
1733 } /* end if requires_resume_key && !continue_bit */
1735 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1736 BOOL got_exact_match = False;
1738 /* this is a heuristic to avoid seeking the dirptr except when
1739 absolutely necessary. It allows for a filename of about 40 chars */
1740 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1741 out_of_space = True;
1742 finished = False;
1743 } else {
1744 finished = !get_lanman2_dir_entry(conn,
1745 inbuf, outbuf,
1746 mask,dirtype,info_level,
1747 requires_resume_key,dont_descend,
1748 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1749 &last_name_off);
1752 if (finished && out_of_space)
1753 finished = False;
1755 if (!finished && !out_of_space)
1756 numentries++;
1759 * As an optimisation if we know we aren't looking
1760 * for a wildcard name (ie. the name matches the wildcard exactly)
1761 * then we can finish on any (first) match.
1762 * This speeds up large directory searches. JRA.
1765 if(got_exact_match)
1766 finished = True;
1768 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1771 /* Check if we can close the dirptr */
1772 if(close_after_request || (finished && close_if_end)) {
1773 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1774 dptr_close(&dptr_num); /* This frees up the saved mask */
1777 /* Set up the return parameter block */
1778 SSVAL(params,0,numentries);
1779 SSVAL(params,2,finished);
1780 SSVAL(params,4,0); /* Never an EA error */
1781 SSVAL(params,6,last_name_off);
1783 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1785 if ((! *directory) && dptr_path(dptr_num))
1786 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1788 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1789 smb_fn_name(CVAL(inbuf,smb_com)),
1790 mask, directory, dirtype, numentries ) );
1792 return(-1);
1795 /****************************************************************************
1796 Reply to a TRANS2_QFSINFO (query filesystem info).
1797 ****************************************************************************/
1799 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1800 int length, int bufsize,
1801 char **pparams, int total_params, char **ppdata, int total_data)
1803 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1804 char *pdata = *ppdata;
1805 char *params = *pparams;
1806 uint16 info_level = SVAL(params,0);
1807 int data_len, len;
1808 SMB_STRUCT_STAT st;
1809 char *vname = volume_label(SNUM(conn));
1810 int snum = SNUM(conn);
1811 char *fstype = lp_fstype(SNUM(conn));
1812 int quota_flag = 0;
1814 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1816 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1817 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1818 return ERROR_DOS(ERRSRV,ERRinvdevice);
1821 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1822 if ( pdata == NULL )
1823 return ERROR_DOS(ERRDOS,ERRnomem);
1825 *ppdata = pdata;
1826 memset((char *)pdata,'\0',max_data_bytes + 1024);
1828 switch (info_level) {
1829 case SMB_INFO_ALLOCATION:
1831 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1832 data_len = 18;
1833 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1834 block_size = lp_block_size(snum);
1835 if (bsize < block_size) {
1836 SMB_BIG_UINT factor = block_size/bsize;
1837 bsize = block_size;
1838 dsize /= factor;
1839 dfree /= factor;
1841 if (bsize > block_size) {
1842 SMB_BIG_UINT factor = bsize/block_size;
1843 bsize = block_size;
1844 dsize *= factor;
1845 dfree *= factor;
1847 bytes_per_sector = 512;
1848 sectors_per_unit = bsize/bytes_per_sector;
1850 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1851 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1852 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1854 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1855 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1856 SIVAL(pdata,l1_cUnit,dsize);
1857 SIVAL(pdata,l1_cUnitAvail,dfree);
1858 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1859 break;
1862 case SMB_INFO_VOLUME:
1863 /* Return volume name */
1865 * Add volume serial number - hash of a combination of
1866 * the called hostname and the service name.
1868 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1869 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1870 SCVAL(pdata,l2_vol_cch,len);
1871 data_len = l2_vol_szVolLabel + len;
1872 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1873 (unsigned)st.st_ctime, len, vname));
1874 break;
1876 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1877 case SMB_FS_ATTRIBUTE_INFORMATION:
1880 #if defined(HAVE_SYS_QUOTAS)
1881 quota_flag = FILE_VOLUME_QUOTAS;
1882 #endif
1884 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1885 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1886 quota_flag); /* FS ATTRIBUTES */
1888 SIVAL(pdata,4,255); /* Max filename component length */
1889 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1890 and will think we can't do long filenames */
1891 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1892 SIVAL(pdata,8,len);
1893 data_len = 12 + len;
1894 break;
1896 case SMB_QUERY_FS_LABEL_INFO:
1897 case SMB_FS_LABEL_INFORMATION:
1898 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1899 data_len = 4 + len;
1900 SIVAL(pdata,0,len);
1901 break;
1903 case SMB_QUERY_FS_VOLUME_INFO:
1904 case SMB_FS_VOLUME_INFORMATION:
1907 * Add volume serial number - hash of a combination of
1908 * the called hostname and the service name.
1910 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1911 (str_checksum(local_machine)<<16));
1913 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1914 SIVAL(pdata,12,len);
1915 data_len = 18+len;
1916 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1917 (int)strlen(vname),vname, lp_servicename(snum)));
1918 break;
1920 case SMB_QUERY_FS_SIZE_INFO:
1921 case SMB_FS_SIZE_INFORMATION:
1923 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1924 data_len = 24;
1925 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1926 block_size = lp_block_size(snum);
1927 if (bsize < block_size) {
1928 SMB_BIG_UINT factor = block_size/bsize;
1929 bsize = block_size;
1930 dsize /= factor;
1931 dfree /= factor;
1933 if (bsize > block_size) {
1934 SMB_BIG_UINT factor = bsize/block_size;
1935 bsize = block_size;
1936 dsize *= factor;
1937 dfree *= factor;
1939 bytes_per_sector = 512;
1940 sectors_per_unit = bsize/bytes_per_sector;
1941 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1942 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1943 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1944 SBIG_UINT(pdata,0,dsize);
1945 SBIG_UINT(pdata,8,dfree);
1946 SIVAL(pdata,16,sectors_per_unit);
1947 SIVAL(pdata,20,bytes_per_sector);
1948 break;
1951 case SMB_FS_FULL_SIZE_INFORMATION:
1953 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1954 data_len = 32;
1955 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1956 block_size = lp_block_size(snum);
1957 if (bsize < block_size) {
1958 SMB_BIG_UINT factor = block_size/bsize;
1959 bsize = block_size;
1960 dsize /= factor;
1961 dfree /= factor;
1963 if (bsize > block_size) {
1964 SMB_BIG_UINT factor = bsize/block_size;
1965 bsize = block_size;
1966 dsize *= factor;
1967 dfree *= factor;
1969 bytes_per_sector = 512;
1970 sectors_per_unit = bsize/bytes_per_sector;
1971 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1972 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1973 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1974 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1975 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1976 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1977 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1978 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1979 break;
1982 case SMB_QUERY_FS_DEVICE_INFO:
1983 case SMB_FS_DEVICE_INFORMATION:
1984 data_len = 8;
1985 SIVAL(pdata,0,0); /* dev type */
1986 SIVAL(pdata,4,0); /* characteristics */
1987 break;
1989 #ifdef HAVE_SYS_QUOTAS
1990 case SMB_FS_QUOTA_INFORMATION:
1992 * what we have to send --metze:
1994 * Unknown1: 24 NULL bytes
1995 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1996 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1997 * Quota Flags: 2 byte :
1998 * Unknown3: 6 NULL bytes
2000 * 48 bytes total
2002 * details for Quota Flags:
2004 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2005 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2006 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2007 * 0x0001 Enable Quotas: enable quota for this fs
2011 /* we need to fake up a fsp here,
2012 * because its not send in this call
2014 files_struct fsp;
2015 SMB_NTQUOTA_STRUCT quotas;
2017 ZERO_STRUCT(fsp);
2018 ZERO_STRUCT(quotas);
2020 fsp.conn = conn;
2021 fsp.fnum = -1;
2022 fsp.fd = -1;
2024 /* access check */
2025 if (current_user.uid != 0) {
2026 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2027 lp_servicename(SNUM(conn)),conn->user));
2028 return ERROR_DOS(ERRDOS,ERRnoaccess);
2031 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2032 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2033 return ERROR_DOS(ERRSRV,ERRerror);
2036 data_len = 48;
2038 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2040 /* Unknown1 24 NULL bytes*/
2041 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2042 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2043 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2045 /* Default Soft Quota 8 bytes */
2046 SBIG_UINT(pdata,24,quotas.softlim);
2048 /* Default Hard Quota 8 bytes */
2049 SBIG_UINT(pdata,32,quotas.hardlim);
2051 /* Quota flag 2 bytes */
2052 SSVAL(pdata,40,quotas.qflags);
2054 /* Unknown3 6 NULL bytes */
2055 SSVAL(pdata,42,0);
2056 SIVAL(pdata,44,0);
2058 break;
2060 #endif /* HAVE_SYS_QUOTAS */
2061 case SMB_FS_OBJECTID_INFORMATION:
2062 data_len = 64;
2063 break;
2066 * Query the version and capabilities of the CIFS UNIX extensions
2067 * in use.
2070 case SMB_QUERY_CIFS_UNIX_INFO:
2071 if (!lp_unix_extensions())
2072 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2073 data_len = 12;
2074 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2075 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2076 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2077 break;
2079 case SMB_MAC_QUERY_FS_INFO:
2081 * Thursby MAC extension... ONLY on NTFS filesystems
2082 * once we do streams then we don't need this
2084 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2085 data_len = 88;
2086 SIVAL(pdata,84,0x100); /* Don't support mac... */
2087 break;
2089 /* drop through */
2090 default:
2091 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2095 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2097 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2099 return -1;
2102 #ifdef HAVE_SYS_QUOTAS
2103 /****************************************************************************
2104 Reply to a TRANS2_SETFSINFO (set filesystem info).
2105 ****************************************************************************/
2107 static int call_trans2setfsinfo(connection_struct *conn,
2108 char *inbuf, char *outbuf, int length, int bufsize,
2109 char **pparams, int total_params, char **ppdata, int total_data)
2111 char *pdata = *ppdata;
2112 char *params = *pparams;
2113 files_struct *fsp = NULL;
2114 uint16 info_level;
2115 int outsize;
2116 SMB_NTQUOTA_STRUCT quotas;
2118 ZERO_STRUCT(quotas);
2120 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2122 /* access check */
2123 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2124 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2125 lp_servicename(SNUM(conn)),conn->user));
2126 return ERROR_DOS(ERRSRV,ERRaccess);
2129 /* */
2130 if (total_params < 4) {
2131 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2132 total_params));
2133 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2136 fsp = file_fsp(params,0);
2138 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2139 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2140 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2143 info_level = SVAL(params,2);
2145 switch(info_level) {
2146 case SMB_FS_QUOTA_INFORMATION:
2147 /* note: normaly there're 48 bytes,
2148 * but we didn't use the last 6 bytes for now
2149 * --metze
2151 if (total_data < 42) {
2152 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2153 total_data));
2154 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2157 /* unknown_1 24 NULL bytes in pdata*/
2159 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2160 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2161 #ifdef LARGE_SMB_OFF_T
2162 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2163 #else /* LARGE_SMB_OFF_T */
2164 if ((IVAL(pdata,28) != 0)&&
2165 ((quotas.softlim != 0xFFFFFFFF)||
2166 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2167 /* more than 32 bits? */
2168 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2170 #endif /* LARGE_SMB_OFF_T */
2172 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2173 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2174 #ifdef LARGE_SMB_OFF_T
2175 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2176 #else /* LARGE_SMB_OFF_T */
2177 if ((IVAL(pdata,36) != 0)&&
2178 ((quotas.hardlim != 0xFFFFFFFF)||
2179 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2180 /* more than 32 bits? */
2181 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2183 #endif /* LARGE_SMB_OFF_T */
2185 /* quota_flags 2 bytes **/
2186 quotas.qflags = SVAL(pdata,40);
2188 /* unknown_2 6 NULL bytes follow*/
2190 /* now set the quotas */
2191 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2192 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2193 return ERROR_DOS(ERRSRV,ERRerror);
2196 break;
2197 default:
2198 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2199 info_level));
2200 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2201 break;
2205 * sending this reply works fine,
2206 * but I'm not sure it's the same
2207 * like windows do...
2208 * --metze
2210 outsize = set_message(outbuf,10,0,True);
2212 return outsize;
2214 #endif /* HAVE_SYS_QUOTAS */
2216 /****************************************************************************
2217 * Utility function to set bad path error.
2218 ****************************************************************************/
2220 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2222 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2223 err, (int)bad_path ));
2225 if(err == ENOENT) {
2226 if (bad_path) {
2227 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2228 } else {
2229 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2232 return UNIXERROR(def_class,def_code);
2235 /****************************************************************************
2236 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2237 file name or file id).
2238 ****************************************************************************/
2240 static int call_trans2qfilepathinfo(connection_struct *conn,
2241 char *inbuf, char *outbuf, int length,
2242 int bufsize,
2243 char **pparams, int total_params, char **ppdata, int total_data)
2245 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2246 char *params = *pparams;
2247 char *pdata = *ppdata;
2248 uint16 tran_call = SVAL(inbuf, smb_setup0);
2249 uint16 info_level;
2250 int mode=0;
2251 SMB_OFF_T file_size=0;
2252 SMB_BIG_UINT allocation_size=0;
2253 unsigned int data_size;
2254 unsigned int param_size = 2;
2255 SMB_STRUCT_STAT sbuf;
2256 pstring fname, dos_fname;
2257 char *fullpathname;
2258 char *base_name;
2259 char *p;
2260 SMB_OFF_T pos = 0;
2261 BOOL bad_path = False;
2262 BOOL delete_pending = False;
2263 int len;
2264 time_t c_time;
2265 files_struct *fsp = NULL;
2266 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2268 if (!params)
2269 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2271 ZERO_STRUCT(sbuf);
2273 if (tran_call == TRANSACT2_QFILEINFO) {
2274 if (total_params < 4)
2275 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2277 fsp = file_fsp(params,0);
2278 info_level = SVAL(params,2);
2280 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2282 if(fsp && (fsp->fake_file_handle)) {
2284 * This is actually for the QUOTA_FAKE_FILE --metze
2287 pstrcpy(fname, fsp->fsp_name);
2288 /* We know this name is ok, it's already passed the checks. */
2290 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2292 * This is actually a QFILEINFO on a directory
2293 * handle (returned from an NT SMB). NT5.0 seems
2294 * to do this call. JRA.
2296 /* We know this name is ok, it's already passed the checks. */
2297 pstrcpy(fname, fsp->fsp_name);
2299 if (INFO_LEVEL_IS_UNIX(info_level)) {
2300 /* Always do lstat for UNIX calls. */
2301 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2302 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2303 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2305 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2306 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2307 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2310 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2311 } else {
2313 * Original code - this is an open file.
2315 CHECK_FSP(fsp,conn);
2317 pstrcpy(fname, fsp->fsp_name);
2318 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2319 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2320 return(UNIXERROR(ERRDOS,ERRbadfid));
2322 pos = fsp->position_information;
2323 delete_pending = fsp->delete_on_close;
2324 desired_access = fsp->desired_access;
2326 } else {
2327 NTSTATUS status = NT_STATUS_OK;
2329 /* qpathinfo */
2330 if (total_params < 6)
2331 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2333 info_level = SVAL(params,0);
2335 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2337 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 return ERROR_NT(status);
2342 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2344 unix_convert(fname,conn,0,&bad_path,&sbuf);
2345 if (bad_path) {
2346 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2348 if (!check_name(fname,conn)) {
2349 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2350 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2353 if (INFO_LEVEL_IS_UNIX(info_level)) {
2354 /* Always do lstat for UNIX calls. */
2355 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2356 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2357 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2359 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2360 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2361 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2365 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2366 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2368 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2369 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2371 p = strrchr_m(fname,'/');
2372 if (!p)
2373 base_name = fname;
2374 else
2375 base_name = p+1;
2377 mode = dos_mode(conn,fname,&sbuf);
2378 if (!mode)
2379 mode = FILE_ATTRIBUTE_NORMAL;
2381 fullpathname = fname;
2382 file_size = get_file_size(sbuf);
2383 allocation_size = get_allocation_size(fsp,&sbuf);
2384 if (mode & aDIR)
2385 file_size = 0;
2387 params = Realloc(*pparams,2);
2388 if (params == NULL)
2389 return ERROR_DOS(ERRDOS,ERRnomem);
2390 *pparams = params;
2391 memset((char *)params,'\0',2);
2392 data_size = max_data_bytes + 1024;
2393 pdata = Realloc(*ppdata, data_size);
2394 if ( pdata == NULL )
2395 return ERROR_DOS(ERRDOS,ERRnomem);
2396 *ppdata = pdata;
2398 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2399 /* uggh, EAs for OS2 */
2400 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2401 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2404 memset((char *)pdata,'\0',data_size);
2406 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2408 if (lp_dos_filetime_resolution(SNUM(conn))) {
2409 c_time &= ~1;
2410 sbuf.st_atime &= ~1;
2411 sbuf.st_ctime &= ~1;
2412 sbuf.st_mtime &= ~1;
2415 /* NT expects the name to be in an exact form of the *full*
2416 filename. See the trans2 torture test */
2417 if (strequal(base_name,".")) {
2418 pstrcpy(dos_fname, "\\");
2419 } else {
2420 pstr_sprintf(dos_fname, "\\%s", fname);
2421 string_replace(dos_fname, '/', '\\');
2424 switch (info_level) {
2425 case SMB_INFO_STANDARD:
2426 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2427 data_size = 22;
2428 put_dos_date2(pdata,l1_fdateCreation,c_time);
2429 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2430 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2431 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2432 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2433 SSVAL(pdata,l1_attrFile,mode);
2434 break;
2436 case SMB_INFO_QUERY_EA_SIZE:
2438 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2439 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2440 data_size = 26;
2441 put_dos_date2(pdata,l1_fdateCreation,c_time);
2442 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2443 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2444 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2445 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2446 SSVAL(pdata,l1_attrFile,mode);
2447 SIVAL(pdata,l1_attrFile+2,ea_size);
2448 break;
2451 case SMB_INFO_IS_NAME_VALID:
2452 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2453 if (tran_call == TRANSACT2_QFILEINFO) {
2454 /* os/2 needs this ? really ?*/
2455 return ERROR_DOS(ERRDOS,ERRbadfunc);
2457 data_size = 0;
2458 param_size = 0;
2459 break;
2461 case SMB_INFO_QUERY_EAS_FROM_LIST:
2462 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2463 data_size = 24;
2464 put_dos_date2(pdata,0,c_time);
2465 put_dos_date2(pdata,4,sbuf.st_atime);
2466 put_dos_date2(pdata,8,sbuf.st_mtime);
2467 SIVAL(pdata,12,(uint32)file_size);
2468 SIVAL(pdata,16,(uint32)allocation_size);
2469 SIVAL(pdata,20,mode);
2470 break;
2472 case SMB_INFO_QUERY_ALL_EAS:
2473 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2474 /* We have data_size bytes to put EA's into. */
2475 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2476 break;
2478 case SMB_FILE_BASIC_INFORMATION:
2479 case SMB_QUERY_FILE_BASIC_INFO:
2481 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2482 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2483 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2484 } else {
2485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2486 data_size = 40;
2487 SIVAL(pdata,36,0);
2489 put_long_date(pdata,c_time);
2490 put_long_date(pdata+8,sbuf.st_atime);
2491 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2492 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2493 SIVAL(pdata,32,mode);
2495 DEBUG(5,("SMB_QFBI - "));
2497 time_t create_time = c_time;
2498 DEBUG(5,("create: %s ", ctime(&create_time)));
2500 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2501 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2502 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2503 DEBUG(5,("mode: %x\n", mode));
2505 break;
2507 case SMB_FILE_STANDARD_INFORMATION:
2508 case SMB_QUERY_FILE_STANDARD_INFO:
2510 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2511 data_size = 24;
2512 SOFF_T(pdata,0,allocation_size);
2513 SOFF_T(pdata,8,file_size);
2514 if (delete_pending & sbuf.st_nlink)
2515 SIVAL(pdata,16,sbuf.st_nlink - 1);
2516 else
2517 SIVAL(pdata,16,sbuf.st_nlink);
2518 SCVAL(pdata,20,0);
2519 SCVAL(pdata,21,(mode&aDIR)?1:0);
2520 break;
2522 case SMB_FILE_EA_INFORMATION:
2523 case SMB_QUERY_FILE_EA_INFO:
2525 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2526 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2527 data_size = 4;
2528 SIVAL(pdata,0,ea_size);
2529 break;
2532 /* Get the 8.3 name - used if NT SMB was negotiated. */
2533 case SMB_QUERY_FILE_ALT_NAME_INFO:
2534 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2536 pstring short_name;
2538 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2539 pstrcpy(short_name,base_name);
2540 /* Mangle if not already 8.3 */
2541 if(!mangle_is_8_3(short_name, True)) {
2542 mangle_map(short_name,True,True,SNUM(conn));
2544 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2545 data_size = 4 + len;
2546 SIVAL(pdata,0,len);
2547 break;
2550 case SMB_QUERY_FILE_NAME_INFO:
2552 this must be *exactly* right for ACLs on mapped drives to work
2554 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2555 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2556 data_size = 4 + len;
2557 SIVAL(pdata,0,len);
2558 break;
2560 case SMB_FILE_ALLOCATION_INFORMATION:
2561 case SMB_QUERY_FILE_ALLOCATION_INFO:
2562 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2563 data_size = 8;
2564 SOFF_T(pdata,0,allocation_size);
2565 break;
2567 case SMB_FILE_END_OF_FILE_INFORMATION:
2568 case SMB_QUERY_FILE_END_OF_FILEINFO:
2569 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2570 data_size = 8;
2571 SOFF_T(pdata,0,file_size);
2572 break;
2574 case SMB_QUERY_FILE_ALL_INFO:
2575 case SMB_FILE_ALL_INFORMATION:
2577 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2578 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2579 put_long_date(pdata,c_time);
2580 put_long_date(pdata+8,sbuf.st_atime);
2581 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2582 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2583 SIVAL(pdata,32,mode);
2584 pdata += 40;
2585 SOFF_T(pdata,0,allocation_size);
2586 SOFF_T(pdata,8,file_size);
2587 if (delete_pending && sbuf.st_nlink)
2588 SIVAL(pdata,16,sbuf.st_nlink - 1);
2589 else
2590 SIVAL(pdata,16,sbuf.st_nlink);
2591 SCVAL(pdata,20,delete_pending);
2592 SCVAL(pdata,21,(mode&aDIR)?1:0);
2593 pdata += 24;
2594 SIVAL(pdata,0,ea_size);
2595 pdata += 4; /* EA info */
2596 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2597 SIVAL(pdata,0,len);
2598 pdata += 4 + len;
2599 data_size = PTR_DIFF(pdata,(*ppdata));
2600 break;
2602 case SMB_FILE_INTERNAL_INFORMATION:
2603 /* This should be an index number - looks like
2604 dev/ino to me :-)
2606 I think this causes us to fail the IFSKIT
2607 BasicFileInformationTest. -tpot */
2609 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2610 SIVAL(pdata,0,sbuf.st_dev);
2611 SIVAL(pdata,4,sbuf.st_ino);
2612 data_size = 8;
2613 break;
2615 case SMB_FILE_ACCESS_INFORMATION:
2616 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2617 SIVAL(pdata,0,desired_access);
2618 data_size = 4;
2619 break;
2621 case SMB_FILE_NAME_INFORMATION:
2622 /* Pathname with leading '\'. */
2624 size_t byte_len;
2625 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2626 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2627 SIVAL(pdata,0,byte_len);
2628 data_size = 4 + byte_len;
2629 break;
2632 case SMB_FILE_DISPOSITION_INFORMATION:
2633 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2634 data_size = 1;
2635 SCVAL(pdata,0,delete_pending);
2636 break;
2638 case SMB_FILE_POSITION_INFORMATION:
2639 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2640 data_size = 8;
2641 SOFF_T(pdata,0,pos);
2642 break;
2644 case SMB_FILE_MODE_INFORMATION:
2645 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2646 SIVAL(pdata,0,mode);
2647 data_size = 4;
2648 break;
2650 case SMB_FILE_ALIGNMENT_INFORMATION:
2651 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2652 SIVAL(pdata,0,0); /* No alignment needed. */
2653 data_size = 4;
2654 break;
2656 #if 0
2658 * NT4 server just returns "invalid query" to this - if we try to answer
2659 * it then NTws gets a BSOD! (tridge).
2660 * W2K seems to want this. JRA.
2662 case SMB_QUERY_FILE_STREAM_INFO:
2663 #endif
2664 case SMB_FILE_STREAM_INFORMATION:
2665 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2666 if (mode & aDIR) {
2667 data_size = 0;
2668 } else {
2669 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2670 SIVAL(pdata,0,0); /* ??? */
2671 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2672 SOFF_T(pdata,8,file_size);
2673 SIVAL(pdata,16,allocation_size);
2674 SIVAL(pdata,20,0); /* ??? */
2675 data_size = 24 + byte_len;
2677 break;
2679 case SMB_QUERY_COMPRESSION_INFO:
2680 case SMB_FILE_COMPRESSION_INFORMATION:
2681 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2682 SOFF_T(pdata,0,file_size);
2683 SIVAL(pdata,8,0); /* ??? */
2684 SIVAL(pdata,12,0); /* ??? */
2685 data_size = 16;
2686 break;
2688 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2689 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2690 put_long_date(pdata,c_time);
2691 put_long_date(pdata+8,sbuf.st_atime);
2692 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2693 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2694 SIVAL(pdata,32,allocation_size);
2695 SOFF_T(pdata,40,file_size);
2696 SIVAL(pdata,48,mode);
2697 SIVAL(pdata,52,0); /* ??? */
2698 data_size = 56;
2699 break;
2701 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2702 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2703 SIVAL(pdata,0,mode);
2704 SIVAL(pdata,4,0);
2705 data_size = 8;
2706 break;
2709 * CIFS UNIX Extensions.
2712 case SMB_QUERY_FILE_UNIX_BASIC:
2714 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2715 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2717 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2718 pdata += 8;
2720 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2721 pdata += 8;
2723 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2724 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2725 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2726 pdata += 24;
2728 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2729 SIVAL(pdata,4,0);
2730 pdata += 8;
2732 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2733 SIVAL(pdata,4,0);
2734 pdata += 8;
2736 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2737 pdata += 4;
2739 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2740 SIVAL(pdata,4,0);
2741 pdata += 8;
2743 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2744 SIVAL(pdata,4,0);
2745 pdata += 8;
2747 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2748 pdata += 8;
2750 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2751 SIVAL(pdata,4,0);
2752 pdata += 8;
2754 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2755 SIVAL(pdata,4,0);
2756 pdata += 8+1;
2757 data_size = PTR_DIFF(pdata,(*ppdata));
2760 int i;
2761 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2763 for (i=0; i<100; i++)
2764 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2765 DEBUG(4,("\n"));
2768 break;
2770 case SMB_QUERY_FILE_UNIX_LINK:
2772 pstring buffer;
2774 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2775 #ifdef S_ISLNK
2776 if(!S_ISLNK(sbuf.st_mode))
2777 return(UNIXERROR(ERRSRV,ERRbadlink));
2778 #else
2779 return(UNIXERROR(ERRDOS,ERRbadlink));
2780 #endif
2781 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2782 if (len == -1)
2783 return(UNIXERROR(ERRDOS,ERRnoaccess));
2784 buffer[len] = 0;
2785 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2786 pdata += len;
2787 data_size = PTR_DIFF(pdata,(*ppdata));
2789 break;
2792 default:
2793 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2796 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2798 return(-1);
2801 /****************************************************************************
2802 Deal with the internal needs of setting the delete on close flag. Note that
2803 as the tdb locking is recursive, it is safe to call this from within
2804 open_file_shared. JRA.
2805 ****************************************************************************/
2807 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2810 * Only allow delete on close for writable shares.
2813 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2814 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2815 fsp->fsp_name ));
2816 return NT_STATUS_ACCESS_DENIED;
2819 * Only allow delete on close for files/directories opened with delete intent.
2822 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2823 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2824 fsp->fsp_name ));
2825 return NT_STATUS_ACCESS_DENIED;
2828 if(fsp->is_directory) {
2829 fsp->directory_delete_on_close = delete_on_close;
2830 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2831 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2832 } else {
2833 fsp->delete_on_close = delete_on_close;
2834 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2835 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2838 return NT_STATUS_OK;
2841 /****************************************************************************
2842 Sets the delete on close flag over all share modes on this file.
2843 Modify the share mode entry for all files open
2844 on this device and inode to tell other smbds we have
2845 changed the delete on close flag. This will be noticed
2846 in the close code, the last closer will delete the file
2847 if flag is set.
2848 ****************************************************************************/
2850 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2852 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2853 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2855 if (fsp->is_directory || fsp->is_stat)
2856 return NT_STATUS_OK;
2858 if (lock_share_entry_fsp(fsp) == False)
2859 return NT_STATUS_ACCESS_DENIED;
2861 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2862 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2863 fsp->fsp_name ));
2864 unlock_share_entry_fsp(fsp);
2865 return NT_STATUS_ACCESS_DENIED;
2868 unlock_share_entry_fsp(fsp);
2869 return NT_STATUS_OK;
2872 /****************************************************************************
2873 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2874 code.
2875 ****************************************************************************/
2877 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2879 BOOL bad_path_oldname = False;
2880 BOOL bad_path_newname = False;
2881 SMB_STRUCT_STAT sbuf1, sbuf2;
2882 pstring last_component_oldname;
2883 pstring last_component_newname;
2884 NTSTATUS status = NT_STATUS_OK;
2886 ZERO_STRUCT(sbuf1);
2887 ZERO_STRUCT(sbuf2);
2889 /* No wildcards. */
2890 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2891 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2894 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2895 if (bad_path_oldname) {
2896 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2899 /* Quick check for "." and ".." */
2900 if (last_component_oldname[0] == '.') {
2901 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2902 return NT_STATUS_OBJECT_NAME_INVALID;
2906 /* source must already exist. */
2907 if (!VALID_STAT(sbuf1)) {
2908 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2911 if (!check_name(oldname,conn)) {
2912 return NT_STATUS_ACCESS_DENIED;
2915 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2916 if (bad_path_newname) {
2917 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2920 /* Quick check for "." and ".." */
2921 if (last_component_newname[0] == '.') {
2922 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2923 return NT_STATUS_OBJECT_NAME_INVALID;
2927 /* Disallow if newname already exists. */
2928 if (VALID_STAT(sbuf2)) {
2929 return NT_STATUS_OBJECT_NAME_COLLISION;
2932 if (!check_name(newname,conn)) {
2933 return NT_STATUS_ACCESS_DENIED;
2936 /* No links from a directory. */
2937 if (S_ISDIR(sbuf1.st_mode)) {
2938 return NT_STATUS_FILE_IS_A_DIRECTORY;
2941 /* Ensure this is within the share. */
2942 if (!reduce_name(conn, oldname) != 0)
2943 return NT_STATUS_ACCESS_DENIED;
2945 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2947 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2948 status = map_nt_error_from_unix(errno);
2949 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2950 nt_errstr(status), newname, oldname));
2953 return status;
2956 /****************************************************************************
2957 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2958 ****************************************************************************/
2960 static int call_trans2setfilepathinfo(connection_struct *conn,
2961 char *inbuf, char *outbuf, int length, int bufsize,
2962 char **pparams, int total_params, char **ppdata, int total_data)
2964 char *params = *pparams;
2965 char *pdata = *ppdata;
2966 uint16 tran_call = SVAL(inbuf, smb_setup0);
2967 uint16 info_level;
2968 int dosmode=0;
2969 SMB_OFF_T size=0;
2970 struct utimbuf tvs;
2971 SMB_STRUCT_STAT sbuf;
2972 pstring fname;
2973 int fd = -1;
2974 BOOL bad_path = False;
2975 files_struct *fsp = NULL;
2976 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2977 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2978 mode_t unixmode = 0;
2979 NTSTATUS status = NT_STATUS_OK;
2981 if (!params)
2982 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2984 ZERO_STRUCT(sbuf);
2986 if (tran_call == TRANSACT2_SETFILEINFO) {
2987 if (total_params < 4)
2988 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2990 fsp = file_fsp(params,0);
2991 info_level = SVAL(params,2);
2993 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2995 * This is actually a SETFILEINFO on a directory
2996 * handle (returned from an NT SMB). NT5.0 seems
2997 * to do this call. JRA.
2999 pstrcpy(fname, fsp->fsp_name);
3000 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3001 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3002 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3004 } else if (fsp && fsp->print_file) {
3006 * Doing a DELETE_ON_CLOSE should cancel a print job.
3008 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3009 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3011 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3013 SSVAL(params,0,0);
3014 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3015 return(-1);
3016 } else
3017 return (UNIXERROR(ERRDOS,ERRbadpath));
3018 } else {
3020 * Original code - this is an open file.
3022 CHECK_FSP(fsp,conn);
3024 pstrcpy(fname, fsp->fsp_name);
3025 fd = fsp->fd;
3027 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3028 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3029 return(UNIXERROR(ERRDOS,ERRbadfid));
3032 } else {
3033 /* set path info */
3034 if (total_params < 6)
3035 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3037 info_level = SVAL(params,0);
3038 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3039 if (!NT_STATUS_IS_OK(status)) {
3040 return ERROR_NT(status);
3042 unix_convert(fname,conn,0,&bad_path,&sbuf);
3043 if (bad_path) {
3044 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3048 * For CIFS UNIX extensions the target name may not exist.
3051 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3052 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3053 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3056 if(!check_name(fname, conn)) {
3057 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3062 if (!CAN_WRITE(conn))
3063 return ERROR_DOS(ERRSRV,ERRaccess);
3065 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3066 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3068 if (VALID_STAT(sbuf))
3069 unixmode = sbuf.st_mode;
3071 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3072 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3074 /* Realloc the parameter and data sizes */
3075 params = Realloc(*pparams,2);
3076 if(params == NULL)
3077 return ERROR_DOS(ERRDOS,ERRnomem);
3078 *pparams = params;
3080 SSVAL(params,0,0);
3082 if (fsp) {
3083 /* the pending modtime overrides the current modtime */
3084 sbuf.st_mtime = fsp->pending_modtime;
3087 size = get_file_size(sbuf);
3088 tvs.modtime = sbuf.st_mtime;
3089 tvs.actime = sbuf.st_atime;
3090 dosmode = dos_mode(conn,fname,&sbuf);
3091 unixmode = sbuf.st_mode;
3093 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3094 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3096 switch (info_level) {
3097 case SMB_INFO_STANDARD:
3099 if (total_data < 12)
3100 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3102 /* access time */
3103 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3104 /* write time */
3105 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3106 break;
3109 case SMB_INFO_SET_EA:
3110 status = set_ea(conn, fsp, fname, pdata, total_data);
3111 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3112 return ERROR_NT(status);
3113 break;
3115 /* XXXX um, i don't think this is right.
3116 it's also not in the cifs6.txt spec.
3118 case SMB_INFO_QUERY_EAS_FROM_LIST:
3119 if (total_data < 28)
3120 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3122 tvs.actime = make_unix_date2(pdata+8);
3123 tvs.modtime = make_unix_date2(pdata+12);
3124 size = IVAL(pdata,16);
3125 dosmode = IVAL(pdata,24);
3126 break;
3128 /* XXXX nor this. not in cifs6.txt, either. */
3129 case SMB_INFO_QUERY_ALL_EAS:
3130 if (total_data < 28)
3131 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3133 tvs.actime = make_unix_date2(pdata+8);
3134 tvs.modtime = make_unix_date2(pdata+12);
3135 size = IVAL(pdata,16);
3136 dosmode = IVAL(pdata,24);
3137 break;
3139 case SMB_SET_FILE_BASIC_INFO:
3140 case SMB_FILE_BASIC_INFORMATION:
3142 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3143 time_t write_time;
3144 time_t changed_time;
3146 if (total_data < 36)
3147 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3149 /* Ignore create time at offset pdata. */
3151 /* access time */
3152 tvs.actime = interpret_long_date(pdata+8);
3154 write_time = interpret_long_date(pdata+16);
3155 changed_time = interpret_long_date(pdata+24);
3157 tvs.modtime = MIN(write_time, changed_time);
3159 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3160 tvs.modtime = write_time;
3162 /* Prefer a defined time to an undefined one. */
3163 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3164 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3165 ? changed_time : write_time);
3167 /* attributes */
3168 dosmode = IVAL(pdata,32);
3169 break;
3172 case SMB_FILE_ALLOCATION_INFORMATION:
3173 case SMB_SET_FILE_ALLOCATION_INFO:
3175 int ret = -1;
3176 SMB_BIG_UINT allocation_size;
3178 if (total_data < 8)
3179 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3181 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3182 #ifdef LARGE_SMB_OFF_T
3183 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3184 #else /* LARGE_SMB_OFF_T */
3185 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3186 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3187 #endif /* LARGE_SMB_OFF_T */
3188 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3189 fname, (double)allocation_size ));
3191 if (allocation_size)
3192 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3194 if(allocation_size != get_file_size(sbuf)) {
3195 SMB_STRUCT_STAT new_sbuf;
3197 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3198 fname, (double)allocation_size ));
3200 if (fd == -1) {
3201 files_struct *new_fsp = NULL;
3202 int access_mode = 0;
3203 int action = 0;
3205 if(global_oplock_break) {
3206 /* Queue this file modify as we are the process of an oplock break. */
3208 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3209 DEBUGADD(2,( "in oplock break state.\n"));
3211 push_oplock_pending_smb_message(inbuf, length);
3212 return -1;
3215 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3216 SET_OPEN_MODE(DOS_OPEN_RDWR),
3217 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3218 FILE_ATTRIBUTE_NORMAL,
3219 INTERNAL_OPEN_ONLY, &access_mode, &action);
3221 if (new_fsp == NULL)
3222 return(UNIXERROR(ERRDOS,ERRbadpath));
3223 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3224 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3225 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3226 new_fsp->fnum, strerror(errno)));
3227 ret = -1;
3229 close_file(new_fsp,True);
3230 } else {
3231 ret = vfs_allocate_file_space(fsp, allocation_size);
3232 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3233 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3234 fsp->fnum, strerror(errno)));
3235 ret = -1;
3238 if (ret == -1)
3239 return ERROR_NT(NT_STATUS_DISK_FULL);
3241 /* Allocate can truncate size... */
3242 size = get_file_size(new_sbuf);
3245 break;
3248 case SMB_FILE_END_OF_FILE_INFORMATION:
3249 case SMB_SET_FILE_END_OF_FILE_INFO:
3251 if (total_data < 8)
3252 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3254 size = IVAL(pdata,0);
3255 #ifdef LARGE_SMB_OFF_T
3256 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3257 #else /* LARGE_SMB_OFF_T */
3258 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3259 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3260 #endif /* LARGE_SMB_OFF_T */
3261 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3262 break;
3265 case SMB_FILE_DISPOSITION_INFORMATION:
3266 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3268 BOOL delete_on_close;
3270 if (total_data < 1)
3271 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3273 delete_on_close = (CVAL(pdata,0) ? True : False);
3275 /* Just ignore this set on a path. */
3276 if (tran_call != TRANSACT2_SETFILEINFO)
3277 break;
3279 if (fsp == NULL)
3280 return(UNIXERROR(ERRDOS,ERRbadfid));
3282 status = set_delete_on_close_internal(fsp, delete_on_close);
3284 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3285 return ERROR_NT(status);
3287 /* The set is across all open files on this dev/inode pair. */
3288 status =set_delete_on_close_over_all(fsp, delete_on_close);
3289 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3290 return ERROR_NT(status);
3292 break;
3295 case SMB_FILE_POSITION_INFORMATION:
3297 SMB_BIG_UINT position_information;
3299 if (total_data < 8)
3300 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3302 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3303 #ifdef LARGE_SMB_OFF_T
3304 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3305 #else /* LARGE_SMB_OFF_T */
3306 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3307 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3308 #endif /* LARGE_SMB_OFF_T */
3309 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3310 fname, (double)position_information ));
3311 if (fsp)
3312 fsp->position_information = position_information;
3313 break;
3317 * CIFS UNIX extensions.
3320 case SMB_SET_FILE_UNIX_BASIC:
3322 uint32 raw_unixmode;
3324 if (total_data < 100)
3325 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3327 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3328 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3329 size=IVAL(pdata,0); /* first 8 Bytes are size */
3330 #ifdef LARGE_SMB_OFF_T
3331 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3332 #else /* LARGE_SMB_OFF_T */
3333 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3334 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3335 #endif /* LARGE_SMB_OFF_T */
3337 pdata+=24; /* ctime & st_blocks are not changed */
3338 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3339 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3340 pdata+=16;
3341 set_owner = (uid_t)IVAL(pdata,0);
3342 pdata += 8;
3343 set_grp = (gid_t)IVAL(pdata,0);
3344 pdata += 8;
3345 raw_unixmode = IVAL(pdata,28);
3346 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3347 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3349 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3350 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3351 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3353 if (!VALID_STAT(sbuf)) {
3356 * The only valid use of this is to create character and block
3357 * devices, and named pipes. This is deprecated (IMHO) and
3358 * a new info level should be used for mknod. JRA.
3361 uint32 file_type = IVAL(pdata,0);
3362 #if defined(HAVE_MAKEDEV)
3363 uint32 dev_major = IVAL(pdata,4);
3364 uint32 dev_minor = IVAL(pdata,12);
3365 #endif
3367 uid_t myuid = geteuid();
3368 gid_t mygid = getegid();
3369 SMB_DEV_T dev = (SMB_DEV_T)0;
3371 if (tran_call == TRANSACT2_SETFILEINFO)
3372 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3374 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3375 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3377 #if defined(HAVE_MAKEDEV)
3378 dev = makedev(dev_major, dev_minor);
3379 #endif
3381 /* We can only create as the owner/group we are. */
3383 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3384 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3385 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3386 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3388 switch (file_type) {
3389 #if defined(S_IFIFO)
3390 case UNIX_TYPE_FIFO:
3391 unixmode |= S_IFIFO;
3392 break;
3393 #endif
3394 #if defined(S_IFSOCK)
3395 case UNIX_TYPE_SOCKET:
3396 unixmode |= S_IFSOCK;
3397 break;
3398 #endif
3399 #if defined(S_IFCHR)
3400 case UNIX_TYPE_CHARDEV:
3401 unixmode |= S_IFCHR;
3402 break;
3403 #endif
3404 #if defined(S_IFBLK)
3405 case UNIX_TYPE_BLKDEV:
3406 unixmode |= S_IFBLK;
3407 break;
3408 #endif
3409 default:
3410 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3413 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3414 0%o for file %s\n", (double)dev, unixmode, fname ));
3416 /* Ok - do the mknod. */
3417 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3418 return(UNIXERROR(ERRDOS,ERRnoaccess));
3420 inherit_access_acl(conn, fname, unixmode);
3422 SSVAL(params,0,0);
3423 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3424 return(-1);
3428 * Deal with the UNIX specific mode set.
3431 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3432 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3433 (unsigned int)unixmode, fname ));
3434 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3435 return(UNIXERROR(ERRDOS,ERRnoaccess));
3439 * Deal with the UNIX specific uid set.
3442 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3443 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3444 (unsigned int)set_owner, fname ));
3445 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3446 return(UNIXERROR(ERRDOS,ERRnoaccess));
3450 * Deal with the UNIX specific gid set.
3453 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3454 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3455 (unsigned int)set_owner, fname ));
3456 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3457 return(UNIXERROR(ERRDOS,ERRnoaccess));
3459 break;
3462 case SMB_SET_FILE_UNIX_LINK:
3464 pstring link_target;
3465 char *newname = fname;
3467 /* Set a symbolic link. */
3468 /* Don't allow this if follow links is false. */
3470 if (!lp_symlinks(SNUM(conn)))
3471 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3473 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3475 /* !widelinks forces the target path to be within the share. */
3476 /* This means we can interpret the target as a pathname. */
3477 if (!lp_widelinks(SNUM(conn))) {
3478 pstring rel_name;
3479 char *last_dirp = NULL;
3481 unix_format(link_target);
3482 if (*link_target == '/') {
3483 /* No absolute paths allowed. */
3484 return(UNIXERROR(ERRDOS,ERRnoaccess));
3486 pstrcpy(rel_name, newname);
3487 last_dirp = strrchr_m(rel_name, '/');
3488 if (last_dirp) {
3489 last_dirp[1] = '\0';
3490 } else {
3491 pstrcpy(rel_name, "./");
3493 pstrcat(rel_name, link_target);
3495 if (!check_name(rel_name, conn)) {
3496 return(UNIXERROR(ERRDOS,ERRnoaccess));
3500 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3501 fname, link_target ));
3503 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3504 return(UNIXERROR(ERRDOS,ERRnoaccess));
3505 SSVAL(params,0,0);
3506 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3507 return(-1);
3510 case SMB_SET_FILE_UNIX_HLINK:
3512 pstring oldname;
3513 char *newname = fname;
3515 /* Set a hard link. */
3516 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 return ERROR_NT(status);
3521 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3522 fname, oldname));
3524 status = hardlink_internals(conn, oldname, newname);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 return ERROR_NT(status);
3529 SSVAL(params,0,0);
3530 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3531 return(-1);
3534 case SMB_FILE_RENAME_INFORMATION:
3536 BOOL overwrite;
3537 uint32 root_fid;
3538 uint32 len;
3539 pstring newname;
3540 pstring base_name;
3541 char *p;
3543 if (total_data < 12)
3544 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3546 overwrite = (CVAL(pdata,0) ? True : False);
3547 root_fid = IVAL(pdata,4);
3548 len = IVAL(pdata,8);
3549 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3550 if (!NT_STATUS_IS_OK(status)) {
3551 return ERROR_NT(status);
3554 /* Check the new name has no '/' characters. */
3555 if (strchr_m(newname, '/'))
3556 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3558 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3560 /* Create the base directory. */
3561 pstrcpy(base_name, fname);
3562 p = strrchr_m(base_name, '/');
3563 if (p)
3564 *p = '\0';
3565 /* Append the new name. */
3566 pstrcat(base_name, "/");
3567 pstrcat(base_name, newname);
3569 if (fsp) {
3570 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3571 fsp->fnum, fsp->fsp_name, base_name ));
3572 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3573 } else {
3574 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3575 fname, newname ));
3576 status = rename_internals(conn, fname, base_name, 0, overwrite);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 return ERROR_NT(status);
3581 process_pending_change_notify_queue((time_t)0);
3582 SSVAL(params,0,0);
3583 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3584 return(-1);
3586 default:
3587 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3590 /* get some defaults (no modifications) if any info is zero or -1. */
3591 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3592 tvs.actime = sbuf.st_atime;
3594 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3595 tvs.modtime = sbuf.st_mtime;
3597 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3598 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3599 DEBUG(6,("size: %.0f ", (double)size));
3601 if (dosmode) {
3602 if (S_ISDIR(sbuf.st_mode))
3603 dosmode |= aDIR;
3604 else
3605 dosmode &= ~aDIR;
3608 DEBUG(6,("dosmode: %x\n" , dosmode));
3610 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3611 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3612 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3613 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3616 * Only do this test if we are not explicitly
3617 * changing the size of a file.
3619 if (!size)
3620 size = get_file_size(sbuf);
3624 * Try and set the times, size and mode of this file -
3625 * if they are different from the current values
3627 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3628 if(fsp != NULL) {
3630 * This was a setfileinfo on an open file.
3631 * NT does this a lot. It's actually pointless
3632 * setting the time here, as it will be overwritten
3633 * on the next write, so we save the request
3634 * away and will set it on file close. JRA.
3637 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3638 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3639 fsp->pending_modtime = tvs.modtime;
3642 } else {
3644 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3646 if(file_utime(conn, fname, &tvs)!=0)
3647 return(UNIXERROR(ERRDOS,ERRnoaccess));
3651 /* check the mode isn't different, before changing it */
3652 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3654 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3656 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3657 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3658 return(UNIXERROR(ERRDOS,ERRnoaccess));
3662 if (size != get_file_size(sbuf)) {
3664 int ret;
3666 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3667 fname, (double)size ));
3669 if (fd == -1) {
3670 files_struct *new_fsp = NULL;
3671 int access_mode = 0;
3672 int action = 0;
3674 if(global_oplock_break) {
3675 /* Queue this file modify as we are the process of an oplock break. */
3677 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3678 DEBUGADD(2,( "in oplock break state.\n"));
3680 push_oplock_pending_smb_message(inbuf, length);
3681 return -1;
3684 new_fsp = open_file_shared(conn, fname, &sbuf,
3685 SET_OPEN_MODE(DOS_OPEN_RDWR),
3686 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3687 FILE_ATTRIBUTE_NORMAL,
3688 INTERNAL_OPEN_ONLY, &access_mode, &action);
3690 if (new_fsp == NULL)
3691 return(UNIXERROR(ERRDOS,ERRbadpath));
3692 ret = vfs_set_filelen(new_fsp, size);
3693 close_file(new_fsp,True);
3694 } else {
3695 ret = vfs_set_filelen(fsp, size);
3698 if (ret == -1)
3699 return (UNIXERROR(ERRHRD,ERRdiskfull));
3702 SSVAL(params,0,0);
3703 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3705 return(-1);
3708 /****************************************************************************
3709 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3710 ****************************************************************************/
3712 static int call_trans2mkdir(connection_struct *conn,
3713 char *inbuf, char *outbuf, int length, int bufsize,
3714 char **pparams, int total_params, char **ppdata, int total_data)
3716 char *params = *pparams;
3717 pstring directory;
3718 int ret = -1;
3719 SMB_STRUCT_STAT sbuf;
3720 BOOL bad_path = False;
3721 NTSTATUS status = NT_STATUS_OK;
3723 if (!CAN_WRITE(conn))
3724 return ERROR_DOS(ERRSRV,ERRaccess);
3726 if (total_params < 4)
3727 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3729 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3730 if (!NT_STATUS_IS_OK(status)) {
3731 return ERROR_NT(status);
3734 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3736 unix_convert(directory,conn,0,&bad_path,&sbuf);
3737 if (bad_path) {
3738 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3740 if (check_name(directory,conn))
3741 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3743 if(ret < 0) {
3744 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3745 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3748 /* Realloc the parameter and data sizes */
3749 params = Realloc(*pparams,2);
3750 if(params == NULL)
3751 return ERROR_DOS(ERRDOS,ERRnomem);
3752 *pparams = params;
3754 SSVAL(params,0,0);
3756 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3758 return(-1);
3761 /****************************************************************************
3762 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3763 We don't actually do this - we just send a null response.
3764 ****************************************************************************/
3766 static int call_trans2findnotifyfirst(connection_struct *conn,
3767 char *inbuf, char *outbuf, int length, int bufsize,
3768 char **pparams, int total_params, char **ppdata, int total_data)
3770 static uint16 fnf_handle = 257;
3771 char *params = *pparams;
3772 uint16 info_level;
3774 if (total_params < 6)
3775 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3777 info_level = SVAL(params,4);
3778 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3780 switch (info_level) {
3781 case 1:
3782 case 2:
3783 break;
3784 default:
3785 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3788 /* Realloc the parameter and data sizes */
3789 params = Realloc(*pparams,6);
3790 if(params == NULL)
3791 return ERROR_DOS(ERRDOS,ERRnomem);
3792 *pparams = params;
3794 SSVAL(params,0,fnf_handle);
3795 SSVAL(params,2,0); /* No changes */
3796 SSVAL(params,4,0); /* No EA errors */
3798 fnf_handle++;
3800 if(fnf_handle == 0)
3801 fnf_handle = 257;
3803 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3805 return(-1);
3808 /****************************************************************************
3809 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3810 changes). Currently this does nothing.
3811 ****************************************************************************/
3813 static int call_trans2findnotifynext(connection_struct *conn,
3814 char *inbuf, char *outbuf, int length, int bufsize,
3815 char **pparams, int total_params, char **ppdata, int total_data)
3817 char *params = *pparams;
3819 DEBUG(3,("call_trans2findnotifynext\n"));
3821 /* Realloc the parameter and data sizes */
3822 params = Realloc(*pparams,4);
3823 if(params == NULL)
3824 return ERROR_DOS(ERRDOS,ERRnomem);
3825 *pparams = params;
3827 SSVAL(params,0,0); /* No changes */
3828 SSVAL(params,2,0); /* No EA errors */
3830 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3832 return(-1);
3835 /****************************************************************************
3836 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3837 ****************************************************************************/
3839 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3840 char* outbuf, int length, int bufsize,
3841 char **pparams, int total_params, char **ppdata, int total_data)
3843 char *params = *pparams;
3844 pstring pathname;
3845 int reply_size = 0;
3846 int max_referral_level;
3848 DEBUG(10,("call_trans2getdfsreferral\n"));
3850 if (total_params < 2)
3851 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3853 max_referral_level = SVAL(params,0);
3855 if(!lp_host_msdfs())
3856 return ERROR_DOS(ERRDOS,ERRbadfunc);
3858 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3859 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3860 return UNIXERROR(ERRDOS,ERRbadfile);
3862 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3863 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3865 return(-1);
3868 #define LMCAT_SPL 0x53
3869 #define LMFUNC_GETJOBID 0x60
3871 /****************************************************************************
3872 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3873 ****************************************************************************/
3875 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3876 char* outbuf, int length, int bufsize,
3877 char **pparams, int total_params, char **ppdata, int total_data)
3879 char *pdata = *ppdata;
3880 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3882 /* check for an invalid fid before proceeding */
3884 if (!fsp)
3885 return(ERROR_DOS(ERRDOS,ERRbadfid));
3887 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3888 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3889 pdata = Realloc(*ppdata, 32);
3890 if(pdata == NULL)
3891 return ERROR_DOS(ERRDOS,ERRnomem);
3892 *ppdata = pdata;
3894 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3895 CAN ACCEPT THIS IN UNICODE. JRA. */
3897 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3898 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3899 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3900 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3901 return(-1);
3902 } else {
3903 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3904 return ERROR_DOS(ERRSRV,ERRerror);
3908 /****************************************************************************
3909 Reply to a SMBfindclose (stop trans2 directory search).
3910 ****************************************************************************/
3912 int reply_findclose(connection_struct *conn,
3913 char *inbuf,char *outbuf,int length,int bufsize)
3915 int outsize = 0;
3916 int dptr_num=SVALS(inbuf,smb_vwv0);
3917 START_PROFILE(SMBfindclose);
3919 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3921 dptr_close(&dptr_num);
3923 outsize = set_message(outbuf,0,0,True);
3925 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3927 END_PROFILE(SMBfindclose);
3928 return(outsize);
3931 /****************************************************************************
3932 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3933 ****************************************************************************/
3935 int reply_findnclose(connection_struct *conn,
3936 char *inbuf,char *outbuf,int length,int bufsize)
3938 int outsize = 0;
3939 int dptr_num= -1;
3940 START_PROFILE(SMBfindnclose);
3942 dptr_num = SVAL(inbuf,smb_vwv0);
3944 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3946 /* We never give out valid handles for a
3947 findnotifyfirst - so any dptr_num is ok here.
3948 Just ignore it. */
3950 outsize = set_message(outbuf,0,0,True);
3952 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3954 END_PROFILE(SMBfindnclose);
3955 return(outsize);
3958 /****************************************************************************
3959 Reply to a SMBtranss2 - just ignore it!
3960 ****************************************************************************/
3962 int reply_transs2(connection_struct *conn,
3963 char *inbuf,char *outbuf,int length,int bufsize)
3965 START_PROFILE(SMBtranss2);
3966 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3967 END_PROFILE(SMBtranss2);
3968 return(-1);
3971 /****************************************************************************
3972 Reply to a SMBtrans2.
3973 ****************************************************************************/
3975 int reply_trans2(connection_struct *conn,
3976 char *inbuf,char *outbuf,int length,int bufsize)
3978 int outsize = 0;
3979 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3980 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3981 #if 0
3982 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3983 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3984 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3985 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3986 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3987 int32 timeout = IVALS(inbuf,smb_timeout);
3988 #endif
3989 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3990 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3991 char *params = NULL, *data = NULL;
3992 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3993 START_PROFILE(SMBtrans2);
3995 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3996 /* Queue this open message as we are the process of an
3997 * oplock break. */
3999 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4000 DEBUGADD(2,( "in oplock break state.\n"));
4002 push_oplock_pending_smb_message(inbuf, length);
4003 END_PROFILE(SMBtrans2);
4004 return -1;
4007 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4008 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4009 END_PROFILE(SMBtrans2);
4010 return ERROR_DOS(ERRSRV,ERRaccess);
4013 outsize = set_message(outbuf,0,0,True);
4015 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4016 is so as a sanity check */
4017 if (suwcnt != 1) {
4019 * Need to have rc=0 for ioctl to get job id for OS/2.
4020 * Network printing will fail if function is not successful.
4021 * Similar function in reply.c will be used if protocol
4022 * is LANMAN1.0 instead of LM1.2X002.
4023 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4024 * outbuf doesn't have to be set(only job id is used).
4026 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4027 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4028 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4029 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4030 } else {
4031 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4032 DEBUG(2,("Transaction is %d\n",tran_call));
4033 END_PROFILE(SMBtrans2);
4034 ERROR_DOS(ERRDOS,ERRinvalidparam);
4038 /* Allocate the space for the maximum needed parameters and data */
4039 if (total_params > 0)
4040 params = (char *)malloc(total_params);
4041 if (total_data > 0)
4042 data = (char *)malloc(total_data);
4044 if ((total_params && !params) || (total_data && !data)) {
4045 DEBUG(2,("Out of memory in reply_trans2\n"));
4046 SAFE_FREE(params);
4047 SAFE_FREE(data);
4048 END_PROFILE(SMBtrans2);
4049 return ERROR_DOS(ERRDOS,ERRnomem);
4052 /* Copy the param and data bytes sent with this request into
4053 the params buffer */
4054 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4055 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4057 if (num_params > total_params || num_data > total_data)
4058 exit_server("invalid params in reply_trans2");
4060 if(params) {
4061 unsigned int psoff = SVAL(inbuf, smb_psoff);
4062 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4063 goto bad_param;
4064 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4065 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4066 goto bad_param;
4067 memcpy( params, smb_base(inbuf) + psoff, num_params);
4069 if(data) {
4070 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4071 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4072 goto bad_param;
4073 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4074 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4075 goto bad_param;
4076 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4079 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4081 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4082 /* We need to send an interim response then receive the rest
4083 of the parameter/data bytes */
4084 outsize = set_message(outbuf,0,0,True);
4085 srv_signing_trans_stop();
4086 if (!send_smb(smbd_server_fd(),outbuf))
4087 exit_server("reply_trans2: send_smb failed.");
4089 while (num_data_sofar < total_data ||
4090 num_params_sofar < total_params) {
4091 BOOL ret;
4092 unsigned int param_disp;
4093 unsigned int param_off;
4094 unsigned int data_disp;
4095 unsigned int data_off;
4097 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4100 * The sequence number for the trans reply is always
4101 * based on the last secondary received.
4104 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4106 if ((ret &&
4107 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4108 outsize = set_message(outbuf,0,0,True);
4109 if(ret)
4110 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4111 else
4112 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4113 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4114 goto bad_param;
4117 /* Revise total_params and total_data in case
4118 they have changed downwards */
4119 if (SVAL(inbuf, smb_tpscnt) < total_params)
4120 total_params = SVAL(inbuf, smb_tpscnt);
4121 if (SVAL(inbuf, smb_tdscnt) < total_data)
4122 total_data = SVAL(inbuf, smb_tdscnt);
4124 num_params = SVAL(inbuf,smb_spscnt);
4125 param_off = SVAL(inbuf, smb_spsoff);
4126 param_disp = SVAL(inbuf, smb_spsdisp);
4127 num_params_sofar += num_params;
4129 num_data = SVAL(inbuf, smb_sdscnt);
4130 data_off = SVAL(inbuf, smb_sdsoff);
4131 data_disp = SVAL(inbuf, smb_sdsdisp);
4132 num_data_sofar += num_data;
4134 if (num_params_sofar > total_params || num_data_sofar > total_data)
4135 goto bad_param;
4137 if (num_params) {
4138 if (param_disp + num_params >= total_params)
4139 goto bad_param;
4140 if ((param_disp + num_params < param_disp) ||
4141 (param_disp + num_params < num_params))
4142 goto bad_param;
4143 if (param_disp > total_params)
4144 goto bad_param;
4145 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4146 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4147 goto bad_param;
4148 if (params + param_disp < params)
4149 goto bad_param;
4151 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4153 if (num_data) {
4154 if (data_disp + num_data >= total_data)
4155 goto bad_param;
4156 if ((data_disp + num_data < data_disp) ||
4157 (data_disp + num_data < num_data))
4158 goto bad_param;
4159 if (data_disp > total_data)
4160 goto bad_param;
4161 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4162 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4163 goto bad_param;
4164 if (data + data_disp < data)
4165 goto bad_param;
4167 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4172 if (Protocol >= PROTOCOL_NT1) {
4173 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4176 /* Now we must call the relevant TRANS2 function */
4177 switch(tran_call) {
4178 case TRANSACT2_OPEN:
4179 START_PROFILE_NESTED(Trans2_open);
4180 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4181 &params, total_params, &data, total_data);
4182 END_PROFILE_NESTED(Trans2_open);
4183 break;
4185 case TRANSACT2_FINDFIRST:
4186 START_PROFILE_NESTED(Trans2_findfirst);
4187 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4188 &params, total_params, &data, total_data);
4189 END_PROFILE_NESTED(Trans2_findfirst);
4190 break;
4192 case TRANSACT2_FINDNEXT:
4193 START_PROFILE_NESTED(Trans2_findnext);
4194 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4195 &params, total_params, &data, total_data);
4196 END_PROFILE_NESTED(Trans2_findnext);
4197 break;
4199 case TRANSACT2_QFSINFO:
4200 START_PROFILE_NESTED(Trans2_qfsinfo);
4201 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4202 &params, total_params, &data, total_data);
4203 END_PROFILE_NESTED(Trans2_qfsinfo);
4204 break;
4206 #ifdef HAVE_SYS_QUOTAS
4207 case TRANSACT2_SETFSINFO:
4208 START_PROFILE_NESTED(Trans2_setfsinfo);
4209 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4210 &params, total_params, &data, total_data);
4211 END_PROFILE_NESTED(Trans2_setfsinfo);
4212 break;
4213 #endif
4214 case TRANSACT2_QPATHINFO:
4215 case TRANSACT2_QFILEINFO:
4216 START_PROFILE_NESTED(Trans2_qpathinfo);
4217 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4218 &params, total_params, &data, total_data);
4219 END_PROFILE_NESTED(Trans2_qpathinfo);
4220 break;
4221 case TRANSACT2_SETPATHINFO:
4222 case TRANSACT2_SETFILEINFO:
4223 START_PROFILE_NESTED(Trans2_setpathinfo);
4224 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4225 &params, total_params, &data, total_data);
4226 END_PROFILE_NESTED(Trans2_setpathinfo);
4227 break;
4229 case TRANSACT2_FINDNOTIFYFIRST:
4230 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4231 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4232 &params, total_params, &data, total_data);
4233 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4234 break;
4236 case TRANSACT2_FINDNOTIFYNEXT:
4237 START_PROFILE_NESTED(Trans2_findnotifynext);
4238 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4239 &params, total_params, &data, total_data);
4240 END_PROFILE_NESTED(Trans2_findnotifynext);
4241 break;
4242 case TRANSACT2_MKDIR:
4243 START_PROFILE_NESTED(Trans2_mkdir);
4244 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4245 &params, total_params, &data, total_data);
4246 END_PROFILE_NESTED(Trans2_mkdir);
4247 break;
4249 case TRANSACT2_GET_DFS_REFERRAL:
4250 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4251 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4252 &params, total_params, &data, total_data);
4253 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4254 break;
4255 case TRANSACT2_IOCTL:
4256 START_PROFILE_NESTED(Trans2_ioctl);
4257 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4258 &params, total_params, &data, total_data);
4259 END_PROFILE_NESTED(Trans2_ioctl);
4260 break;
4261 default:
4262 /* Error in request */
4263 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4264 SAFE_FREE(params);
4265 SAFE_FREE(data);
4266 END_PROFILE(SMBtrans2);
4267 srv_signing_trans_stop();
4268 return ERROR_DOS(ERRSRV,ERRerror);
4271 /* As we do not know how many data packets will need to be
4272 returned here the various call_trans2xxxx calls
4273 must send their own. Thus a call_trans2xxx routine only
4274 returns a value other than -1 when it wants to send
4275 an error packet.
4278 srv_signing_trans_stop();
4280 SAFE_FREE(params);
4281 SAFE_FREE(data);
4282 END_PROFILE(SMBtrans2);
4283 return outsize; /* If a correct response was needed the
4284 call_trans2xxx calls have already sent
4285 it. If outsize != -1 then it is returning */
4287 bad_param:
4289 srv_signing_trans_stop();
4290 SAFE_FREE(params);
4291 SAFE_FREE(data);
4292 END_PROFILE(SMBtrans2);
4293 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);