r5933: We were handling setting of EA's incorrectly - we should be able to set
[Samba/gebeck_regimport.git] / source / smbd / trans2.c
blobd09231dd83e9b879c1664f333978d2d1bf1533ce
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 enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest allocation roundup size boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44 /* Only roundup for Windows clients. */
45 enum remote_arch_types ra_type = get_remote_arch();
46 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47 val = SMB_ROUNDUP(val,rval);
49 return val;
52 /********************************************************************
53 Given a stat buffer return the allocated size on disk, taking into
54 account sparse files.
55 ********************************************************************/
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
59 SMB_BIG_UINT ret;
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
63 #else
64 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
65 #endif
67 if (!ret && fsp && fsp->initial_allocation_size)
68 ret = fsp->initial_allocation_size;
70 return smb_roundup(conn, ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
80 NULL
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
89 int i;
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
93 return True;
95 return False;
98 struct ea_list {
99 struct ea_list *next, *prev;
100 struct ea_struct ea;
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
112 char *val = NULL;
113 ssize_t sizeret;
115 again:
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
118 if (!val) {
119 return False;
122 if (fsp && fsp->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
124 } else {
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
129 attr_size = 65536;
130 goto again;
133 if (sizeret == -1) {
134 return False;
137 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138 dump_data(10, val, sizeret);
140 pea->flags = 0;
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
143 } else {
144 pea->name = ea_name;
146 pea->value.data = (unsigned char *)val;
147 pea->value.length = (size_t)sizeret;
148 return True;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
156 const char *fname, size_t *pea_total_len)
158 /* Get a list of all xattrs. Max namesize is 64k. */
159 size_t ea_namelist_size = 1024;
160 char *ea_namelist;
161 char *p;
162 ssize_t sizeret;
163 int i;
164 struct ea_list *ea_list_head = NULL;
166 *pea_total_len = 0;
168 if (!lp_ea_support(SNUM(conn))) {
169 return NULL;
172 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
173 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
174 if (fsp && fsp->fd != -1) {
175 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176 } else {
177 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
180 if (sizeret == -1 && errno == ERANGE) {
181 ea_namelist_size *= 2;
182 } else {
183 break;
187 if (sizeret == -1)
188 return NULL;
190 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret ));
192 if (sizeret) {
193 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194 struct ea_list *listp, *tmp;
196 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
197 continue;
199 listp = TALLOC_P(mem_ctx, struct ea_list);
200 if (!listp)
201 return NULL;
203 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
204 return NULL;
208 fstring dos_ea_name;
209 push_ascii_fstring(dos_ea_name, listp->ea.name);
210 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
212 *pea_total_len, dos_ea_name,
213 (unsigned int)listp->ea.value.length ));
215 DLIST_ADD_END(ea_list_head, listp, tmp);
217 /* Add on 4 for total length. */
218 if (*pea_total_len) {
219 *pea_total_len += 4;
223 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len));
224 return ea_list_head;
227 /****************************************************************************
228 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229 that was filled.
230 ****************************************************************************/
232 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
233 connection_struct *conn, struct ea_list *ea_list)
235 unsigned int ret_data_size = 4;
236 char *p = pdata;
238 SMB_ASSERT(total_data_size >= 4);
240 SIVAL(pdata,0,0);
241 if (!lp_ea_support(SNUM(conn))) {
242 return 4;
245 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
246 size_t dos_namelen;
247 fstring dos_ea_name;
248 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
249 dos_namelen = strlen(dos_ea_name);
250 if (dos_namelen > 255 || dos_namelen == 0) {
251 break;
253 if (ea_list->ea.value.length > 65535) {
254 break;
256 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
257 break;
260 /* We know we have room. */
261 SCVAL(p,0,ea_list->ea.flags);
262 SCVAL(p,1,dos_namelen);
263 SSVAL(p,2,ea_list->ea.value.length);
264 fstrcpy(p+4, dos_ea_name);
265 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
267 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
268 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
271 ret_data_size = PTR_DIFF(p, pdata);
272 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
273 SIVAL(pdata,0,ret_data_size);
274 return ret_data_size;
277 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
279 size_t total_ea_len = 0;
280 TALLOC_CTX *mem_ctx = NULL;
282 if (!lp_ea_support(SNUM(conn))) {
283 return 0;
285 mem_ctx = talloc_init("estimate_ea_size");
286 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
287 talloc_destroy(mem_ctx);
288 return total_ea_len;
291 /****************************************************************************
292 Ensure the EA name is case insensitive by matching any existing EA name.
293 ****************************************************************************/
295 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
297 size_t total_ea_len;
298 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
299 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
301 for (; ea_list; ea_list = ea_list->next) {
302 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
303 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
304 &unix_ea_name[5], ea_list->ea.name));
305 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
306 break;
309 talloc_destroy(mem_ctx);
312 /****************************************************************************
313 Set or delete an extended attribute.
314 ****************************************************************************/
316 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
318 if (!lp_ea_support(SNUM(conn))) {
319 return NT_STATUS_EAS_NOT_SUPPORTED;
322 while (ea_list) {
323 int ret;
324 fstring unix_ea_name;
326 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
327 fstrcat(unix_ea_name, ea_list->ea.name);
329 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
331 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length));
333 if (samba_private_attr_name(unix_ea_name)) {
334 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
335 return NT_STATUS_ACCESS_DENIED;
338 if (ea_list->ea.value.length == 0) {
339 /* Remove the attribute. */
340 if (fsp && (fsp->fd != -1)) {
341 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
342 unix_ea_name, fsp->fsp_name));
343 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
344 } else {
345 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
346 unix_ea_name, fname));
347 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
349 #ifdef ENOATTR
350 /* Removing a non existent attribute always succeeds. */
351 if (ret == -1 && errno == ENOATTR) {
352 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
353 unix_ea_name));
354 ret = 0;
356 #endif
357 } else {
358 if (fsp && (fsp->fd != -1)) {
359 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
360 unix_ea_name, fsp->fsp_name));
361 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name,
362 ea_list->ea.value.data, ea_list->ea.value.length, 0);
363 } else {
364 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
365 unix_ea_name, fname));
366 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
367 ea_list->ea.value.data, ea_list->ea.value.length, 0);
371 if (ret == -1) {
372 #ifdef ENOTSUP
373 if (errno == ENOTSUP) {
374 return NT_STATUS_EAS_NOT_SUPPORTED;
376 #endif
377 return map_nt_error_from_unix(errno);
381 return NT_STATUS_OK;
383 /****************************************************************************
384 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
385 ****************************************************************************/
387 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
389 struct ea_list *ea_list_head = NULL;
390 size_t offset = 4;
392 while (offset + 2 < data_size) {
393 struct ea_list *tmp;
394 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
395 unsigned int namelen = CVAL(pdata,offset);
397 offset++; /* Go past the namelen byte. */
398 if (offset + namelen >= data_size) {
399 break;
401 /* Ensure the name is null terminated. */
402 if (pdata[offset + namelen] != '\0') {
403 return NULL;
405 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
406 if (!eal->ea.name) {
407 return NULL;
410 offset += (namelen + 1); /* Go past the name + terminating zero. */
411 DLIST_ADD_END(ea_list_head, eal, tmp);
412 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
415 return ea_list_head;
418 /****************************************************************************
419 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
420 ****************************************************************************/
422 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
424 struct ea_list *ea_list_head = NULL;
425 size_t offset = 4;
427 if (data_size < 10) {
428 return NULL;
431 if (IVAL(pdata,0) > data_size) {
432 DEBUG(10,("read_ea_list: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)data_size));
433 return NULL;
436 /* Each entry must be at least 6 bytes in length. */
437 while (offset + 6 <= data_size) {
438 struct ea_list *tmp;
439 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
440 uint16 val_len;
441 unsigned int namelen;
443 eal->ea.flags = CVAL(pdata,offset);
444 namelen = CVAL(pdata,offset + 1);
445 val_len = SVAL(pdata,offset + 2);
447 if (offset + 4 + namelen + 1 + val_len > data_size) {
448 return NULL;
451 /* Ensure the name is null terminated. */
452 if (pdata[offset + 4 + namelen] != '\0') {
453 return NULL;
455 pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset);
456 if (!eal->ea.name) {
457 return NULL;
460 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
461 if (!eal->ea.value.data) {
462 break;
465 memcpy(eal->ea.value.data, pdata + offset + 4 + namelen + 1, val_len);
467 /* Ensure we're null terminated just in case we print the value. */
468 eal->ea.value.data[val_len] = '\0';
469 /* But don't count the null. */
470 eal->ea.value.length--;
472 offset += 4 + namelen + 1 + val_len;
474 DLIST_ADD_END(ea_list_head, eal, tmp);
476 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
477 dump_data(10, eal->ea.value.data, eal->ea.value.length);
480 return ea_list_head;
483 /****************************************************************************
484 Count the total EA size needed.
485 ****************************************************************************/
487 static size_t ea_list_size(struct ea_list *ealist)
489 fstring dos_ea_name;
490 struct ea_list *listp;
491 size_t ret = 0;
493 for (listp = ealist; listp; listp = listp->next) {
494 push_ascii_fstring(dos_ea_name, listp->ea.name);
495 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
497 /* Add on 4 for total length. */
498 if (ret) {
499 ret += 4;
502 return ret;
505 /****************************************************************************
506 Return a union of EA's from a file list and a list of names.
507 The TALLOC context for the two lists *MUST* be identical as we steal
508 memory from one list to another. JRA.
509 ****************************************************************************/
511 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
513 struct ea_list *nlistp, *flistp;
515 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
516 for (flistp = file_list; flistp; flistp = flistp->next) {
517 if (strequal(nlistp->ea.name, flistp->ea.name)) {
518 break;
522 if (flistp) {
523 /* Copy the data from this entry. */
524 nlistp->ea.flags = flistp->ea.flags;
525 nlistp->ea.value = flistp->ea.value;
526 } else {
527 /* Null entry. */
528 nlistp->ea.flags = 0;
529 ZERO_STRUCT(nlistp->ea.value);
533 *total_ea_len = ea_list_size(name_list);
534 return name_list;
537 /****************************************************************************
538 Send the required number of replies back.
539 We assume all fields other than the data fields are
540 set correctly for the type of call.
541 HACK ! Always assumes smb_setup field is zero.
542 ****************************************************************************/
544 static int send_trans2_replies(char *outbuf,
545 int bufsize,
546 char *params,
547 int paramsize,
548 char *pdata,
549 int datasize)
551 /* As we are using a protocol > LANMAN1 then the max_send
552 variable must have been set in the sessetupX call.
553 This takes precedence over the max_xmit field in the
554 global struct. These different max_xmit variables should
555 be merged as this is now too confusing */
557 extern int max_send;
558 int data_to_send = datasize;
559 int params_to_send = paramsize;
560 int useable_space;
561 char *pp = params;
562 char *pd = pdata;
563 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
564 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
565 int data_alignment_offset = 0;
567 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
569 set_message(outbuf,10,0,True);
571 /* If there genuinely are no parameters or data to send just send the empty packet */
573 if(params_to_send == 0 && data_to_send == 0) {
574 if (!send_smb(smbd_server_fd(),outbuf))
575 exit_server("send_trans2_replies: send_smb failed.");
576 return 0;
579 /* When sending params and data ensure that both are nicely aligned */
580 /* Only do this alignment when there is also data to send - else
581 can cause NT redirector problems. */
583 if (((params_to_send % 4) != 0) && (data_to_send != 0))
584 data_alignment_offset = 4 - (params_to_send % 4);
586 /* Space is bufsize minus Netbios over TCP header minus SMB header */
587 /* The alignment_offset is to align the param bytes on an even byte
588 boundary. NT 4.0 Beta needs this to work correctly. */
590 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
592 /* useable_space can never be more than max_send minus the alignment offset. */
594 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
596 while (params_to_send || data_to_send) {
597 /* Calculate whether we will totally or partially fill this packet */
599 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
601 /* We can never send more than useable_space */
603 * Note that 'useable_space' does not include the alignment offsets,
604 * but we must include the alignment offsets in the calculation of
605 * the length of the data we send over the wire, as the alignment offsets
606 * are sent here. Fix from Marc_Jacobsen@hp.com.
609 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
611 set_message(outbuf, 10, total_sent_thistime, True);
613 /* Set total params and data to be sent */
614 SSVAL(outbuf,smb_tprcnt,paramsize);
615 SSVAL(outbuf,smb_tdrcnt,datasize);
617 /* Calculate how many parameters and data we can fit into
618 * this packet. Parameters get precedence
621 params_sent_thistime = MIN(params_to_send,useable_space);
622 data_sent_thistime = useable_space - params_sent_thistime;
623 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
625 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
627 /* smb_proff is the offset from the start of the SMB header to the
628 parameter bytes, however the first 4 bytes of outbuf are
629 the Netbios over TCP header. Thus use smb_base() to subtract
630 them from the calculation */
632 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
634 if(params_sent_thistime == 0)
635 SSVAL(outbuf,smb_prdisp,0);
636 else
637 /* Absolute displacement of param bytes sent in this packet */
638 SSVAL(outbuf,smb_prdisp,pp - params);
640 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
641 if(data_sent_thistime == 0) {
642 SSVAL(outbuf,smb_droff,0);
643 SSVAL(outbuf,smb_drdisp, 0);
644 } else {
645 /* The offset of the data bytes is the offset of the
646 parameter bytes plus the number of parameters being sent this time */
647 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
648 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
649 SSVAL(outbuf,smb_drdisp, pd - pdata);
652 /* Copy the param bytes into the packet */
654 if(params_sent_thistime)
655 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
657 /* Copy in the data bytes */
658 if(data_sent_thistime)
659 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
660 data_alignment_offset,pd,data_sent_thistime);
662 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
663 params_sent_thistime, data_sent_thistime, useable_space));
664 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
665 params_to_send, data_to_send, paramsize, datasize));
667 /* Send the packet */
668 if (!send_smb(smbd_server_fd(),outbuf))
669 exit_server("send_trans2_replies: send_smb failed.");
671 pp += params_sent_thistime;
672 pd += data_sent_thistime;
674 params_to_send -= params_sent_thistime;
675 data_to_send -= data_sent_thistime;
677 /* Sanity check */
678 if(params_to_send < 0 || data_to_send < 0) {
679 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
680 params_to_send, data_to_send));
681 return -1;
685 return 0;
688 /****************************************************************************
689 Reply to a TRANSACT2_OPEN.
690 ****************************************************************************/
692 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
693 char **pparams, int total_params, char **ppdata, int total_data,
694 unsigned int max_data_bytes)
696 char *params = *pparams;
697 int16 open_mode;
698 int16 open_attr;
699 BOOL oplock_request;
700 #if 0
701 BOOL return_additional_info;
702 int16 open_sattr;
703 time_t open_time;
704 #endif
705 int16 open_ofun;
706 int32 open_size;
707 char *pname;
708 pstring fname;
709 SMB_OFF_T size=0;
710 int fmode=0,mtime=0,rmode;
711 SMB_INO_T inode = 0;
712 SMB_STRUCT_STAT sbuf;
713 int smb_action = 0;
714 BOOL bad_path = False;
715 files_struct *fsp;
716 NTSTATUS status;
719 * Ensure we have enough parameters to perform the operation.
722 if (total_params < 29) {
723 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
726 open_mode = SVAL(params, 2);
727 open_attr = SVAL(params,6);
728 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
729 #if 0
730 return_additional_info = BITSETW(params,0);
731 open_sattr = SVAL(params, 4);
732 open_time = make_unix_date3(params+8);
733 #endif
734 open_ofun = SVAL(params,12);
735 open_size = IVAL(params,14);
736 pname = &params[28];
738 if (IS_IPC(conn))
739 return(ERROR_DOS(ERRSRV,ERRaccess));
741 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
742 if (!NT_STATUS_IS_OK(status)) {
743 return ERROR_NT(status);
746 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
747 fname,open_mode, open_attr, open_ofun, open_size));
749 /* XXXX we need to handle passed times, sattr and flags */
751 unix_convert(fname,conn,0,&bad_path,&sbuf);
752 if (bad_path) {
753 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
756 if (!check_name(fname,conn)) {
757 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
760 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
761 oplock_request, &rmode,&smb_action);
763 if (!fsp) {
764 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
765 /* We have re-scheduled this call. */
766 clear_cached_errors();
767 return -1;
769 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
772 size = get_file_size(sbuf);
773 fmode = dos_mode(conn,fname,&sbuf);
774 mtime = sbuf.st_mtime;
775 inode = sbuf.st_ino;
776 if (fmode & aDIR) {
777 close_file(fsp,False);
778 return(ERROR_DOS(ERRDOS,ERRnoaccess));
781 /* Realloc the size of parameters and data we will return */
782 params = SMB_REALLOC(*pparams, 28);
783 if( params == NULL ) {
784 return ERROR_NT(NT_STATUS_NO_MEMORY);
786 *pparams = params;
788 memset((char *)params,'\0',28);
789 SSVAL(params,0,fsp->fnum);
790 SSVAL(params,2,fmode);
791 put_dos_date2(params,4, mtime);
792 SIVAL(params,8, (uint32)size);
793 SSVAL(params,12,rmode);
795 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
796 smb_action |= EXTENDED_OPLOCK_GRANTED;
798 SSVAL(params,18,smb_action);
801 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
803 SIVAL(params,20,inode);
805 /* Send the required number of replies */
806 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
808 return -1;
811 /*********************************************************
812 Routine to check if a given string matches exactly.
813 as a special case a mask of "." does NOT match. That
814 is required for correct wildcard semantics
815 Case can be significant or not.
816 **********************************************************/
818 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
820 if (mask[0] == '.' && mask[1] == 0)
821 return False;
822 if (case_sig)
823 return strcmp(str,mask)==0;
824 if (StrCaseCmp(str,mask) != 0) {
825 return False;
827 if (ms_has_wild(str)) {
828 return False;
830 return True;
833 /****************************************************************************
834 Return the filetype for UNIX extensions.
835 ****************************************************************************/
837 static uint32 unix_filetype(mode_t mode)
839 if(S_ISREG(mode))
840 return UNIX_TYPE_FILE;
841 else if(S_ISDIR(mode))
842 return UNIX_TYPE_DIR;
843 #ifdef S_ISLNK
844 else if(S_ISLNK(mode))
845 return UNIX_TYPE_SYMLINK;
846 #endif
847 #ifdef S_ISCHR
848 else if(S_ISCHR(mode))
849 return UNIX_TYPE_CHARDEV;
850 #endif
851 #ifdef S_ISBLK
852 else if(S_ISBLK(mode))
853 return UNIX_TYPE_BLKDEV;
854 #endif
855 #ifdef S_ISFIFO
856 else if(S_ISFIFO(mode))
857 return UNIX_TYPE_FIFO;
858 #endif
859 #ifdef S_ISSOCK
860 else if(S_ISSOCK(mode))
861 return UNIX_TYPE_SOCKET;
862 #endif
864 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
865 return UNIX_TYPE_UNKNOWN;
868 /****************************************************************************
869 Map wire perms onto standard UNIX permissions. Obey share restrictions.
870 ****************************************************************************/
872 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
874 mode_t ret = 0;
876 if (perms == SMB_MODE_NO_CHANGE)
877 return pst->st_mode;
879 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
880 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
881 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
882 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
883 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
884 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
885 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
886 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
887 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
888 #ifdef S_ISVTX
889 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
890 #endif
891 #ifdef S_ISGID
892 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
893 #endif
894 #ifdef S_ISUID
895 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
896 #endif
898 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
899 ret &= lp_dir_mask(SNUM(conn));
900 /* Add in force bits */
901 ret |= lp_force_dir_mode(SNUM(conn));
902 } else {
903 /* Apply mode mask */
904 ret &= lp_create_mask(SNUM(conn));
905 /* Add in force bits */
906 ret |= lp_force_create_mode(SNUM(conn));
909 return ret;
912 /****************************************************************************
913 Get a level dependent lanman2 dir entry.
914 ****************************************************************************/
916 static BOOL get_lanman2_dir_entry(connection_struct *conn,
917 void *inbuf, void *outbuf,
918 char *path_mask,int dirtype,int info_level,
919 int requires_resume_key,
920 BOOL dont_descend,char **ppdata,
921 char *base_data, int space_remaining,
922 BOOL *out_of_space, BOOL *got_exact_match,
923 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
925 const char *dname;
926 BOOL found = False;
927 SMB_STRUCT_STAT sbuf;
928 pstring mask;
929 pstring pathreal;
930 pstring fname;
931 char *p, *q, *pdata = *ppdata;
932 uint32 reskey=0;
933 long prev_dirpos=0;
934 int mode=0;
935 SMB_OFF_T file_size = 0;
936 SMB_BIG_UINT allocation_size = 0;
937 uint32 len;
938 time_t mdate=0, adate=0, cdate=0;
939 char *nameptr;
940 char *last_entry_ptr;
941 BOOL was_8_3;
942 int nt_extmode; /* Used for NT connections instead of mode */
943 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
945 *fname = 0;
946 *out_of_space = False;
947 *got_exact_match = False;
949 if (!conn->dirptr)
950 return(False);
952 p = strrchr_m(path_mask,'/');
953 if(p != NULL) {
954 if(p[1] == '\0')
955 pstrcpy(mask,"*.*");
956 else
957 pstrcpy(mask, p+1);
958 } else
959 pstrcpy(mask, path_mask);
962 while (!found) {
963 BOOL got_match;
964 /* Needed if we run out of space */
965 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
966 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
969 * Due to bugs in NT client redirectors we are not using
970 * resume keys any more - set them to zero.
971 * Check out the related comments in findfirst/findnext.
972 * JRA.
975 reskey = 0;
977 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
978 (long)conn->dirptr,curr_dirpos));
980 if (!dname)
981 return(False);
983 pstrcpy(fname,dname);
985 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
986 got_match = mask_match(fname, mask, conn->case_sensitive);
988 if(!got_match && !mangle_is_8_3(fname, False)) {
991 * It turns out that NT matches wildcards against
992 * both long *and* short names. This may explain some
993 * of the wildcard wierdness from old DOS clients
994 * that some people have been seeing.... JRA.
997 pstring newname;
998 pstrcpy( newname, fname);
999 mangle_map( newname, True, False, SNUM(conn));
1000 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1001 got_match = mask_match(newname, mask, conn->case_sensitive);
1004 if(got_match) {
1005 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1006 if (dont_descend && !isdots)
1007 continue;
1009 pstrcpy(pathreal,conn->dirpath);
1010 if(needslash)
1011 pstrcat(pathreal,"/");
1012 pstrcat(pathreal,dname);
1014 if (INFO_LEVEL_IS_UNIX(info_level)) {
1015 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1016 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1017 pathreal,strerror(errno)));
1018 continue;
1020 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1022 /* Needed to show the msdfs symlinks as
1023 * directories */
1025 if(lp_host_msdfs() &&
1026 lp_msdfs_root(SNUM(conn)) &&
1027 is_msdfs_link(conn, pathreal, NULL, NULL,
1028 &sbuf)) {
1030 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1031 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1033 } else {
1035 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1036 pathreal,strerror(errno)));
1037 continue;
1041 mode = dos_mode(conn,pathreal,&sbuf);
1043 if (!dir_check_ftype(conn,mode,dirtype)) {
1044 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1045 continue;
1048 file_size = get_file_size(sbuf);
1049 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1050 mdate = sbuf.st_mtime;
1051 adate = sbuf.st_atime;
1052 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1054 if (lp_dos_filetime_resolution(SNUM(conn))) {
1055 cdate &= ~1;
1056 mdate &= ~1;
1057 adate &= ~1;
1060 if(mode & aDIR) {
1061 /* This is necessary, as otherwise the
1062 * desktop.ini file in this folder is
1063 * ignored */
1064 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1065 file_size = 0;
1068 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1070 found = True;
1074 mangle_map(fname,False,True,SNUM(conn));
1076 p = pdata;
1077 last_entry_ptr = p;
1079 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1081 switch (info_level) {
1082 case SMB_FIND_INFO_STANDARD:
1083 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1084 if(requires_resume_key) {
1085 SIVAL(p,0,reskey);
1086 p += 4;
1088 put_dos_date2(p,l1_fdateCreation,cdate);
1089 put_dos_date2(p,l1_fdateLastAccess,adate);
1090 put_dos_date2(p,l1_fdateLastWrite,mdate);
1091 SIVAL(p,l1_cbFile,(uint32)file_size);
1092 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1093 SSVAL(p,l1_attrFile,mode);
1094 p += l1_achName;
1095 nameptr = p;
1096 p += align_string(outbuf, p, 0);
1097 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1098 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1099 if (len > 2) {
1100 SCVAL(nameptr, -1, len - 2);
1101 } else {
1102 SCVAL(nameptr, -1, 0);
1104 } else {
1105 if (len > 1) {
1106 SCVAL(nameptr, -1, len - 1);
1107 } else {
1108 SCVAL(nameptr, -1, 0);
1111 p += len;
1112 break;
1114 case SMB_FIND_EA_SIZE:
1115 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1116 if(requires_resume_key) {
1117 SIVAL(p,0,reskey);
1118 p += 4;
1120 put_dos_date2(p,l2_fdateCreation,cdate);
1121 put_dos_date2(p,l2_fdateLastAccess,adate);
1122 put_dos_date2(p,l2_fdateLastWrite,mdate);
1123 SIVAL(p,l2_cbFile,(uint32)file_size);
1124 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1125 SSVAL(p,l2_attrFile,mode);
1127 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1128 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1130 p += l2_achName;
1131 nameptr = p - 1;
1132 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1133 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1134 if (len > 2) {
1135 len -= 2;
1136 } else {
1137 len = 0;
1139 } else {
1140 if (len > 1) {
1141 len -= 1;
1142 } else {
1143 len = 0;
1146 SCVAL(nameptr,0,len);
1147 p += len;
1148 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1149 break;
1151 case SMB_FIND_EA_LIST:
1153 struct ea_list *file_list = NULL;
1154 size_t ea_len = 0;
1156 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1157 if (!name_list) {
1158 return False;
1160 if(requires_resume_key) {
1161 SIVAL(p,0,reskey);
1162 p += 4;
1164 put_dos_date2(p,l2_fdateCreation,cdate);
1165 put_dos_date2(p,l2_fdateLastAccess,adate);
1166 put_dos_date2(p,l2_fdateLastWrite,mdate);
1167 SIVAL(p,l2_cbFile,(uint32)file_size);
1168 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1169 SSVAL(p,l2_attrFile,mode);
1170 p += l2_cbList; /* p now points to the EA area. */
1172 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1173 name_list = ea_list_union(name_list, file_list, &ea_len);
1175 /* We need to determine if this entry will fit in the space available. */
1176 /* Max string size is 255 bytes. */
1177 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1178 /* Move the dirptr back to prev_dirpos */
1179 dptr_SeekDir(conn->dirptr, prev_dirpos);
1180 *out_of_space = True;
1181 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1182 return False; /* Not finished - just out of space */
1185 /* Push the ea_data followed by the name. */
1186 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1187 nameptr = p;
1188 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1189 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1190 if (len > 2) {
1191 len -= 2;
1192 } else {
1193 len = 0;
1195 } else {
1196 if (len > 1) {
1197 len -= 1;
1198 } else {
1199 len = 0;
1202 SCVAL(nameptr,0,len);
1203 p += len + 1;
1204 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1205 break;
1208 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1209 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1210 was_8_3 = mangle_is_8_3(fname, True);
1211 p += 4;
1212 SIVAL(p,0,reskey); p += 4;
1213 put_long_date(p,cdate); p += 8;
1214 put_long_date(p,adate); p += 8;
1215 put_long_date(p,mdate); p += 8;
1216 put_long_date(p,mdate); p += 8;
1217 SOFF_T(p,0,file_size); p += 8;
1218 SOFF_T(p,0,allocation_size); p += 8;
1219 SIVAL(p,0,nt_extmode); p += 4;
1220 q = p; p += 4; /* q is placeholder for name length. */
1222 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1223 SIVAL(p,0,ea_size); /* Extended attributes */
1224 p += 4;
1226 /* Clear the short name buffer. This is
1227 * IMPORTANT as not doing so will trigger
1228 * a Win2k client bug. JRA.
1230 memset(p,'\0',26);
1231 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1232 pstring mangled_name;
1233 pstrcpy(mangled_name, fname);
1234 mangle_map(mangled_name,True,True,SNUM(conn));
1235 mangled_name[12] = 0;
1236 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1237 SSVAL(p, 0, len);
1238 } else {
1239 SSVAL(p,0,0);
1240 *(p+2) = 0;
1242 p += 2 + 24;
1243 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1244 SIVAL(q,0,len);
1245 p += len;
1246 len = PTR_DIFF(p, pdata);
1247 len = (len + 3) & ~3;
1248 SIVAL(pdata,0,len);
1249 p = pdata + len;
1250 break;
1252 case SMB_FIND_FILE_DIRECTORY_INFO:
1253 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1254 p += 4;
1255 SIVAL(p,0,reskey); p += 4;
1256 put_long_date(p,cdate); p += 8;
1257 put_long_date(p,adate); p += 8;
1258 put_long_date(p,mdate); p += 8;
1259 put_long_date(p,mdate); p += 8;
1260 SOFF_T(p,0,file_size); p += 8;
1261 SOFF_T(p,0,allocation_size); p += 8;
1262 SIVAL(p,0,nt_extmode); p += 4;
1263 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1264 SIVAL(p,0,len);
1265 p += 4 + len;
1266 len = PTR_DIFF(p, pdata);
1267 len = (len + 3) & ~3;
1268 SIVAL(pdata,0,len);
1269 p = pdata + len;
1270 break;
1272 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1273 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1274 p += 4;
1275 SIVAL(p,0,reskey); p += 4;
1276 put_long_date(p,cdate); p += 8;
1277 put_long_date(p,adate); p += 8;
1278 put_long_date(p,mdate); p += 8;
1279 put_long_date(p,mdate); p += 8;
1280 SOFF_T(p,0,file_size); p += 8;
1281 SOFF_T(p,0,allocation_size); p += 8;
1282 SIVAL(p,0,nt_extmode); p += 4;
1283 q = p; p += 4; /* q is placeholder for name length. */
1285 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1286 SIVAL(p,0,ea_size); /* Extended attributes */
1287 p +=4;
1289 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1290 SIVAL(q, 0, len);
1291 p += len;
1293 len = PTR_DIFF(p, pdata);
1294 len = (len + 3) & ~3;
1295 SIVAL(pdata,0,len);
1296 p = pdata + len;
1297 break;
1299 case SMB_FIND_FILE_NAMES_INFO:
1300 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1301 p += 4;
1302 SIVAL(p,0,reskey); p += 4;
1303 p += 4;
1304 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1305 acl on a dir (tridge) */
1306 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1307 SIVAL(p, -4, len);
1308 p += len;
1309 len = PTR_DIFF(p, pdata);
1310 len = (len + 3) & ~3;
1311 SIVAL(pdata,0,len);
1312 p = pdata + len;
1313 break;
1315 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1316 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1317 p += 4;
1318 SIVAL(p,0,reskey); p += 4;
1319 put_long_date(p,cdate); p += 8;
1320 put_long_date(p,adate); p += 8;
1321 put_long_date(p,mdate); p += 8;
1322 put_long_date(p,mdate); p += 8;
1323 SOFF_T(p,0,file_size); p += 8;
1324 SOFF_T(p,0,allocation_size); p += 8;
1325 SIVAL(p,0,nt_extmode); p += 4;
1326 q = p; p += 4; /* q is placeholder for name length. */
1328 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1329 SIVAL(p,0,ea_size); /* Extended attributes */
1330 p +=4;
1332 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1333 SIVAL(p,0,sbuf.st_dev); p += 4;
1334 SIVAL(p,0,sbuf.st_ino); p += 4;
1335 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1336 SIVAL(q, 0, len);
1337 p += len;
1338 len = PTR_DIFF(p, pdata);
1339 len = (len + 3) & ~3;
1340 SIVAL(pdata,0,len);
1341 p = pdata + len;
1342 break;
1344 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1346 was_8_3 = mangle_is_8_3(fname, True);
1347 p += 4;
1348 SIVAL(p,0,reskey); p += 4;
1349 put_long_date(p,cdate); p += 8;
1350 put_long_date(p,adate); p += 8;
1351 put_long_date(p,mdate); p += 8;
1352 put_long_date(p,mdate); p += 8;
1353 SOFF_T(p,0,file_size); p += 8;
1354 SOFF_T(p,0,allocation_size); p += 8;
1355 SIVAL(p,0,nt_extmode); p += 4;
1356 q = p; p += 4; /* q is placeholder for name length */
1358 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1359 SIVAL(p,0,ea_size); /* Extended attributes */
1360 p +=4;
1362 /* Clear the short name buffer. This is
1363 * IMPORTANT as not doing so will trigger
1364 * a Win2k client bug. JRA.
1366 memset(p,'\0',26);
1367 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1368 pstring mangled_name;
1369 pstrcpy(mangled_name, fname);
1370 mangle_map(mangled_name,True,True,SNUM(conn));
1371 mangled_name[12] = 0;
1372 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1373 SSVAL(p, 0, len);
1374 } else {
1375 SSVAL(p,0,0);
1376 *(p+2) = 0;
1378 p += 26;
1379 SSVAL(p,0,0); p += 2; /* Reserved ? */
1380 SIVAL(p,0,sbuf.st_dev); p += 4;
1381 SIVAL(p,0,sbuf.st_ino); p += 4;
1382 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1383 SIVAL(q,0,len);
1384 p += len;
1385 len = PTR_DIFF(p, pdata);
1386 len = (len + 3) & ~3;
1387 SIVAL(pdata,0,len);
1388 p = pdata + len;
1389 break;
1391 /* CIFS UNIX Extension. */
1393 case SMB_FIND_FILE_UNIX:
1394 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1395 p+= 4;
1396 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1398 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1399 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1400 p+= 8;
1402 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1403 p+= 8;
1405 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1406 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1407 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1408 p+= 24;
1410 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1411 SIVAL(p,4,0);
1412 p+= 8;
1414 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1415 SIVAL(p,4,0);
1416 p+= 8;
1418 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1419 p+= 4;
1421 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1422 SIVAL(p,4,0);
1423 p+= 8;
1425 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1426 SIVAL(p,4,0);
1427 p+= 8;
1429 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1430 p+= 8;
1432 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1433 SIVAL(p,4,0);
1434 p+= 8;
1436 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1437 SIVAL(p,4,0);
1438 p+= 8;
1440 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1441 p += len;
1443 len = PTR_DIFF(p, pdata);
1444 len = (len + 3) & ~3;
1445 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1446 p = pdata + len;
1447 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1449 break;
1451 default:
1452 return(False);
1456 if (PTR_DIFF(p,pdata) > space_remaining) {
1457 /* Move the dirptr back to prev_dirpos */
1458 dptr_SeekDir(conn->dirptr, prev_dirpos);
1459 *out_of_space = True;
1460 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1461 return False; /* Not finished - just out of space */
1464 /* Setup the last entry pointer, as an offset from base_data */
1465 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1466 /* Advance the data pointer to the next slot */
1467 *ppdata = p;
1469 return(found);
1472 /****************************************************************************
1473 Reply to a TRANS2_FINDFIRST.
1474 ****************************************************************************/
1476 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1477 char **pparams, int total_params, char **ppdata, int total_data,
1478 unsigned int max_data_bytes)
1480 /* We must be careful here that we don't return more than the
1481 allowed number of data bytes. If this means returning fewer than
1482 maxentries then so be it. We assume that the redirector has
1483 enough room for the fixed number of parameter bytes it has
1484 requested. */
1485 char *params = *pparams;
1486 char *pdata = *ppdata;
1487 int dirtype = SVAL(params,0);
1488 int maxentries = SVAL(params,2);
1489 uint16 findfirst_flags = SVAL(params,4);
1490 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1491 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1492 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1493 int info_level = SVAL(params,6);
1494 pstring directory;
1495 pstring mask;
1496 char *p;
1497 int last_entry_off=0;
1498 int dptr_num = -1;
1499 int numentries = 0;
1500 int i;
1501 BOOL finished = False;
1502 BOOL dont_descend = False;
1503 BOOL out_of_space = False;
1504 int space_remaining;
1505 BOOL bad_path = False;
1506 SMB_STRUCT_STAT sbuf;
1507 TALLOC_CTX *ea_ctx = NULL;
1508 struct ea_list *ea_list = NULL;
1509 NTSTATUS ntstatus = NT_STATUS_OK;
1511 if (total_params < 12) {
1512 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1515 *directory = *mask = 0;
1517 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1518 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1519 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1520 info_level, max_data_bytes));
1522 if (!maxentries) {
1523 /* W2K3 seems to treat zero as 1. */
1524 maxentries = 1;
1527 switch (info_level) {
1528 case SMB_FIND_INFO_STANDARD:
1529 case SMB_FIND_EA_SIZE:
1530 case SMB_FIND_EA_LIST:
1531 case SMB_FIND_FILE_DIRECTORY_INFO:
1532 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1533 case SMB_FIND_FILE_NAMES_INFO:
1534 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1535 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1536 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1537 break;
1538 case SMB_FIND_FILE_UNIX:
1539 if (!lp_unix_extensions())
1540 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1541 break;
1542 default:
1543 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1546 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1547 if (!NT_STATUS_IS_OK(ntstatus)) {
1548 return ERROR_NT(ntstatus);
1551 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1553 unix_convert(directory,conn,0,&bad_path,&sbuf);
1554 if (bad_path) {
1555 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1557 if(!check_name(directory,conn)) {
1558 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1561 p = strrchr_m(directory,'/');
1562 if(p == NULL) {
1563 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1564 if((directory[0] == '.') && (directory[1] == '\0'))
1565 pstrcpy(mask,"*");
1566 else
1567 pstrcpy(mask,directory);
1568 pstrcpy(directory,"./");
1569 } else {
1570 pstrcpy(mask,p+1);
1571 *p = 0;
1574 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1576 if (info_level == SMB_FIND_EA_LIST) {
1577 uint32 ea_size;
1579 if (total_data < 4) {
1580 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1583 ea_size = IVAL(pdata,0);
1584 if (ea_size != total_data) {
1585 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1586 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1587 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1590 if (!lp_ea_support(SNUM(conn))) {
1591 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1594 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1595 return ERROR_NT(NT_STATUS_NO_MEMORY);
1598 /* Pull out the list of names. */
1599 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
1600 if (!ea_list) {
1601 talloc_destroy(ea_ctx);
1602 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1606 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1607 if( pdata == NULL ) {
1608 talloc_destroy(ea_ctx);
1609 return ERROR_NT(NT_STATUS_NO_MEMORY);
1612 *ppdata = pdata;
1613 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1615 /* Realloc the params space */
1616 params = SMB_REALLOC(*pparams, 10);
1617 if (params == NULL) {
1618 talloc_destroy(ea_ctx);
1619 return ERROR_NT(NT_STATUS_NO_MEMORY);
1621 *pparams = params;
1623 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1624 if (dptr_num < 0) {
1625 talloc_destroy(ea_ctx);
1626 return(UNIXERROR(ERRDOS,ERRbadfile));
1629 /* Save the wildcard match and attribs we are using on this directory -
1630 needed as lanman2 assumes these are being saved between calls */
1632 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1633 dptr_close(&dptr_num);
1634 talloc_destroy(ea_ctx);
1635 return ERROR_NT(NT_STATUS_NO_MEMORY);
1638 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1640 /* We don't need to check for VOL here as this is returned by
1641 a different TRANS2 call. */
1643 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1644 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1645 dont_descend = True;
1647 p = pdata;
1648 space_remaining = max_data_bytes;
1649 out_of_space = False;
1651 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1652 BOOL got_exact_match = False;
1654 /* this is a heuristic to avoid seeking the dirptr except when
1655 absolutely necessary. It allows for a filename of about 40 chars */
1656 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1657 out_of_space = True;
1658 finished = False;
1659 } else {
1660 finished = !get_lanman2_dir_entry(conn,
1661 inbuf, outbuf,
1662 mask,dirtype,info_level,
1663 requires_resume_key,dont_descend,
1664 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1665 &last_entry_off, ea_list, ea_ctx);
1668 if (finished && out_of_space)
1669 finished = False;
1671 if (!finished && !out_of_space)
1672 numentries++;
1675 * As an optimisation if we know we aren't looking
1676 * for a wildcard name (ie. the name matches the wildcard exactly)
1677 * then we can finish on any (first) match.
1678 * This speeds up large directory searches. JRA.
1681 if(got_exact_match)
1682 finished = True;
1684 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1687 talloc_destroy(ea_ctx);
1689 /* Check if we can close the dirptr */
1690 if(close_after_first || (finished && close_if_end)) {
1691 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1692 dptr_close(&dptr_num);
1696 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1697 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1698 * the protocol level is less than NT1. Tested with smbclient. JRA.
1699 * This should fix the OS/2 client bug #2335.
1702 if(numentries == 0) {
1703 dptr_close(&dptr_num);
1704 if (Protocol < PROTOCOL_NT1) {
1705 return ERROR_DOS(ERRDOS,ERRnofiles);
1706 } else {
1707 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1711 /* At this point pdata points to numentries directory entries. */
1713 /* Set up the return parameter block */
1714 SSVAL(params,0,dptr_num);
1715 SSVAL(params,2,numentries);
1716 SSVAL(params,4,finished);
1717 SSVAL(params,6,0); /* Never an EA error */
1718 SSVAL(params,8,last_entry_off);
1720 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1722 if ((! *directory) && dptr_path(dptr_num))
1723 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1725 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1726 smb_fn_name(CVAL(inbuf,smb_com)),
1727 mask, directory, dirtype, numentries ) );
1730 * Force a name mangle here to ensure that the
1731 * mask as an 8.3 name is top of the mangled cache.
1732 * The reasons for this are subtle. Don't remove
1733 * this code unless you know what you are doing
1734 * (see PR#13758). JRA.
1737 if(!mangle_is_8_3_wildcards( mask, False))
1738 mangle_map(mask, True, True, SNUM(conn));
1740 return(-1);
1743 /****************************************************************************
1744 Reply to a TRANS2_FINDNEXT.
1745 ****************************************************************************/
1747 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1748 char **pparams, int total_params, char **ppdata, int total_data,
1749 unsigned int max_data_bytes)
1751 /* We must be careful here that we don't return more than the
1752 allowed number of data bytes. If this means returning fewer than
1753 maxentries then so be it. We assume that the redirector has
1754 enough room for the fixed number of parameter bytes it has
1755 requested. */
1756 char *params = *pparams;
1757 char *pdata = *ppdata;
1758 int dptr_num = SVAL(params,0);
1759 int maxentries = SVAL(params,2);
1760 uint16 info_level = SVAL(params,4);
1761 uint32 resume_key = IVAL(params,6);
1762 uint16 findnext_flags = SVAL(params,10);
1763 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1764 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1765 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1766 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1767 pstring resume_name;
1768 pstring mask;
1769 pstring directory;
1770 char *p;
1771 uint16 dirtype;
1772 int numentries = 0;
1773 int i, last_entry_off=0;
1774 BOOL finished = False;
1775 BOOL dont_descend = False;
1776 BOOL out_of_space = False;
1777 int space_remaining;
1778 TALLOC_CTX *ea_ctx = NULL;
1779 struct ea_list *ea_list = NULL;
1780 NTSTATUS ntstatus = NT_STATUS_OK;
1782 if (total_params < 12) {
1783 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1786 *mask = *directory = *resume_name = 0;
1788 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1789 if (!NT_STATUS_IS_OK(ntstatus)) {
1790 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1791 complain (it thinks we're asking for the directory above the shared
1792 path or an invalid name). Catch this as the resume name is only compared, never used in
1793 a file access. JRA. */
1794 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1795 pstrcpy(resume_name, "..");
1796 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1797 pstrcpy(resume_name, ".");
1798 } else {
1799 return ERROR_NT(ntstatus);
1803 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1804 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1805 resume_key = %d resume name = %s continue=%d level = %d\n",
1806 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1807 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1809 if (!maxentries) {
1810 /* W2K3 seems to treat zero as 1. */
1811 maxentries = 1;
1814 switch (info_level) {
1815 case SMB_FIND_INFO_STANDARD:
1816 case SMB_FIND_EA_SIZE:
1817 case SMB_FIND_EA_LIST:
1818 case SMB_FIND_FILE_DIRECTORY_INFO:
1819 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1820 case SMB_FIND_FILE_NAMES_INFO:
1821 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1822 break;
1823 case SMB_FIND_FILE_UNIX:
1824 if (!lp_unix_extensions())
1825 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1826 break;
1827 default:
1828 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1831 if (info_level == SMB_FIND_EA_LIST) {
1832 uint32 ea_size;
1834 if (total_data < 4) {
1835 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1838 ea_size = IVAL(pdata,0);
1839 if (ea_size != total_data) {
1840 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1841 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1842 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1845 if (!lp_ea_support(SNUM(conn))) {
1846 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1849 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1850 return ERROR_NT(NT_STATUS_NO_MEMORY);
1853 /* Pull out the list of names. */
1854 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
1855 if (!ea_list) {
1856 talloc_destroy(ea_ctx);
1857 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1861 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1862 if(pdata == NULL) {
1863 talloc_destroy(ea_ctx);
1864 return ERROR_NT(NT_STATUS_NO_MEMORY);
1867 *ppdata = pdata;
1868 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1870 /* Realloc the params space */
1871 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1872 if( params == NULL ) {
1873 talloc_destroy(ea_ctx);
1874 return ERROR_NT(NT_STATUS_NO_MEMORY);
1877 *pparams = params;
1879 /* Check that the dptr is valid */
1880 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1881 talloc_destroy(ea_ctx);
1882 return ERROR_DOS(ERRDOS,ERRnofiles);
1885 string_set(&conn->dirpath,dptr_path(dptr_num));
1887 /* Get the wildcard mask from the dptr */
1888 if((p = dptr_wcard(dptr_num))== NULL) {
1889 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1890 talloc_destroy(ea_ctx);
1891 return ERROR_DOS(ERRDOS,ERRnofiles);
1894 pstrcpy(mask, p);
1895 pstrcpy(directory,conn->dirpath);
1897 /* Get the attr mask from the dptr */
1898 dirtype = dptr_attr(dptr_num);
1900 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1901 dptr_num, mask, dirtype,
1902 (long)conn->dirptr,
1903 dptr_TellDir(conn->dirptr)));
1905 /* We don't need to check for VOL here as this is returned by
1906 a different TRANS2 call. */
1908 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1909 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1910 dont_descend = True;
1912 p = pdata;
1913 space_remaining = max_data_bytes;
1914 out_of_space = False;
1917 * Seek to the correct position. We no longer use the resume key but
1918 * depend on the last file name instead.
1921 if(*resume_name && !continue_bit) {
1922 SMB_STRUCT_STAT st;
1924 long current_pos = 0;
1926 * Remember, mangle_map is called by
1927 * get_lanman2_dir_entry(), so the resume name
1928 * could be mangled. Ensure we check the unmangled name.
1931 if (mangle_is_mangled(resume_name)) {
1932 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1936 * Fix for NT redirector problem triggered by resume key indexes
1937 * changing between directory scans. We now return a resume key of 0
1938 * and instead look for the filename to continue from (also given
1939 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1940 * findfirst/findnext (as is usual) then the directory pointer
1941 * should already be at the correct place.
1944 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
1945 } /* end if resume_name && !continue_bit */
1947 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1948 BOOL got_exact_match = False;
1950 /* this is a heuristic to avoid seeking the dirptr except when
1951 absolutely necessary. It allows for a filename of about 40 chars */
1952 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1953 out_of_space = True;
1954 finished = False;
1955 } else {
1956 finished = !get_lanman2_dir_entry(conn,
1957 inbuf, outbuf,
1958 mask,dirtype,info_level,
1959 requires_resume_key,dont_descend,
1960 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1961 &last_entry_off, ea_list, ea_ctx);
1964 if (finished && out_of_space)
1965 finished = False;
1967 if (!finished && !out_of_space)
1968 numentries++;
1971 * As an optimisation if we know we aren't looking
1972 * for a wildcard name (ie. the name matches the wildcard exactly)
1973 * then we can finish on any (first) match.
1974 * This speeds up large directory searches. JRA.
1977 if(got_exact_match)
1978 finished = True;
1980 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1983 talloc_destroy(ea_ctx);
1985 /* Check if we can close the dirptr */
1986 if(close_after_request || (finished && close_if_end)) {
1987 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1988 dptr_close(&dptr_num); /* This frees up the saved mask */
1991 /* Set up the return parameter block */
1992 SSVAL(params,0,numentries);
1993 SSVAL(params,2,finished);
1994 SSVAL(params,4,0); /* Never an EA error */
1995 SSVAL(params,6,last_entry_off);
1997 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1999 if ((! *directory) && dptr_path(dptr_num))
2000 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2002 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2003 smb_fn_name(CVAL(inbuf,smb_com)),
2004 mask, directory, dirtype, numentries ) );
2006 return(-1);
2009 /****************************************************************************
2010 Reply to a TRANS2_QFSINFO (query filesystem info).
2011 ****************************************************************************/
2013 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2014 char **pparams, int total_params, char **ppdata, int total_data,
2015 unsigned int max_data_bytes)
2017 char *pdata = *ppdata;
2018 char *params = *pparams;
2019 uint16 info_level = SVAL(params,0);
2020 int data_len, len;
2021 SMB_STRUCT_STAT st;
2022 char *vname = volume_label(SNUM(conn));
2023 int snum = SNUM(conn);
2024 char *fstype = lp_fstype(SNUM(conn));
2025 int quota_flag = 0;
2027 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2029 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2030 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2031 return ERROR_DOS(ERRSRV,ERRinvdevice);
2034 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2035 if ( pdata == NULL ) {
2036 return ERROR_NT(NT_STATUS_NO_MEMORY);
2039 *ppdata = pdata;
2040 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2042 switch (info_level) {
2043 case SMB_INFO_ALLOCATION:
2045 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2046 data_len = 18;
2047 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2048 return(UNIXERROR(ERRHRD,ERRgeneral));
2051 block_size = lp_block_size(snum);
2052 if (bsize < block_size) {
2053 SMB_BIG_UINT factor = block_size/bsize;
2054 bsize = block_size;
2055 dsize /= factor;
2056 dfree /= factor;
2058 if (bsize > block_size) {
2059 SMB_BIG_UINT factor = bsize/block_size;
2060 bsize = block_size;
2061 dsize *= factor;
2062 dfree *= factor;
2064 bytes_per_sector = 512;
2065 sectors_per_unit = bsize/bytes_per_sector;
2067 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2068 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2069 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2071 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2072 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2073 SIVAL(pdata,l1_cUnit,dsize);
2074 SIVAL(pdata,l1_cUnitAvail,dfree);
2075 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2076 break;
2079 case SMB_INFO_VOLUME:
2080 /* Return volume name */
2082 * Add volume serial number - hash of a combination of
2083 * the called hostname and the service name.
2085 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2086 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
2087 SCVAL(pdata,l2_vol_cch,len);
2088 data_len = l2_vol_szVolLabel + len;
2089 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2090 (unsigned)st.st_ctime, len, vname));
2091 break;
2093 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2094 case SMB_FS_ATTRIBUTE_INFORMATION:
2097 #if defined(HAVE_SYS_QUOTAS)
2098 quota_flag = FILE_VOLUME_QUOTAS;
2099 #endif
2101 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2102 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2103 quota_flag); /* FS ATTRIBUTES */
2105 SIVAL(pdata,4,255); /* Max filename component length */
2106 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2107 and will think we can't do long filenames */
2108 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2109 SIVAL(pdata,8,len);
2110 data_len = 12 + len;
2111 break;
2113 case SMB_QUERY_FS_LABEL_INFO:
2114 case SMB_FS_LABEL_INFORMATION:
2115 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2116 data_len = 4 + len;
2117 SIVAL(pdata,0,len);
2118 break;
2120 case SMB_QUERY_FS_VOLUME_INFO:
2121 case SMB_FS_VOLUME_INFORMATION:
2124 * Add volume serial number - hash of a combination of
2125 * the called hostname and the service name.
2127 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2128 (str_checksum(get_local_machine_name())<<16));
2130 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2131 SIVAL(pdata,12,len);
2132 data_len = 18+len;
2133 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2134 (int)strlen(vname),vname, lp_servicename(snum)));
2135 break;
2137 case SMB_QUERY_FS_SIZE_INFO:
2138 case SMB_FS_SIZE_INFORMATION:
2140 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2141 data_len = 24;
2142 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2143 return(UNIXERROR(ERRHRD,ERRgeneral));
2145 block_size = lp_block_size(snum);
2146 if (bsize < block_size) {
2147 SMB_BIG_UINT factor = block_size/bsize;
2148 bsize = block_size;
2149 dsize /= factor;
2150 dfree /= factor;
2152 if (bsize > block_size) {
2153 SMB_BIG_UINT factor = bsize/block_size;
2154 bsize = block_size;
2155 dsize *= factor;
2156 dfree *= factor;
2158 bytes_per_sector = 512;
2159 sectors_per_unit = bsize/bytes_per_sector;
2160 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2161 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2162 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2163 SBIG_UINT(pdata,0,dsize);
2164 SBIG_UINT(pdata,8,dfree);
2165 SIVAL(pdata,16,sectors_per_unit);
2166 SIVAL(pdata,20,bytes_per_sector);
2167 break;
2170 case SMB_FS_FULL_SIZE_INFORMATION:
2172 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2173 data_len = 32;
2174 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2175 return(UNIXERROR(ERRHRD,ERRgeneral));
2177 block_size = lp_block_size(snum);
2178 if (bsize < block_size) {
2179 SMB_BIG_UINT factor = block_size/bsize;
2180 bsize = block_size;
2181 dsize /= factor;
2182 dfree /= factor;
2184 if (bsize > block_size) {
2185 SMB_BIG_UINT factor = bsize/block_size;
2186 bsize = block_size;
2187 dsize *= factor;
2188 dfree *= factor;
2190 bytes_per_sector = 512;
2191 sectors_per_unit = bsize/bytes_per_sector;
2192 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2193 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2194 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2195 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2196 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2197 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2198 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2199 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2200 break;
2203 case SMB_QUERY_FS_DEVICE_INFO:
2204 case SMB_FS_DEVICE_INFORMATION:
2205 data_len = 8;
2206 SIVAL(pdata,0,0); /* dev type */
2207 SIVAL(pdata,4,0); /* characteristics */
2208 break;
2210 #ifdef HAVE_SYS_QUOTAS
2211 case SMB_FS_QUOTA_INFORMATION:
2213 * what we have to send --metze:
2215 * Unknown1: 24 NULL bytes
2216 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2217 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2218 * Quota Flags: 2 byte :
2219 * Unknown3: 6 NULL bytes
2221 * 48 bytes total
2223 * details for Quota Flags:
2225 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2226 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2227 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2228 * 0x0001 Enable Quotas: enable quota for this fs
2232 /* we need to fake up a fsp here,
2233 * because its not send in this call
2235 files_struct fsp;
2236 SMB_NTQUOTA_STRUCT quotas;
2238 ZERO_STRUCT(fsp);
2239 ZERO_STRUCT(quotas);
2241 fsp.conn = conn;
2242 fsp.fnum = -1;
2243 fsp.fd = -1;
2245 /* access check */
2246 if (current_user.uid != 0) {
2247 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2248 lp_servicename(SNUM(conn)),conn->user));
2249 return ERROR_DOS(ERRDOS,ERRnoaccess);
2252 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2253 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2254 return ERROR_DOS(ERRSRV,ERRerror);
2257 data_len = 48;
2259 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2261 /* Unknown1 24 NULL bytes*/
2262 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2263 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2264 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2266 /* Default Soft Quota 8 bytes */
2267 SBIG_UINT(pdata,24,quotas.softlim);
2269 /* Default Hard Quota 8 bytes */
2270 SBIG_UINT(pdata,32,quotas.hardlim);
2272 /* Quota flag 2 bytes */
2273 SSVAL(pdata,40,quotas.qflags);
2275 /* Unknown3 6 NULL bytes */
2276 SSVAL(pdata,42,0);
2277 SIVAL(pdata,44,0);
2279 break;
2281 #endif /* HAVE_SYS_QUOTAS */
2282 case SMB_FS_OBJECTID_INFORMATION:
2283 data_len = 64;
2284 break;
2287 * Query the version and capabilities of the CIFS UNIX extensions
2288 * in use.
2291 case SMB_QUERY_CIFS_UNIX_INFO:
2292 if (!lp_unix_extensions())
2293 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2294 data_len = 12;
2295 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2296 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2297 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2298 break;
2300 case SMB_MAC_QUERY_FS_INFO:
2302 * Thursby MAC extension... ONLY on NTFS filesystems
2303 * once we do streams then we don't need this
2305 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2306 data_len = 88;
2307 SIVAL(pdata,84,0x100); /* Don't support mac... */
2308 break;
2310 /* drop through */
2311 default:
2312 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2316 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2318 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2320 return -1;
2323 #ifdef HAVE_SYS_QUOTAS
2324 /****************************************************************************
2325 Reply to a TRANS2_SETFSINFO (set filesystem info).
2326 ****************************************************************************/
2328 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2329 char **pparams, int total_params, char **ppdata, int total_data,
2330 unsigned int max_data_bytes)
2332 char *pdata = *ppdata;
2333 char *params = *pparams;
2334 files_struct *fsp = NULL;
2335 uint16 info_level;
2336 int outsize;
2337 SMB_NTQUOTA_STRUCT quotas;
2339 ZERO_STRUCT(quotas);
2341 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2343 /* access check */
2344 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2345 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2346 lp_servicename(SNUM(conn)),conn->user));
2347 return ERROR_DOS(ERRSRV,ERRaccess);
2350 /* */
2351 if (total_params < 4) {
2352 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2353 total_params));
2354 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2357 fsp = file_fsp(params,0);
2359 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2360 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2361 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2364 info_level = SVAL(params,2);
2366 switch(info_level) {
2367 case SMB_FS_QUOTA_INFORMATION:
2368 /* note: normaly there're 48 bytes,
2369 * but we didn't use the last 6 bytes for now
2370 * --metze
2372 if (total_data < 42) {
2373 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2374 total_data));
2375 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2378 /* unknown_1 24 NULL bytes in pdata*/
2380 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2381 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2382 #ifdef LARGE_SMB_OFF_T
2383 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2384 #else /* LARGE_SMB_OFF_T */
2385 if ((IVAL(pdata,28) != 0)&&
2386 ((quotas.softlim != 0xFFFFFFFF)||
2387 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2388 /* more than 32 bits? */
2389 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2391 #endif /* LARGE_SMB_OFF_T */
2393 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2394 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2395 #ifdef LARGE_SMB_OFF_T
2396 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2397 #else /* LARGE_SMB_OFF_T */
2398 if ((IVAL(pdata,36) != 0)&&
2399 ((quotas.hardlim != 0xFFFFFFFF)||
2400 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2401 /* more than 32 bits? */
2402 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2404 #endif /* LARGE_SMB_OFF_T */
2406 /* quota_flags 2 bytes **/
2407 quotas.qflags = SVAL(pdata,40);
2409 /* unknown_2 6 NULL bytes follow*/
2411 /* now set the quotas */
2412 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2413 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2414 return ERROR_DOS(ERRSRV,ERRerror);
2417 break;
2418 default:
2419 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2420 info_level));
2421 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2422 break;
2426 * sending this reply works fine,
2427 * but I'm not sure it's the same
2428 * like windows do...
2429 * --metze
2431 outsize = set_message(outbuf,10,0,True);
2433 return outsize;
2435 #endif /* HAVE_SYS_QUOTAS */
2437 /****************************************************************************
2438 Utility function to set bad path error.
2439 ****************************************************************************/
2441 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2443 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2444 err, (int)bad_path ));
2446 if(err == ENOENT) {
2447 if (bad_path) {
2448 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2449 } else {
2450 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2453 return UNIXERROR(def_class,def_code);
2456 #if defined(HAVE_POSIX_ACLS)
2457 /****************************************************************************
2458 Utility function to count the number of entries in a POSIX acl.
2459 ****************************************************************************/
2461 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2463 unsigned int ace_count = 0;
2464 int entry_id = SMB_ACL_FIRST_ENTRY;
2465 SMB_ACL_ENTRY_T entry;
2467 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2468 /* get_next... */
2469 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2470 entry_id = SMB_ACL_NEXT_ENTRY;
2472 ace_count++;
2474 return ace_count;
2477 /****************************************************************************
2478 Utility function to marshall a POSIX acl into wire format.
2479 ****************************************************************************/
2481 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2483 int entry_id = SMB_ACL_FIRST_ENTRY;
2484 SMB_ACL_ENTRY_T entry;
2486 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2487 SMB_ACL_TAG_T tagtype;
2488 SMB_ACL_PERMSET_T permset;
2489 unsigned char perms = 0;
2490 unsigned int own_grp;
2492 /* get_next... */
2493 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2494 entry_id = SMB_ACL_NEXT_ENTRY;
2497 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2498 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2499 return False;
2502 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2503 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2504 return False;
2507 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2508 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2509 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2511 SCVAL(pdata,1,perms);
2513 switch (tagtype) {
2514 case SMB_ACL_USER_OBJ:
2515 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2516 own_grp = (unsigned int)pst->st_uid;
2517 SIVAL(pdata,2,own_grp);
2518 SIVAL(pdata,6,0);
2519 break;
2520 case SMB_ACL_USER:
2522 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2523 if (!puid) {
2524 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2526 own_grp = (unsigned int)*puid;
2527 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2528 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2529 SIVAL(pdata,2,own_grp);
2530 SIVAL(pdata,6,0);
2531 break;
2533 case SMB_ACL_GROUP_OBJ:
2534 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2535 own_grp = (unsigned int)pst->st_gid;
2536 SIVAL(pdata,2,own_grp);
2537 SIVAL(pdata,6,0);
2538 break;
2539 case SMB_ACL_GROUP:
2541 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2542 if (!pgid) {
2543 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2545 own_grp = (unsigned int)*pgid;
2546 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2547 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2548 SIVAL(pdata,2,own_grp);
2549 SIVAL(pdata,6,0);
2550 break;
2552 case SMB_ACL_MASK:
2553 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2554 SIVAL(pdata,2,0xFFFFFFFF);
2555 SIVAL(pdata,6,0xFFFFFFFF);
2556 break;
2557 case SMB_ACL_OTHER:
2558 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2559 SIVAL(pdata,2,0xFFFFFFFF);
2560 SIVAL(pdata,6,0xFFFFFFFF);
2561 break;
2562 default:
2563 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2564 return False;
2566 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2569 return True;
2571 #endif
2573 /****************************************************************************
2574 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2575 file name or file id).
2576 ****************************************************************************/
2578 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2579 char **pparams, int total_params, char **ppdata, int total_data,
2580 unsigned int max_data_bytes)
2582 char *params = *pparams;
2583 char *pdata = *ppdata;
2584 uint16 tran_call = SVAL(inbuf, smb_setup0);
2585 uint16 info_level;
2586 int mode=0;
2587 SMB_OFF_T file_size=0;
2588 SMB_BIG_UINT allocation_size=0;
2589 unsigned int data_size = 0;
2590 unsigned int param_size = 2;
2591 SMB_STRUCT_STAT sbuf;
2592 pstring fname, dos_fname;
2593 char *fullpathname;
2594 char *base_name;
2595 char *p;
2596 SMB_OFF_T pos = 0;
2597 BOOL bad_path = False;
2598 BOOL delete_pending = False;
2599 int len;
2600 time_t c_time;
2601 files_struct *fsp = NULL;
2602 TALLOC_CTX *ea_ctx = NULL;
2603 struct ea_list *ea_list = NULL;
2604 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2606 if (!params)
2607 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2609 ZERO_STRUCT(sbuf);
2611 if (tran_call == TRANSACT2_QFILEINFO) {
2612 if (total_params < 4) {
2613 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2616 fsp = file_fsp(params,0);
2617 info_level = SVAL(params,2);
2619 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2621 if(fsp && (fsp->fake_file_handle)) {
2623 * This is actually for the QUOTA_FAKE_FILE --metze
2626 pstrcpy(fname, fsp->fsp_name);
2627 /* We know this name is ok, it's already passed the checks. */
2629 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2631 * This is actually a QFILEINFO on a directory
2632 * handle (returned from an NT SMB). NT5.0 seems
2633 * to do this call. JRA.
2635 /* We know this name is ok, it's already passed the checks. */
2636 pstrcpy(fname, fsp->fsp_name);
2638 if (INFO_LEVEL_IS_UNIX(info_level)) {
2639 /* Always do lstat for UNIX calls. */
2640 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2641 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2642 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2644 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2645 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2646 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2649 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2650 } else {
2652 * Original code - this is an open file.
2654 CHECK_FSP(fsp,conn);
2656 pstrcpy(fname, fsp->fsp_name);
2657 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2658 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2659 return(UNIXERROR(ERRDOS,ERRbadfid));
2661 pos = fsp->position_information;
2662 delete_pending = fsp->delete_on_close;
2663 desired_access = fsp->desired_access;
2665 } else {
2666 NTSTATUS status = NT_STATUS_OK;
2668 /* qpathinfo */
2669 if (total_params < 6) {
2670 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2673 info_level = SVAL(params,0);
2675 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2677 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 return ERROR_NT(status);
2682 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2684 unix_convert(fname,conn,0,&bad_path,&sbuf);
2685 if (bad_path) {
2686 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2688 if (!check_name(fname,conn)) {
2689 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2690 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2693 if (INFO_LEVEL_IS_UNIX(info_level)) {
2694 /* Always do lstat for UNIX calls. */
2695 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2696 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2697 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2699 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2700 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2701 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2705 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2706 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2708 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2709 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2711 p = strrchr_m(fname,'/');
2712 if (!p)
2713 base_name = fname;
2714 else
2715 base_name = p+1;
2717 mode = dos_mode(conn,fname,&sbuf);
2718 if (!mode)
2719 mode = FILE_ATTRIBUTE_NORMAL;
2721 fullpathname = fname;
2722 file_size = get_file_size(sbuf);
2723 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2724 if (mode & aDIR) {
2725 /* This is necessary, as otherwise the desktop.ini file in
2726 * this folder is ignored */
2727 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2728 file_size = 0;
2731 /* Pull any EA list from the data portion. */
2732 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2733 uint32 ea_size = IVAL(pdata,0);
2735 if (total_data > 0 && ea_size != total_data) {
2736 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2737 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2738 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2741 if (!lp_ea_support(SNUM(conn))) {
2742 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2745 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2746 return ERROR_NT(NT_STATUS_NO_MEMORY);
2749 /* Pull out the list of names. */
2750 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
2751 if (!ea_list) {
2752 talloc_destroy(ea_ctx);
2753 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2757 params = SMB_REALLOC(*pparams,2);
2758 if (params == NULL) {
2759 talloc_destroy(ea_ctx);
2760 return ERROR_NT(NT_STATUS_NO_MEMORY);
2762 *pparams = params;
2763 memset((char *)params,'\0',2);
2764 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2765 pdata = SMB_REALLOC(*ppdata, data_size);
2766 if ( pdata == NULL ) {
2767 talloc_destroy(ea_ctx);
2768 return ERROR_NT(NT_STATUS_NO_MEMORY);
2770 *ppdata = pdata;
2772 memset((char *)pdata,'\0',data_size);
2774 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2776 if (fsp) {
2777 if (fsp->pending_modtime) {
2778 /* the pending modtime overrides the current modtime */
2779 sbuf.st_mtime = fsp->pending_modtime;
2781 } else {
2782 /* Do we have this path open ? */
2783 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2784 if (fsp1 && fsp1->pending_modtime) {
2785 /* the pending modtime overrides the current modtime */
2786 sbuf.st_mtime = fsp1->pending_modtime;
2790 if (lp_dos_filetime_resolution(SNUM(conn))) {
2791 c_time &= ~1;
2792 sbuf.st_atime &= ~1;
2793 sbuf.st_ctime &= ~1;
2794 sbuf.st_mtime &= ~1;
2797 /* NT expects the name to be in an exact form of the *full*
2798 filename. See the trans2 torture test */
2799 if (strequal(base_name,".")) {
2800 pstrcpy(dos_fname, "\\");
2801 } else {
2802 pstr_sprintf(dos_fname, "\\%s", fname);
2803 string_replace(dos_fname, '/', '\\');
2806 switch (info_level) {
2807 case SMB_INFO_STANDARD:
2808 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2809 data_size = 22;
2810 put_dos_date2(pdata,l1_fdateCreation,c_time);
2811 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2812 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2813 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2814 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2815 SSVAL(pdata,l1_attrFile,mode);
2816 break;
2818 case SMB_INFO_QUERY_EA_SIZE:
2820 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2821 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2822 data_size = 26;
2823 put_dos_date2(pdata,l1_fdateCreation,c_time);
2824 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2825 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2826 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2827 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2828 SSVAL(pdata,l1_attrFile,mode);
2829 SIVAL(pdata,l1_attrFile+2,ea_size);
2830 break;
2833 case SMB_INFO_IS_NAME_VALID:
2834 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2835 if (tran_call == TRANSACT2_QFILEINFO) {
2836 /* os/2 needs this ? really ?*/
2837 return ERROR_DOS(ERRDOS,ERRbadfunc);
2839 data_size = 0;
2840 param_size = 0;
2841 break;
2843 case SMB_INFO_QUERY_EAS_FROM_LIST:
2845 size_t total_ea_len = 0;
2846 struct ea_list *ea_file_list = NULL;
2848 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2849 put_dos_date2(pdata,0,c_time);
2850 put_dos_date2(pdata,4,sbuf.st_atime);
2851 put_dos_date2(pdata,8,sbuf.st_mtime);
2852 SIVAL(pdata,12,(uint32)file_size);
2853 SIVAL(pdata,16,(uint32)allocation_size);
2854 SIVAL(pdata,20,mode);
2856 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2858 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2860 if (!ea_list || (total_ea_len > data_size - 24)) {
2861 talloc_destroy(ea_ctx);
2862 data_size = 4;
2863 break;
2866 data_size = fill_ea_buffer(ea_ctx, pdata + 24, data_size - 24, conn, ea_list);
2867 data_size += 24;
2868 talloc_destroy(ea_ctx);
2869 break;
2872 case SMB_INFO_QUERY_ALL_EAS:
2874 /* We have data_size bytes to put EA's into. */
2875 size_t total_ea_len = 0;
2877 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2879 ea_ctx = talloc_init("ea_ctx");
2880 if (!ea_ctx) {
2881 return ERROR_NT(NT_STATUS_NO_MEMORY);
2884 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2885 if (!ea_list || (total_ea_len > data_size)) {
2886 talloc_destroy(ea_ctx);
2887 data_size = 4;
2888 break;
2891 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2892 talloc_destroy(ea_ctx);
2893 break;
2896 case SMB_FILE_BASIC_INFORMATION:
2897 case SMB_QUERY_FILE_BASIC_INFO:
2899 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2900 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2901 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2902 } else {
2903 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2904 data_size = 40;
2905 SIVAL(pdata,36,0);
2907 put_long_date(pdata,c_time);
2908 put_long_date(pdata+8,sbuf.st_atime);
2909 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2910 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2911 SIVAL(pdata,32,mode);
2913 DEBUG(5,("SMB_QFBI - "));
2915 time_t create_time = c_time;
2916 DEBUG(5,("create: %s ", ctime(&create_time)));
2918 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2919 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2920 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2921 DEBUG(5,("mode: %x\n", mode));
2923 break;
2925 case SMB_FILE_STANDARD_INFORMATION:
2926 case SMB_QUERY_FILE_STANDARD_INFO:
2928 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2929 data_size = 24;
2930 SOFF_T(pdata,0,allocation_size);
2931 SOFF_T(pdata,8,file_size);
2932 if (delete_pending & sbuf.st_nlink)
2933 SIVAL(pdata,16,sbuf.st_nlink - 1);
2934 else
2935 SIVAL(pdata,16,sbuf.st_nlink);
2936 SCVAL(pdata,20,0);
2937 SCVAL(pdata,21,(mode&aDIR)?1:0);
2938 break;
2940 case SMB_FILE_EA_INFORMATION:
2941 case SMB_QUERY_FILE_EA_INFO:
2943 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2944 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2945 data_size = 4;
2946 SIVAL(pdata,0,ea_size);
2947 break;
2950 /* Get the 8.3 name - used if NT SMB was negotiated. */
2951 case SMB_QUERY_FILE_ALT_NAME_INFO:
2952 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2954 pstring short_name;
2956 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2957 pstrcpy(short_name,base_name);
2958 /* Mangle if not already 8.3 */
2959 if(!mangle_is_8_3(short_name, True)) {
2960 mangle_map(short_name,True,True,SNUM(conn));
2962 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2963 data_size = 4 + len;
2964 SIVAL(pdata,0,len);
2965 break;
2968 case SMB_QUERY_FILE_NAME_INFO:
2970 this must be *exactly* right for ACLs on mapped drives to work
2972 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2973 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2974 data_size = 4 + len;
2975 SIVAL(pdata,0,len);
2976 break;
2978 case SMB_FILE_ALLOCATION_INFORMATION:
2979 case SMB_QUERY_FILE_ALLOCATION_INFO:
2980 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2981 data_size = 8;
2982 SOFF_T(pdata,0,allocation_size);
2983 break;
2985 case SMB_FILE_END_OF_FILE_INFORMATION:
2986 case SMB_QUERY_FILE_END_OF_FILEINFO:
2987 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2988 data_size = 8;
2989 SOFF_T(pdata,0,file_size);
2990 break;
2992 case SMB_QUERY_FILE_ALL_INFO:
2993 case SMB_FILE_ALL_INFORMATION:
2995 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2996 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2997 put_long_date(pdata,c_time);
2998 put_long_date(pdata+8,sbuf.st_atime);
2999 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3000 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3001 SIVAL(pdata,32,mode);
3002 pdata += 40;
3003 SOFF_T(pdata,0,allocation_size);
3004 SOFF_T(pdata,8,file_size);
3005 if (delete_pending && sbuf.st_nlink)
3006 SIVAL(pdata,16,sbuf.st_nlink - 1);
3007 else
3008 SIVAL(pdata,16,sbuf.st_nlink);
3009 SCVAL(pdata,20,delete_pending);
3010 SCVAL(pdata,21,(mode&aDIR)?1:0);
3011 pdata += 24;
3012 SIVAL(pdata,0,ea_size);
3013 pdata += 4; /* EA info */
3014 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3015 SIVAL(pdata,0,len);
3016 pdata += 4 + len;
3017 data_size = PTR_DIFF(pdata,(*ppdata));
3018 break;
3020 case SMB_FILE_INTERNAL_INFORMATION:
3021 /* This should be an index number - looks like
3022 dev/ino to me :-)
3024 I think this causes us to fail the IFSKIT
3025 BasicFileInformationTest. -tpot */
3027 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3028 SIVAL(pdata,0,sbuf.st_dev);
3029 SIVAL(pdata,4,sbuf.st_ino);
3030 data_size = 8;
3031 break;
3033 case SMB_FILE_ACCESS_INFORMATION:
3034 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3035 SIVAL(pdata,0,desired_access);
3036 data_size = 4;
3037 break;
3039 case SMB_FILE_NAME_INFORMATION:
3040 /* Pathname with leading '\'. */
3042 size_t byte_len;
3043 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3044 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3045 SIVAL(pdata,0,byte_len);
3046 data_size = 4 + byte_len;
3047 break;
3050 case SMB_FILE_DISPOSITION_INFORMATION:
3051 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3052 data_size = 1;
3053 SCVAL(pdata,0,delete_pending);
3054 break;
3056 case SMB_FILE_POSITION_INFORMATION:
3057 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3058 data_size = 8;
3059 SOFF_T(pdata,0,pos);
3060 break;
3062 case SMB_FILE_MODE_INFORMATION:
3063 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3064 SIVAL(pdata,0,mode);
3065 data_size = 4;
3066 break;
3068 case SMB_FILE_ALIGNMENT_INFORMATION:
3069 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3070 SIVAL(pdata,0,0); /* No alignment needed. */
3071 data_size = 4;
3072 break;
3074 #if 0
3076 * NT4 server just returns "invalid query" to this - if we try to answer
3077 * it then NTws gets a BSOD! (tridge).
3078 * W2K seems to want this. JRA.
3080 case SMB_QUERY_FILE_STREAM_INFO:
3081 #endif
3082 case SMB_FILE_STREAM_INFORMATION:
3083 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3084 if (mode & aDIR) {
3085 data_size = 0;
3086 } else {
3087 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3088 SIVAL(pdata,0,0); /* ??? */
3089 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3090 SOFF_T(pdata,8,file_size);
3091 SIVAL(pdata,16,allocation_size);
3092 SIVAL(pdata,20,0); /* ??? */
3093 data_size = 24 + byte_len;
3095 break;
3097 case SMB_QUERY_COMPRESSION_INFO:
3098 case SMB_FILE_COMPRESSION_INFORMATION:
3099 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3100 SOFF_T(pdata,0,file_size);
3101 SIVAL(pdata,8,0); /* ??? */
3102 SIVAL(pdata,12,0); /* ??? */
3103 data_size = 16;
3104 break;
3106 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3107 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3108 put_long_date(pdata,c_time);
3109 put_long_date(pdata+8,sbuf.st_atime);
3110 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3111 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3112 SIVAL(pdata,32,allocation_size);
3113 SOFF_T(pdata,40,file_size);
3114 SIVAL(pdata,48,mode);
3115 SIVAL(pdata,52,0); /* ??? */
3116 data_size = 56;
3117 break;
3119 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3120 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3121 SIVAL(pdata,0,mode);
3122 SIVAL(pdata,4,0);
3123 data_size = 8;
3124 break;
3127 * CIFS UNIX Extensions.
3130 case SMB_QUERY_FILE_UNIX_BASIC:
3132 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3133 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3135 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3136 pdata += 8;
3138 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3139 pdata += 8;
3141 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3142 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3143 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3144 pdata += 24;
3146 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3147 SIVAL(pdata,4,0);
3148 pdata += 8;
3150 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3151 SIVAL(pdata,4,0);
3152 pdata += 8;
3154 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3155 pdata += 4;
3157 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3158 SIVAL(pdata,4,0);
3159 pdata += 8;
3161 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3162 SIVAL(pdata,4,0);
3163 pdata += 8;
3165 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3166 pdata += 8;
3168 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3169 SIVAL(pdata,4,0);
3170 pdata += 8;
3172 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3173 SIVAL(pdata,4,0);
3174 pdata += 8+1;
3175 data_size = PTR_DIFF(pdata,(*ppdata));
3178 int i;
3179 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3181 for (i=0; i<100; i++)
3182 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3183 DEBUG(4,("\n"));
3186 break;
3188 case SMB_QUERY_FILE_UNIX_LINK:
3190 pstring buffer;
3192 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3193 #ifdef S_ISLNK
3194 if(!S_ISLNK(sbuf.st_mode))
3195 return(UNIXERROR(ERRSRV,ERRbadlink));
3196 #else
3197 return(UNIXERROR(ERRDOS,ERRbadlink));
3198 #endif
3199 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3200 if (len == -1)
3201 return(UNIXERROR(ERRDOS,ERRnoaccess));
3202 buffer[len] = 0;
3203 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3204 pdata += len;
3205 data_size = PTR_DIFF(pdata,(*ppdata));
3207 break;
3210 #if defined(HAVE_POSIX_ACLS)
3211 case SMB_QUERY_POSIX_ACL:
3213 SMB_ACL_T file_acl = NULL;
3214 SMB_ACL_T def_acl = NULL;
3215 uint16 num_file_acls = 0;
3216 uint16 num_def_acls = 0;
3218 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3219 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3220 } else {
3221 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3224 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3225 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3226 fname ));
3227 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3230 if (S_ISDIR(sbuf.st_mode)) {
3231 if (fsp && fsp->is_directory) {
3232 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3233 } else {
3234 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3236 def_acl = free_empty_sys_acl(conn, def_acl);
3239 num_file_acls = count_acl_entries(conn, file_acl);
3240 num_def_acls = count_acl_entries(conn, def_acl);
3242 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3243 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3244 data_size,
3245 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3246 SMB_POSIX_ACL_HEADER_SIZE) ));
3247 if (file_acl) {
3248 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3250 if (def_acl) {
3251 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3253 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3256 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3257 SSVAL(pdata,2,num_file_acls);
3258 SSVAL(pdata,4,num_def_acls);
3259 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3260 if (file_acl) {
3261 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3263 if (def_acl) {
3264 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3266 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3268 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3269 if (file_acl) {
3270 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3272 if (def_acl) {
3273 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3275 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3278 if (file_acl) {
3279 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3281 if (def_acl) {
3282 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3284 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3285 break;
3287 #endif
3289 default:
3290 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3293 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3295 return(-1);
3298 /****************************************************************************
3299 Deal with the internal needs of setting the delete on close flag. Note that
3300 as the tdb locking is recursive, it is safe to call this from within
3301 open_file_shared. JRA.
3302 ****************************************************************************/
3304 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3306 if (delete_on_close) {
3308 * Only allow delete on close for writable files.
3311 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3312 if (dosmode & aRONLY) {
3313 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3314 fsp->fsp_name ));
3315 return NT_STATUS_CANNOT_DELETE;
3320 * Only allow delete on close for writable shares.
3323 if (!CAN_WRITE(fsp->conn)) {
3324 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3325 fsp->fsp_name ));
3326 return NT_STATUS_ACCESS_DENIED;
3330 * Only allow delete on close for files/directories opened with delete intent.
3333 if (!(fsp->desired_access & DELETE_ACCESS)) {
3334 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3335 fsp->fsp_name ));
3336 return NT_STATUS_ACCESS_DENIED;
3340 if(fsp->is_directory) {
3341 fsp->directory_delete_on_close = delete_on_close;
3342 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3343 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3344 } else {
3345 fsp->delete_on_close = delete_on_close;
3346 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3347 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3350 return NT_STATUS_OK;
3353 /****************************************************************************
3354 Sets the delete on close flag over all share modes on this file.
3355 Modify the share mode entry for all files open
3356 on this device and inode to tell other smbds we have
3357 changed the delete on close flag. This will be noticed
3358 in the close code, the last closer will delete the file
3359 if flag is set.
3360 ****************************************************************************/
3362 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3364 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3365 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3367 if (fsp->is_directory || fsp->is_stat)
3368 return NT_STATUS_OK;
3370 if (lock_share_entry_fsp(fsp) == False)
3371 return NT_STATUS_ACCESS_DENIED;
3373 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3374 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3375 fsp->fsp_name ));
3376 unlock_share_entry_fsp(fsp);
3377 return NT_STATUS_ACCESS_DENIED;
3380 unlock_share_entry_fsp(fsp);
3381 return NT_STATUS_OK;
3384 /****************************************************************************
3385 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3386 code.
3387 ****************************************************************************/
3389 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3391 BOOL bad_path_oldname = False;
3392 BOOL bad_path_newname = False;
3393 SMB_STRUCT_STAT sbuf1, sbuf2;
3394 pstring last_component_oldname;
3395 pstring last_component_newname;
3396 NTSTATUS status = NT_STATUS_OK;
3398 ZERO_STRUCT(sbuf1);
3399 ZERO_STRUCT(sbuf2);
3401 /* No wildcards. */
3402 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3403 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3406 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3407 if (bad_path_oldname) {
3408 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3411 /* Quick check for "." and ".." */
3412 if (last_component_oldname[0] == '.') {
3413 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3414 return NT_STATUS_OBJECT_NAME_INVALID;
3418 /* source must already exist. */
3419 if (!VALID_STAT(sbuf1)) {
3420 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3423 if (!check_name(oldname,conn)) {
3424 return NT_STATUS_ACCESS_DENIED;
3427 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3428 if (bad_path_newname) {
3429 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3432 /* Quick check for "." and ".." */
3433 if (last_component_newname[0] == '.') {
3434 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3435 return NT_STATUS_OBJECT_NAME_INVALID;
3439 /* Disallow if newname already exists. */
3440 if (VALID_STAT(sbuf2)) {
3441 return NT_STATUS_OBJECT_NAME_COLLISION;
3444 if (!check_name(newname,conn)) {
3445 return NT_STATUS_ACCESS_DENIED;
3448 /* No links from a directory. */
3449 if (S_ISDIR(sbuf1.st_mode)) {
3450 return NT_STATUS_FILE_IS_A_DIRECTORY;
3453 /* Ensure this is within the share. */
3454 if (!reduce_name(conn, oldname) != 0)
3455 return NT_STATUS_ACCESS_DENIED;
3457 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3459 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3460 status = map_nt_error_from_unix(errno);
3461 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3462 nt_errstr(status), newname, oldname));
3465 return status;
3468 /****************************************************************************
3469 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3470 ****************************************************************************/
3472 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3473 char **pparams, int total_params, char **ppdata, int total_data,
3474 unsigned int max_data_bytes)
3476 char *params = *pparams;
3477 char *pdata = *ppdata;
3478 uint16 tran_call = SVAL(inbuf, smb_setup0);
3479 uint16 info_level;
3480 int dosmode=0;
3481 SMB_OFF_T size=0;
3482 struct utimbuf tvs;
3483 SMB_STRUCT_STAT sbuf;
3484 pstring fname;
3485 int fd = -1;
3486 BOOL bad_path = False;
3487 files_struct *fsp = NULL;
3488 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3489 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3490 mode_t unixmode = 0;
3491 NTSTATUS status = NT_STATUS_OK;
3493 if (!params)
3494 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3496 ZERO_STRUCT(sbuf);
3498 if (tran_call == TRANSACT2_SETFILEINFO) {
3499 if (total_params < 4) {
3500 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3503 fsp = file_fsp(params,0);
3504 info_level = SVAL(params,2);
3506 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3508 * This is actually a SETFILEINFO on a directory
3509 * handle (returned from an NT SMB). NT5.0 seems
3510 * to do this call. JRA.
3512 pstrcpy(fname, fsp->fsp_name);
3513 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3514 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3515 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3517 } else if (fsp && fsp->print_file) {
3519 * Doing a DELETE_ON_CLOSE should cancel a print job.
3521 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3522 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3524 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3526 SSVAL(params,0,0);
3527 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3528 return(-1);
3529 } else
3530 return (UNIXERROR(ERRDOS,ERRbadpath));
3531 } else {
3533 * Original code - this is an open file.
3535 CHECK_FSP(fsp,conn);
3537 pstrcpy(fname, fsp->fsp_name);
3538 fd = fsp->fd;
3540 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3541 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3542 return(UNIXERROR(ERRDOS,ERRbadfid));
3545 } else {
3546 /* set path info */
3547 if (total_params < 6) {
3548 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3551 info_level = SVAL(params,0);
3552 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3553 if (!NT_STATUS_IS_OK(status)) {
3554 return ERROR_NT(status);
3556 unix_convert(fname,conn,0,&bad_path,&sbuf);
3557 if (bad_path) {
3558 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3562 * For CIFS UNIX extensions the target name may not exist.
3565 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3566 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3567 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3570 if(!check_name(fname, conn)) {
3571 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3576 if (!CAN_WRITE(conn))
3577 return ERROR_DOS(ERRSRV,ERRaccess);
3579 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3580 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3582 if (VALID_STAT(sbuf))
3583 unixmode = sbuf.st_mode;
3585 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3586 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3588 /* Realloc the parameter size */
3589 params = SMB_REALLOC(*pparams,2);
3590 if(params == NULL) {
3591 return ERROR_NT(NT_STATUS_NO_MEMORY);
3593 *pparams = params;
3595 SSVAL(params,0,0);
3597 if (fsp && fsp->pending_modtime) {
3598 /* the pending modtime overrides the current modtime */
3599 sbuf.st_mtime = fsp->pending_modtime;
3602 size = get_file_size(sbuf);
3603 tvs.modtime = sbuf.st_mtime;
3604 tvs.actime = sbuf.st_atime;
3605 dosmode = dos_mode(conn,fname,&sbuf);
3606 unixmode = sbuf.st_mode;
3608 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3609 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3611 switch (info_level) {
3612 case SMB_INFO_STANDARD:
3614 if (total_data < 12) {
3615 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3618 /* access time */
3619 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3620 /* write time */
3621 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3622 break;
3625 case SMB_INFO_SET_EA:
3627 struct ea_list *ea_list = NULL;
3628 TALLOC_CTX *ctx = talloc_init("SMB_INFO_SET_EA");
3629 if (!ctx) {
3630 return ERROR_NT(NT_STATUS_NO_MEMORY);
3632 ea_list = read_ea_list(ctx, pdata, total_data);
3633 if (!ea_list) {
3634 talloc_destroy(ctx);
3635 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3637 status = set_ea(conn, fsp, fname, ea_list);
3638 talloc_destroy(ctx);
3640 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) {
3641 return ERROR_NT(status);
3643 break;
3646 #if 0
3647 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3648 /* XXXX um, i don't think this is right.
3649 it's also not in the cifs6.txt spec.
3651 case SMB_INFO_QUERY_EAS_FROM_LIST:
3652 if (total_data < 28)
3653 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3655 tvs.actime = make_unix_date2(pdata+8);
3656 tvs.modtime = make_unix_date2(pdata+12);
3657 size = IVAL(pdata,16);
3658 dosmode = IVAL(pdata,24);
3659 break;
3661 /* XXXX nor this. not in cifs6.txt, either. */
3662 case SMB_INFO_QUERY_ALL_EAS:
3663 if (total_data < 28)
3664 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3666 tvs.actime = make_unix_date2(pdata+8);
3667 tvs.modtime = make_unix_date2(pdata+12);
3668 size = IVAL(pdata,16);
3669 dosmode = IVAL(pdata,24);
3670 break;
3671 #endif
3673 case SMB_SET_FILE_BASIC_INFO:
3674 case SMB_FILE_BASIC_INFORMATION:
3676 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3677 time_t write_time;
3678 time_t changed_time;
3680 if (total_data < 36) {
3681 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3684 /* Ignore create time at offset pdata. */
3686 /* access time */
3687 tvs.actime = interpret_long_date(pdata+8);
3689 write_time = interpret_long_date(pdata+16);
3690 changed_time = interpret_long_date(pdata+24);
3692 tvs.modtime = MIN(write_time, changed_time);
3694 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3695 tvs.modtime = write_time;
3697 /* Prefer a defined time to an undefined one. */
3698 if (null_mtime(tvs.modtime)) {
3699 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3702 /* attributes */
3703 dosmode = IVAL(pdata,32);
3704 break;
3707 case SMB_FILE_ALLOCATION_INFORMATION:
3708 case SMB_SET_FILE_ALLOCATION_INFO:
3710 int ret = -1;
3711 SMB_BIG_UINT allocation_size;
3713 if (total_data < 8) {
3714 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3717 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3718 #ifdef LARGE_SMB_OFF_T
3719 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3720 #else /* LARGE_SMB_OFF_T */
3721 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3722 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3723 #endif /* LARGE_SMB_OFF_T */
3724 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3725 fname, (double)allocation_size ));
3727 if (allocation_size) {
3728 allocation_size = smb_roundup(conn, allocation_size);
3731 if(allocation_size != get_file_size(sbuf)) {
3732 SMB_STRUCT_STAT new_sbuf;
3734 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3735 fname, (double)allocation_size ));
3737 if (fd == -1) {
3738 files_struct *new_fsp = NULL;
3739 int access_mode = 0;
3740 int action = 0;
3742 if(global_oplock_break) {
3743 /* Queue this file modify as we are the process of an oplock break. */
3745 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3746 DEBUGADD(2,( "in oplock break state.\n"));
3748 push_oplock_pending_smb_message(inbuf, length);
3749 return -1;
3752 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3753 SET_OPEN_MODE(DOS_OPEN_RDWR),
3754 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3755 FILE_ATTRIBUTE_NORMAL,
3756 INTERNAL_OPEN_ONLY, &access_mode, &action);
3758 if (new_fsp == NULL)
3759 return(UNIXERROR(ERRDOS,ERRbadpath));
3760 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3761 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3762 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3763 new_fsp->fnum, strerror(errno)));
3764 ret = -1;
3766 close_file(new_fsp,True);
3767 } else {
3768 ret = vfs_allocate_file_space(fsp, allocation_size);
3769 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3770 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3771 fsp->fnum, strerror(errno)));
3772 ret = -1;
3775 if (ret == -1)
3776 return ERROR_NT(NT_STATUS_DISK_FULL);
3778 /* Allocate can truncate size... */
3779 size = get_file_size(new_sbuf);
3782 break;
3785 case SMB_FILE_END_OF_FILE_INFORMATION:
3786 case SMB_SET_FILE_END_OF_FILE_INFO:
3788 if (total_data < 8) {
3789 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3792 size = IVAL(pdata,0);
3793 #ifdef LARGE_SMB_OFF_T
3794 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3795 #else /* LARGE_SMB_OFF_T */
3796 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3797 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3798 #endif /* LARGE_SMB_OFF_T */
3799 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3800 break;
3803 case SMB_FILE_DISPOSITION_INFORMATION:
3804 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3806 BOOL delete_on_close;
3808 if (total_data < 1) {
3809 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3812 delete_on_close = (CVAL(pdata,0) ? True : False);
3814 /* Just ignore this set on a path. */
3815 if (tran_call != TRANSACT2_SETFILEINFO)
3816 break;
3818 if (fsp == NULL)
3819 return(UNIXERROR(ERRDOS,ERRbadfid));
3821 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3823 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3824 return ERROR_NT(status);
3826 /* The set is across all open files on this dev/inode pair. */
3827 status =set_delete_on_close_over_all(fsp, delete_on_close);
3828 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3829 return ERROR_NT(status);
3831 break;
3834 case SMB_FILE_POSITION_INFORMATION:
3836 SMB_BIG_UINT position_information;
3838 if (total_data < 8) {
3839 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3842 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3843 #ifdef LARGE_SMB_OFF_T
3844 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3845 #else /* LARGE_SMB_OFF_T */
3846 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3847 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3848 #endif /* LARGE_SMB_OFF_T */
3849 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3850 fname, (double)position_information ));
3851 if (fsp)
3852 fsp->position_information = position_information;
3853 break;
3856 /* From tridge Samba4 :
3857 * MODE_INFORMATION in setfileinfo (I have no
3858 * idea what "mode information" on a file is - it takes a value of 0,
3859 * 2, 4 or 6. What could it be?).
3862 case SMB_FILE_MODE_INFORMATION:
3864 uint32 mode;
3866 if (total_data < 4) {
3867 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3869 mode = IVAL(pdata,0);
3870 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3871 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3873 break;
3877 * CIFS UNIX extensions.
3880 case SMB_SET_FILE_UNIX_BASIC:
3882 uint32 raw_unixmode;
3884 if (total_data < 100) {
3885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3888 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3889 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3890 size=IVAL(pdata,0); /* first 8 Bytes are size */
3891 #ifdef LARGE_SMB_OFF_T
3892 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3893 #else /* LARGE_SMB_OFF_T */
3894 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3895 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3896 #endif /* LARGE_SMB_OFF_T */
3898 pdata+=24; /* ctime & st_blocks are not changed */
3899 tvs.actime = interpret_long_date(pdata); /* access_time */
3900 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3901 pdata+=16;
3902 set_owner = (uid_t)IVAL(pdata,0);
3903 pdata += 8;
3904 set_grp = (gid_t)IVAL(pdata,0);
3905 pdata += 8;
3906 raw_unixmode = IVAL(pdata,28);
3907 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3908 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3910 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3911 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3912 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3914 if (!VALID_STAT(sbuf)) {
3917 * The only valid use of this is to create character and block
3918 * devices, and named pipes. This is deprecated (IMHO) and
3919 * a new info level should be used for mknod. JRA.
3922 uint32 file_type = IVAL(pdata,0);
3923 #if defined(HAVE_MAKEDEV)
3924 uint32 dev_major = IVAL(pdata,4);
3925 uint32 dev_minor = IVAL(pdata,12);
3926 #endif
3928 uid_t myuid = geteuid();
3929 gid_t mygid = getegid();
3930 SMB_DEV_T dev = (SMB_DEV_T)0;
3932 if (tran_call == TRANSACT2_SETFILEINFO)
3933 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3935 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
3936 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3939 #if defined(HAVE_MAKEDEV)
3940 dev = makedev(dev_major, dev_minor);
3941 #endif
3943 /* We can only create as the owner/group we are. */
3945 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3946 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3947 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3948 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3950 switch (file_type) {
3951 #if defined(S_IFIFO)
3952 case UNIX_TYPE_FIFO:
3953 unixmode |= S_IFIFO;
3954 break;
3955 #endif
3956 #if defined(S_IFSOCK)
3957 case UNIX_TYPE_SOCKET:
3958 unixmode |= S_IFSOCK;
3959 break;
3960 #endif
3961 #if defined(S_IFCHR)
3962 case UNIX_TYPE_CHARDEV:
3963 unixmode |= S_IFCHR;
3964 break;
3965 #endif
3966 #if defined(S_IFBLK)
3967 case UNIX_TYPE_BLKDEV:
3968 unixmode |= S_IFBLK;
3969 break;
3970 #endif
3971 default:
3972 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3975 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3976 0%o for file %s\n", (double)dev, unixmode, fname ));
3978 /* Ok - do the mknod. */
3979 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3980 return(UNIXERROR(ERRDOS,ERRnoaccess));
3982 inherit_access_acl(conn, fname, unixmode);
3984 SSVAL(params,0,0);
3985 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3986 return(-1);
3990 * Deal with the UNIX specific mode set.
3993 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3994 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3995 (unsigned int)unixmode, fname ));
3996 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3997 return(UNIXERROR(ERRDOS,ERRnoaccess));
4001 * Deal with the UNIX specific uid set.
4004 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4005 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4006 (unsigned int)set_owner, fname ));
4007 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4008 return(UNIXERROR(ERRDOS,ERRnoaccess));
4012 * Deal with the UNIX specific gid set.
4015 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4016 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4017 (unsigned int)set_owner, fname ));
4018 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4019 return(UNIXERROR(ERRDOS,ERRnoaccess));
4021 break;
4024 case SMB_SET_FILE_UNIX_LINK:
4026 pstring link_target;
4027 char *newname = fname;
4029 /* Set a symbolic link. */
4030 /* Don't allow this if follow links is false. */
4032 if (!lp_symlinks(SNUM(conn)))
4033 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4035 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4037 /* !widelinks forces the target path to be within the share. */
4038 /* This means we can interpret the target as a pathname. */
4039 if (!lp_widelinks(SNUM(conn))) {
4040 pstring rel_name;
4041 char *last_dirp = NULL;
4043 unix_format(link_target);
4044 if (*link_target == '/') {
4045 /* No absolute paths allowed. */
4046 return(UNIXERROR(ERRDOS,ERRnoaccess));
4048 pstrcpy(rel_name, newname);
4049 last_dirp = strrchr_m(rel_name, '/');
4050 if (last_dirp) {
4051 last_dirp[1] = '\0';
4052 } else {
4053 pstrcpy(rel_name, "./");
4055 pstrcat(rel_name, link_target);
4057 if (!check_name(rel_name, conn)) {
4058 return(UNIXERROR(ERRDOS,ERRnoaccess));
4062 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4063 fname, link_target ));
4065 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4066 return(UNIXERROR(ERRDOS,ERRnoaccess));
4067 SSVAL(params,0,0);
4068 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4069 return(-1);
4072 case SMB_SET_FILE_UNIX_HLINK:
4074 pstring oldname;
4075 char *newname = fname;
4077 /* Set a hard link. */
4078 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4079 if (!NT_STATUS_IS_OK(status)) {
4080 return ERROR_NT(status);
4083 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4084 fname, oldname));
4086 status = hardlink_internals(conn, oldname, newname);
4087 if (!NT_STATUS_IS_OK(status)) {
4088 return ERROR_NT(status);
4091 SSVAL(params,0,0);
4092 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4093 return(-1);
4096 case SMB_FILE_RENAME_INFORMATION:
4098 BOOL overwrite;
4099 uint32 root_fid;
4100 uint32 len;
4101 pstring newname;
4102 pstring base_name;
4103 char *p;
4105 if (total_data < 12) {
4106 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4109 overwrite = (CVAL(pdata,0) ? True : False);
4110 root_fid = IVAL(pdata,4);
4111 len = IVAL(pdata,8);
4112 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4113 if (!NT_STATUS_IS_OK(status)) {
4114 return ERROR_NT(status);
4117 /* Check the new name has no '/' characters. */
4118 if (strchr_m(newname, '/'))
4119 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4121 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4123 /* Create the base directory. */
4124 pstrcpy(base_name, fname);
4125 p = strrchr_m(base_name, '/');
4126 if (p)
4127 *p = '\0';
4128 /* Append the new name. */
4129 pstrcat(base_name, "/");
4130 pstrcat(base_name, newname);
4132 if (fsp) {
4133 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4134 fsp->fnum, fsp->fsp_name, base_name ));
4135 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4136 } else {
4137 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4138 fname, newname ));
4139 status = rename_internals(conn, fname, base_name, 0, overwrite);
4141 if (!NT_STATUS_IS_OK(status)) {
4142 return ERROR_NT(status);
4144 process_pending_change_notify_queue((time_t)0);
4145 SSVAL(params,0,0);
4146 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4147 return(-1);
4150 #if defined(HAVE_POSIX_ACLS)
4151 case SMB_SET_POSIX_ACL:
4153 uint16 posix_acl_version;
4154 uint16 num_file_acls;
4155 uint16 num_def_acls;
4156 BOOL valid_file_acls = True;
4157 BOOL valid_def_acls = True;
4159 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4160 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4162 posix_acl_version = SVAL(pdata,0);
4163 num_file_acls = SVAL(pdata,2);
4164 num_def_acls = SVAL(pdata,4);
4166 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4167 valid_file_acls = False;
4168 num_file_acls = 0;
4171 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4172 valid_def_acls = False;
4173 num_def_acls = 0;
4176 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4177 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4180 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4181 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4182 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4185 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4186 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4187 return(UNIXERROR(ERRDOS,ERRnoaccess));
4190 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4191 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4192 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4193 return(UNIXERROR(ERRDOS,ERRnoaccess));
4196 SSVAL(params,0,0);
4197 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4198 return(-1);
4200 #endif
4202 default:
4203 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4206 /* get some defaults (no modifications) if any info is zero or -1. */
4207 if (null_mtime(tvs.actime)) {
4208 tvs.actime = sbuf.st_atime;
4211 if (null_mtime(tvs.modtime)) {
4212 tvs.modtime = sbuf.st_mtime;
4215 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4216 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4217 DEBUG(6,("size: %.0f ", (double)size));
4219 if (dosmode) {
4220 if (S_ISDIR(sbuf.st_mode))
4221 dosmode |= aDIR;
4222 else
4223 dosmode &= ~aDIR;
4226 DEBUG(6,("dosmode: %x\n" , dosmode));
4228 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4229 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4230 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4231 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4234 * Only do this test if we are not explicitly
4235 * changing the size of a file.
4237 if (!size)
4238 size = get_file_size(sbuf);
4242 * Try and set the times, size and mode of this file -
4243 * if they are different from the current values
4246 /* check the mode isn't different, before changing it */
4247 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4249 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4251 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4252 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4253 return(UNIXERROR(ERRDOS,ERRnoaccess));
4257 /* Now the size. */
4258 if (size != get_file_size(sbuf)) {
4260 int ret;
4262 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4263 fname, (double)size ));
4265 if (fd == -1) {
4266 files_struct *new_fsp = NULL;
4267 int access_mode = 0;
4268 int action = 0;
4270 if(global_oplock_break) {
4271 /* Queue this file modify as we are the process of an oplock break. */
4273 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4274 DEBUGADD(2,( "in oplock break state.\n"));
4276 push_oplock_pending_smb_message(inbuf, length);
4277 return -1;
4280 new_fsp = open_file_shared(conn, fname, &sbuf,
4281 SET_OPEN_MODE(DOS_OPEN_RDWR),
4282 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4283 FILE_ATTRIBUTE_NORMAL,
4284 INTERNAL_OPEN_ONLY, &access_mode, &action);
4286 if (new_fsp == NULL)
4287 return(UNIXERROR(ERRDOS,ERRbadpath));
4288 ret = vfs_set_filelen(new_fsp, size);
4289 close_file(new_fsp,True);
4290 } else {
4291 ret = vfs_set_filelen(fsp, size);
4294 if (ret == -1)
4295 return (UNIXERROR(ERRHRD,ERRdiskfull));
4299 * Finally the times.
4301 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4302 if(fsp != NULL) {
4304 * This was a setfileinfo on an open file.
4305 * NT does this a lot. We also need to
4306 * set the time here, as it can be read by
4307 * FindFirst/FindNext and with the patch for bug #2045
4308 * in smbd/fileio.c it ensures that this timestamp is
4309 * kept sticky even after a write. We save the request
4310 * away and will set it on file close and after a write. JRA.
4313 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4314 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4315 fsp_set_pending_modtime(fsp, tvs.modtime);
4319 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4321 if(file_utime(conn, fname, &tvs)!=0) {
4322 return(UNIXERROR(ERRDOS,ERRnoaccess));
4326 SSVAL(params,0,0);
4327 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4329 return(-1);
4332 /****************************************************************************
4333 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4334 ****************************************************************************/
4336 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4337 char **pparams, int total_params, char **ppdata, int total_data,
4338 unsigned int max_data_bytes)
4340 char *params = *pparams;
4341 pstring directory;
4342 int ret = -1;
4343 SMB_STRUCT_STAT sbuf;
4344 BOOL bad_path = False;
4345 NTSTATUS status = NT_STATUS_OK;
4347 if (!CAN_WRITE(conn))
4348 return ERROR_DOS(ERRSRV,ERRaccess);
4350 if (total_params < 4) {
4351 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4354 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4355 if (!NT_STATUS_IS_OK(status)) {
4356 return ERROR_NT(status);
4359 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4361 unix_convert(directory,conn,0,&bad_path,&sbuf);
4362 if (bad_path) {
4363 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4365 if (check_name(directory,conn))
4366 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4368 if(ret < 0) {
4369 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4370 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4373 /* Realloc the parameter and data sizes */
4374 params = SMB_REALLOC(*pparams,2);
4375 if(params == NULL) {
4376 return ERROR_NT(NT_STATUS_NO_MEMORY);
4378 *pparams = params;
4380 SSVAL(params,0,0);
4382 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4384 return(-1);
4387 /****************************************************************************
4388 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4389 We don't actually do this - we just send a null response.
4390 ****************************************************************************/
4392 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4393 char **pparams, int total_params, char **ppdata, int total_data,
4394 unsigned int max_data_bytes)
4396 static uint16 fnf_handle = 257;
4397 char *params = *pparams;
4398 uint16 info_level;
4400 if (total_params < 6) {
4401 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4404 info_level = SVAL(params,4);
4405 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4407 switch (info_level) {
4408 case 1:
4409 case 2:
4410 break;
4411 default:
4412 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4415 /* Realloc the parameter and data sizes */
4416 params = SMB_REALLOC(*pparams,6);
4417 if(params == NULL) {
4418 return ERROR_NT(NT_STATUS_NO_MEMORY);
4420 *pparams = params;
4422 SSVAL(params,0,fnf_handle);
4423 SSVAL(params,2,0); /* No changes */
4424 SSVAL(params,4,0); /* No EA errors */
4426 fnf_handle++;
4428 if(fnf_handle == 0)
4429 fnf_handle = 257;
4431 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4433 return(-1);
4436 /****************************************************************************
4437 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4438 changes). Currently this does nothing.
4439 ****************************************************************************/
4441 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4442 char **pparams, int total_params, char **ppdata, int total_data,
4443 unsigned int max_data_bytes)
4445 char *params = *pparams;
4447 DEBUG(3,("call_trans2findnotifynext\n"));
4449 /* Realloc the parameter and data sizes */
4450 params = SMB_REALLOC(*pparams,4);
4451 if(params == NULL) {
4452 return ERROR_NT(NT_STATUS_NO_MEMORY);
4454 *pparams = params;
4456 SSVAL(params,0,0); /* No changes */
4457 SSVAL(params,2,0); /* No EA errors */
4459 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4461 return(-1);
4464 /****************************************************************************
4465 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4466 ****************************************************************************/
4468 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4469 char **pparams, int total_params, char **ppdata, int total_data,
4470 unsigned int max_data_bytes)
4472 char *params = *pparams;
4473 pstring pathname;
4474 int reply_size = 0;
4475 int max_referral_level;
4477 DEBUG(10,("call_trans2getdfsreferral\n"));
4479 if (total_params < 2) {
4480 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4483 max_referral_level = SVAL(params,0);
4485 if(!lp_host_msdfs())
4486 return ERROR_DOS(ERRDOS,ERRbadfunc);
4488 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4489 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4490 return UNIXERROR(ERRDOS,ERRbadfile);
4492 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4493 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4495 return(-1);
4498 #define LMCAT_SPL 0x53
4499 #define LMFUNC_GETJOBID 0x60
4501 /****************************************************************************
4502 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4503 ****************************************************************************/
4505 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4506 char **pparams, int total_params, char **ppdata, int total_data,
4507 unsigned int max_data_bytes)
4509 char *pdata = *ppdata;
4510 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4512 /* check for an invalid fid before proceeding */
4514 if (!fsp)
4515 return(ERROR_DOS(ERRDOS,ERRbadfid));
4517 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4518 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4519 pdata = SMB_REALLOC(*ppdata, 32);
4520 if(pdata == NULL) {
4521 return ERROR_NT(NT_STATUS_NO_MEMORY);
4523 *ppdata = pdata;
4525 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4526 CAN ACCEPT THIS IN UNICODE. JRA. */
4528 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4529 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4530 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4531 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4532 return(-1);
4533 } else {
4534 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4535 return ERROR_DOS(ERRSRV,ERRerror);
4539 /****************************************************************************
4540 Reply to a SMBfindclose (stop trans2 directory search).
4541 ****************************************************************************/
4543 int reply_findclose(connection_struct *conn,
4544 char *inbuf,char *outbuf,int length,int bufsize)
4546 int outsize = 0;
4547 int dptr_num=SVALS(inbuf,smb_vwv0);
4548 START_PROFILE(SMBfindclose);
4550 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4552 dptr_close(&dptr_num);
4554 outsize = set_message(outbuf,0,0,True);
4556 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4558 END_PROFILE(SMBfindclose);
4559 return(outsize);
4562 /****************************************************************************
4563 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4564 ****************************************************************************/
4566 int reply_findnclose(connection_struct *conn,
4567 char *inbuf,char *outbuf,int length,int bufsize)
4569 int outsize = 0;
4570 int dptr_num= -1;
4571 START_PROFILE(SMBfindnclose);
4573 dptr_num = SVAL(inbuf,smb_vwv0);
4575 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4577 /* We never give out valid handles for a
4578 findnotifyfirst - so any dptr_num is ok here.
4579 Just ignore it. */
4581 outsize = set_message(outbuf,0,0,True);
4583 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4585 END_PROFILE(SMBfindnclose);
4586 return(outsize);
4589 /****************************************************************************
4590 Reply to a SMBtranss2 - just ignore it!
4591 ****************************************************************************/
4593 int reply_transs2(connection_struct *conn,
4594 char *inbuf,char *outbuf,int length,int bufsize)
4596 START_PROFILE(SMBtranss2);
4597 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4598 END_PROFILE(SMBtranss2);
4599 return(-1);
4602 /****************************************************************************
4603 Reply to a SMBtrans2.
4604 ****************************************************************************/
4606 int reply_trans2(connection_struct *conn,
4607 char *inbuf,char *outbuf,int length,int bufsize)
4609 int outsize = 0;
4610 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4611 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4612 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4613 #if 0
4614 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4615 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4616 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4617 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4618 int32 timeout = IVALS(inbuf,smb_timeout);
4619 #endif
4620 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4621 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4622 char *params = NULL, *data = NULL;
4623 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4624 START_PROFILE(SMBtrans2);
4626 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4627 /* Queue this open message as we are the process of an
4628 * oplock break. */
4630 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4631 DEBUGADD(2,( "in oplock break state.\n"));
4633 push_oplock_pending_smb_message(inbuf, length);
4634 END_PROFILE(SMBtrans2);
4635 return -1;
4638 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4639 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4640 END_PROFILE(SMBtrans2);
4641 return ERROR_DOS(ERRSRV,ERRaccess);
4644 outsize = set_message(outbuf,0,0,True);
4646 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4647 is so as a sanity check */
4648 if (suwcnt != 1) {
4650 * Need to have rc=0 for ioctl to get job id for OS/2.
4651 * Network printing will fail if function is not successful.
4652 * Similar function in reply.c will be used if protocol
4653 * is LANMAN1.0 instead of LM1.2X002.
4654 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4655 * outbuf doesn't have to be set(only job id is used).
4657 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4658 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4659 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4660 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4661 } else {
4662 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4663 DEBUG(2,("Transaction is %d\n",tran_call));
4664 END_PROFILE(SMBtrans2);
4665 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4669 /* Allocate the space for the maximum needed parameters and data */
4670 if (total_params > 0)
4671 params = (char *)SMB_MALLOC(total_params);
4672 if (total_data > 0)
4673 data = (char *)SMB_MALLOC(total_data);
4675 if ((total_params && !params) || (total_data && !data)) {
4676 DEBUG(2,("Out of memory in reply_trans2\n"));
4677 SAFE_FREE(params);
4678 SAFE_FREE(data);
4679 END_PROFILE(SMBtrans2);
4680 return ERROR_NT(NT_STATUS_NO_MEMORY);
4683 /* Copy the param and data bytes sent with this request into
4684 the params buffer */
4685 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4686 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4688 if (num_params > total_params || num_data > total_data)
4689 exit_server("invalid params in reply_trans2");
4691 if(params) {
4692 unsigned int psoff = SVAL(inbuf, smb_psoff);
4693 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4694 goto bad_param;
4695 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4696 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4697 goto bad_param;
4698 memcpy( params, smb_base(inbuf) + psoff, num_params);
4700 if(data) {
4701 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4702 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4703 goto bad_param;
4704 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4705 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4706 goto bad_param;
4707 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4710 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4712 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4713 /* We need to send an interim response then receive the rest
4714 of the parameter/data bytes */
4715 outsize = set_message(outbuf,0,0,True);
4716 srv_signing_trans_stop();
4717 if (!send_smb(smbd_server_fd(),outbuf))
4718 exit_server("reply_trans2: send_smb failed.");
4720 while (num_data_sofar < total_data ||
4721 num_params_sofar < total_params) {
4722 BOOL ret;
4723 unsigned int param_disp;
4724 unsigned int param_off;
4725 unsigned int data_disp;
4726 unsigned int data_off;
4728 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4731 * The sequence number for the trans reply is always
4732 * based on the last secondary received.
4735 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4737 if ((ret &&
4738 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4739 outsize = set_message(outbuf,0,0,True);
4740 if(ret)
4741 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4742 else
4743 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4744 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4745 goto bad_param;
4748 /* Revise total_params and total_data in case
4749 they have changed downwards */
4750 if (SVAL(inbuf, smb_tpscnt) < total_params)
4751 total_params = SVAL(inbuf, smb_tpscnt);
4752 if (SVAL(inbuf, smb_tdscnt) < total_data)
4753 total_data = SVAL(inbuf, smb_tdscnt);
4755 num_params = SVAL(inbuf,smb_spscnt);
4756 param_off = SVAL(inbuf, smb_spsoff);
4757 param_disp = SVAL(inbuf, smb_spsdisp);
4758 num_params_sofar += num_params;
4760 num_data = SVAL(inbuf, smb_sdscnt);
4761 data_off = SVAL(inbuf, smb_sdsoff);
4762 data_disp = SVAL(inbuf, smb_sdsdisp);
4763 num_data_sofar += num_data;
4765 if (num_params_sofar > total_params || num_data_sofar > total_data)
4766 goto bad_param;
4768 if (num_params) {
4769 if (param_disp + num_params > total_params)
4770 goto bad_param;
4771 if ((param_disp + num_params < param_disp) ||
4772 (param_disp + num_params < num_params))
4773 goto bad_param;
4774 if (param_disp > total_params)
4775 goto bad_param;
4776 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4777 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4778 goto bad_param;
4779 if (params + param_disp < params)
4780 goto bad_param;
4782 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4784 if (num_data) {
4785 if (data_disp + num_data > total_data)
4786 goto bad_param;
4787 if ((data_disp + num_data < data_disp) ||
4788 (data_disp + num_data < num_data))
4789 goto bad_param;
4790 if (data_disp > total_data)
4791 goto bad_param;
4792 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4793 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4794 goto bad_param;
4795 if (data + data_disp < data)
4796 goto bad_param;
4798 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4803 if (Protocol >= PROTOCOL_NT1) {
4804 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4807 /* Now we must call the relevant TRANS2 function */
4808 switch(tran_call) {
4809 case TRANSACT2_OPEN:
4810 START_PROFILE_NESTED(Trans2_open);
4811 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4812 &params, total_params, &data, total_data, max_data_bytes);
4813 END_PROFILE_NESTED(Trans2_open);
4814 break;
4816 case TRANSACT2_FINDFIRST:
4817 START_PROFILE_NESTED(Trans2_findfirst);
4818 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4819 &params, total_params, &data, total_data, max_data_bytes);
4820 END_PROFILE_NESTED(Trans2_findfirst);
4821 break;
4823 case TRANSACT2_FINDNEXT:
4824 START_PROFILE_NESTED(Trans2_findnext);
4825 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4826 &params, total_params, &data, total_data, max_data_bytes);
4827 END_PROFILE_NESTED(Trans2_findnext);
4828 break;
4830 case TRANSACT2_QFSINFO:
4831 START_PROFILE_NESTED(Trans2_qfsinfo);
4832 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4833 &params, total_params, &data, total_data, max_data_bytes);
4834 END_PROFILE_NESTED(Trans2_qfsinfo);
4835 break;
4837 #ifdef HAVE_SYS_QUOTAS
4838 case TRANSACT2_SETFSINFO:
4839 START_PROFILE_NESTED(Trans2_setfsinfo);
4840 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4841 &params, total_params, &data, total_data, max_data_bytes);
4842 END_PROFILE_NESTED(Trans2_setfsinfo);
4843 break;
4844 #endif
4845 case TRANSACT2_QPATHINFO:
4846 case TRANSACT2_QFILEINFO:
4847 START_PROFILE_NESTED(Trans2_qpathinfo);
4848 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4849 &params, total_params, &data, total_data, max_data_bytes);
4850 END_PROFILE_NESTED(Trans2_qpathinfo);
4851 break;
4852 case TRANSACT2_SETPATHINFO:
4853 case TRANSACT2_SETFILEINFO:
4854 START_PROFILE_NESTED(Trans2_setpathinfo);
4855 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4856 &params, total_params, &data, total_data, max_data_bytes);
4857 END_PROFILE_NESTED(Trans2_setpathinfo);
4858 break;
4860 case TRANSACT2_FINDNOTIFYFIRST:
4861 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4862 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4863 &params, total_params, &data, total_data, max_data_bytes);
4864 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4865 break;
4867 case TRANSACT2_FINDNOTIFYNEXT:
4868 START_PROFILE_NESTED(Trans2_findnotifynext);
4869 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4870 &params, total_params, &data, total_data, max_data_bytes);
4871 END_PROFILE_NESTED(Trans2_findnotifynext);
4872 break;
4873 case TRANSACT2_MKDIR:
4874 START_PROFILE_NESTED(Trans2_mkdir);
4875 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4876 &params, total_params, &data, total_data, max_data_bytes);
4877 END_PROFILE_NESTED(Trans2_mkdir);
4878 break;
4880 case TRANSACT2_GET_DFS_REFERRAL:
4881 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4882 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4883 &params, total_params, &data, total_data, max_data_bytes);
4884 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4885 break;
4886 case TRANSACT2_IOCTL:
4887 START_PROFILE_NESTED(Trans2_ioctl);
4888 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4889 &params, total_params, &data, total_data, max_data_bytes);
4890 END_PROFILE_NESTED(Trans2_ioctl);
4891 break;
4892 default:
4893 /* Error in request */
4894 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4895 SAFE_FREE(params);
4896 SAFE_FREE(data);
4897 END_PROFILE(SMBtrans2);
4898 srv_signing_trans_stop();
4899 return ERROR_DOS(ERRSRV,ERRerror);
4902 /* As we do not know how many data packets will need to be
4903 returned here the various call_trans2xxxx calls
4904 must send their own. Thus a call_trans2xxx routine only
4905 returns a value other than -1 when it wants to send
4906 an error packet.
4909 srv_signing_trans_stop();
4911 SAFE_FREE(params);
4912 SAFE_FREE(data);
4913 END_PROFILE(SMBtrans2);
4914 return outsize; /* If a correct response was needed the
4915 call_trans2xxx calls have already sent
4916 it. If outsize != -1 then it is returning */
4918 bad_param:
4920 srv_signing_trans_stop();
4921 SAFE_FREE(params);
4922 SAFE_FREE(data);
4923 END_PROFILE(SMBtrans2);
4924 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);