r10400: commit merge patch from jra
[Samba.git] / source / smbd / trans2.c
blob38363bf66ae05b3882e5a216784149a37ca1cbf8
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
8 Extensively modified by Andrew Tridgell, 1995
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
27 extern int max_send;
28 extern enum protocol_types Protocol;
29 extern int smb_read_error;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
51 return val;
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
56 account sparse files.
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
61 SMB_BIG_UINT ret;
63 if(S_ISDIR(sbuf->st_mode)) {
64 return 0;
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
86 NULL
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
95 int i;
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return True;
101 return False;
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
113 char *val = NULL;
114 ssize_t sizeret;
116 again:
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119 if (!val) {
120 return False;
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125 } else {
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130 attr_size = 65536;
131 goto again;
134 if (sizeret == -1) {
135 return False;
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
141 pea->flags = 0;
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
144 } else {
145 pea->name = ea_name;
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
149 return True;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
161 char *ea_namelist;
162 char *p;
163 ssize_t sizeret;
164 int i;
165 struct ea_list *ea_list_head = NULL;
167 *pea_total_len = 0;
169 if (!lp_ea_support(SNUM(conn))) {
170 return NULL;
173 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175 if (fsp && fsp->fh->fd != -1) {
176 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
177 } else {
178 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
181 if (sizeret == -1 && errno == ERANGE) {
182 ea_namelist_size *= 2;
183 } else {
184 break;
188 if (sizeret == -1)
189 return NULL;
191 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
193 if (sizeret) {
194 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
195 struct ea_list *listp, *tmp;
197 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
198 continue;
200 listp = TALLOC_P(mem_ctx, struct ea_list);
201 if (!listp)
202 return NULL;
204 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
205 return NULL;
209 fstring dos_ea_name;
210 push_ascii_fstring(dos_ea_name, listp->ea.name);
211 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
212 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
213 (unsigned int)*pea_total_len, dos_ea_name,
214 (unsigned int)listp->ea.value.length ));
216 DLIST_ADD_END(ea_list_head, listp, tmp);
218 /* Add on 4 for total length. */
219 if (*pea_total_len) {
220 *pea_total_len += 4;
224 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
225 return ea_list_head;
228 /****************************************************************************
229 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
230 that was filled.
231 ****************************************************************************/
233 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
234 connection_struct *conn, struct ea_list *ea_list)
236 unsigned int ret_data_size = 4;
237 char *p = pdata;
239 SMB_ASSERT(total_data_size >= 4);
241 if (!lp_ea_support(SNUM(conn))) {
242 SIVAL(pdata,4,0);
243 return 4;
246 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
247 size_t dos_namelen;
248 fstring dos_ea_name;
249 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
250 dos_namelen = strlen(dos_ea_name);
251 if (dos_namelen > 255 || dos_namelen == 0) {
252 break;
254 if (ea_list->ea.value.length > 65535) {
255 break;
257 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
258 break;
261 /* We know we have room. */
262 SCVAL(p,0,ea_list->ea.flags);
263 SCVAL(p,1,dos_namelen);
264 SSVAL(p,2,ea_list->ea.value.length);
265 fstrcpy(p+4, dos_ea_name);
266 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
268 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
269 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
272 ret_data_size = PTR_DIFF(p, pdata);
273 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
274 SIVAL(pdata,0,ret_data_size);
275 return ret_data_size;
278 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
280 size_t total_ea_len = 0;
281 TALLOC_CTX *mem_ctx = NULL;
283 if (!lp_ea_support(SNUM(conn))) {
284 return 0;
286 mem_ctx = talloc_init("estimate_ea_size");
287 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
288 talloc_destroy(mem_ctx);
289 return total_ea_len;
292 /****************************************************************************
293 Ensure the EA name is case insensitive by matching any existing EA name.
294 ****************************************************************************/
296 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
298 size_t total_ea_len;
299 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
300 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 for (; ea_list; ea_list = ea_list->next) {
303 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
304 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
305 &unix_ea_name[5], ea_list->ea.name));
306 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
307 break;
310 talloc_destroy(mem_ctx);
313 /****************************************************************************
314 Set or delete an extended attribute.
315 ****************************************************************************/
317 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
319 if (!lp_ea_support(SNUM(conn))) {
320 return NT_STATUS_EAS_NOT_SUPPORTED;
323 for (;ea_list; ea_list = ea_list->next) {
324 int ret;
325 fstring unix_ea_name;
327 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
328 fstrcat(unix_ea_name, ea_list->ea.name);
330 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
332 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
334 if (samba_private_attr_name(unix_ea_name)) {
335 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
336 return NT_STATUS_ACCESS_DENIED;
339 if (ea_list->ea.value.length == 0) {
340 /* Remove the attribute. */
341 if (fsp && (fsp->fh->fd != -1)) {
342 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
343 unix_ea_name, fsp->fsp_name));
344 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
345 } else {
346 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
347 unix_ea_name, fname));
348 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
350 #ifdef ENOATTR
351 /* Removing a non existent attribute always succeeds. */
352 if (ret == -1 && errno == ENOATTR) {
353 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
354 unix_ea_name));
355 ret = 0;
357 #endif
358 } else {
359 if (fsp && (fsp->fh->fd != -1)) {
360 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
361 unix_ea_name, fsp->fsp_name));
362 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
363 ea_list->ea.value.data, ea_list->ea.value.length, 0);
364 } else {
365 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
366 unix_ea_name, fname));
367 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
372 if (ret == -1) {
373 #ifdef ENOTSUP
374 if (errno == ENOTSUP) {
375 return NT_STATUS_EAS_NOT_SUPPORTED;
377 #endif
378 return map_nt_error_from_unix(errno);
382 return NT_STATUS_OK;
384 /****************************************************************************
385 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
386 ****************************************************************************/
388 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
390 struct ea_list *ea_list_head = NULL;
391 size_t offset = 0;
393 while (offset + 2 < data_size) {
394 struct ea_list *tmp;
395 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
396 unsigned int namelen = CVAL(pdata,offset);
398 offset++; /* Go past the namelen byte. */
400 /* integer wrap paranioa. */
401 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
402 (offset > data_size) || (namelen > data_size) ||
403 (offset + namelen >= data_size)) {
404 break;
406 /* Ensure the name is null terminated. */
407 if (pdata[offset + namelen] != '\0') {
408 return NULL;
410 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
411 if (!eal->ea.name) {
412 return NULL;
415 offset += (namelen + 1); /* Go past the name + terminating zero. */
416 DLIST_ADD_END(ea_list_head, eal, tmp);
417 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
420 return ea_list_head;
423 /****************************************************************************
424 Read one EA list entry from the buffer.
425 ****************************************************************************/
427 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
429 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
430 uint16 val_len;
431 unsigned int namelen;
433 if (!eal) {
434 return NULL;
437 if (data_size < 6) {
438 return NULL;
441 eal->ea.flags = CVAL(pdata,0);
442 namelen = CVAL(pdata,1);
443 val_len = SVAL(pdata,2);
445 if (4 + namelen + 1 + val_len > data_size) {
446 return NULL;
449 /* Ensure the name is null terminated. */
450 if (pdata[namelen + 4] != '\0') {
451 return NULL;
453 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
454 if (!eal->ea.name) {
455 return NULL;
458 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
459 if (!eal->ea.value.data) {
460 return NULL;
463 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
465 /* Ensure we're null terminated just in case we print the value. */
466 eal->ea.value.data[val_len] = '\0';
467 /* But don't count the null. */
468 eal->ea.value.length--;
470 if (pbytes_used) {
471 *pbytes_used = 4 + namelen + 1 + val_len;
474 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
475 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
477 return eal;
480 /****************************************************************************
481 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
482 ****************************************************************************/
484 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
486 struct ea_list *ea_list_head = NULL;
487 size_t offset = 0;
488 size_t bytes_used = 0;
490 while (offset < data_size) {
491 struct ea_list *tmp;
492 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
494 if (!eal) {
495 return NULL;
498 DLIST_ADD_END(ea_list_head, eal, tmp);
499 offset += bytes_used;
502 return ea_list_head;
505 /****************************************************************************
506 Count the total EA size needed.
507 ****************************************************************************/
509 static size_t ea_list_size(struct ea_list *ealist)
511 fstring dos_ea_name;
512 struct ea_list *listp;
513 size_t ret = 0;
515 for (listp = ealist; listp; listp = listp->next) {
516 push_ascii_fstring(dos_ea_name, listp->ea.name);
517 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
519 /* Add on 4 for total length. */
520 if (ret) {
521 ret += 4;
524 return ret;
527 /****************************************************************************
528 Return a union of EA's from a file list and a list of names.
529 The TALLOC context for the two lists *MUST* be identical as we steal
530 memory from one list to add to another. JRA.
531 ****************************************************************************/
533 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
535 struct ea_list *nlistp, *flistp;
537 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
538 for (flistp = file_list; flistp; flistp = flistp->next) {
539 if (strequal(nlistp->ea.name, flistp->ea.name)) {
540 break;
544 if (flistp) {
545 /* Copy the data from this entry. */
546 nlistp->ea.flags = flistp->ea.flags;
547 nlistp->ea.value = flistp->ea.value;
548 } else {
549 /* Null entry. */
550 nlistp->ea.flags = 0;
551 ZERO_STRUCT(nlistp->ea.value);
555 *total_ea_len = ea_list_size(name_list);
556 return name_list;
559 /****************************************************************************
560 Send the required number of replies back.
561 We assume all fields other than the data fields are
562 set correctly for the type of call.
563 HACK ! Always assumes smb_setup field is zero.
564 ****************************************************************************/
566 static int send_trans2_replies(char *outbuf,
567 int bufsize,
568 char *params,
569 int paramsize,
570 char *pdata,
571 int datasize)
573 /* As we are using a protocol > LANMAN1 then the max_send
574 variable must have been set in the sessetupX call.
575 This takes precedence over the max_xmit field in the
576 global struct. These different max_xmit variables should
577 be merged as this is now too confusing */
579 int data_to_send = datasize;
580 int params_to_send = paramsize;
581 int useable_space;
582 char *pp = params;
583 char *pd = pdata;
584 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
585 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
586 int data_alignment_offset = 0;
588 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
590 set_message(outbuf,10,0,True);
592 /* If there genuinely are no parameters or data to send just send the empty packet */
594 if(params_to_send == 0 && data_to_send == 0) {
595 show_msg(outbuf);
596 if (!send_smb(smbd_server_fd(),outbuf))
597 exit_server("send_trans2_replies: send_smb failed.");
598 return 0;
601 /* When sending params and data ensure that both are nicely aligned */
602 /* Only do this alignment when there is also data to send - else
603 can cause NT redirector problems. */
605 if (((params_to_send % 4) != 0) && (data_to_send != 0))
606 data_alignment_offset = 4 - (params_to_send % 4);
608 /* Space is bufsize minus Netbios over TCP header minus SMB header */
609 /* The alignment_offset is to align the param bytes on an even byte
610 boundary. NT 4.0 Beta needs this to work correctly. */
612 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
614 /* useable_space can never be more than max_send minus the alignment offset. */
616 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
618 while (params_to_send || data_to_send) {
619 /* Calculate whether we will totally or partially fill this packet */
621 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
623 /* We can never send more than useable_space */
625 * Note that 'useable_space' does not include the alignment offsets,
626 * but we must include the alignment offsets in the calculation of
627 * the length of the data we send over the wire, as the alignment offsets
628 * are sent here. Fix from Marc_Jacobsen@hp.com.
631 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
633 set_message(outbuf, 10, total_sent_thistime, True);
635 /* Set total params and data to be sent */
636 SSVAL(outbuf,smb_tprcnt,paramsize);
637 SSVAL(outbuf,smb_tdrcnt,datasize);
639 /* Calculate how many parameters and data we can fit into
640 * this packet. Parameters get precedence
643 params_sent_thistime = MIN(params_to_send,useable_space);
644 data_sent_thistime = useable_space - params_sent_thistime;
645 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
647 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
649 /* smb_proff is the offset from the start of the SMB header to the
650 parameter bytes, however the first 4 bytes of outbuf are
651 the Netbios over TCP header. Thus use smb_base() to subtract
652 them from the calculation */
654 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
656 if(params_sent_thistime == 0)
657 SSVAL(outbuf,smb_prdisp,0);
658 else
659 /* Absolute displacement of param bytes sent in this packet */
660 SSVAL(outbuf,smb_prdisp,pp - params);
662 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
663 if(data_sent_thistime == 0) {
664 SSVAL(outbuf,smb_droff,0);
665 SSVAL(outbuf,smb_drdisp, 0);
666 } else {
667 /* The offset of the data bytes is the offset of the
668 parameter bytes plus the number of parameters being sent this time */
669 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
670 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
671 SSVAL(outbuf,smb_drdisp, pd - pdata);
674 /* Copy the param bytes into the packet */
676 if(params_sent_thistime)
677 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
679 /* Copy in the data bytes */
680 if(data_sent_thistime)
681 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
682 data_alignment_offset,pd,data_sent_thistime);
684 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
685 params_sent_thistime, data_sent_thistime, useable_space));
686 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
687 params_to_send, data_to_send, paramsize, datasize));
689 /* Send the packet */
690 show_msg(outbuf);
691 if (!send_smb(smbd_server_fd(),outbuf))
692 exit_server("send_trans2_replies: send_smb failed.");
694 pp += params_sent_thistime;
695 pd += data_sent_thistime;
697 params_to_send -= params_sent_thistime;
698 data_to_send -= data_sent_thistime;
700 /* Sanity check */
701 if(params_to_send < 0 || data_to_send < 0) {
702 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
703 params_to_send, data_to_send));
704 return -1;
708 return 0;
711 /****************************************************************************
712 Reply to a TRANSACT2_OPEN.
713 ****************************************************************************/
715 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
716 char **pparams, int total_params, char **ppdata, int total_data,
717 unsigned int max_data_bytes)
719 char *params = *pparams;
720 char *pdata = *ppdata;
721 int deny_mode;
722 int32 open_attr;
723 BOOL oplock_request;
724 #if 0
725 BOOL return_additional_info;
726 int16 open_sattr;
727 time_t open_time;
728 #endif
729 int open_ofun;
730 int32 open_size;
731 char *pname;
732 pstring fname;
733 SMB_OFF_T size=0;
734 int fattr=0,mtime=0;
735 SMB_INO_T inode = 0;
736 SMB_STRUCT_STAT sbuf;
737 int smb_action = 0;
738 BOOL bad_path = False;
739 files_struct *fsp;
740 TALLOC_CTX *ctx = NULL;
741 struct ea_list *ea_list = NULL;
742 uint16 flags = 0;
743 NTSTATUS status;
744 uint32 access_mask;
745 uint32 share_mode;
746 uint32 create_disposition;
747 uint32 create_options = 0;
750 * Ensure we have enough parameters to perform the operation.
753 if (total_params < 29) {
754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
757 flags = SVAL(params, 0);
758 deny_mode = SVAL(params, 2);
759 open_attr = SVAL(params,6);
760 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
761 if (oplock_request) {
762 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
765 #if 0
766 return_additional_info = BITSETW(params,0);
767 open_sattr = SVAL(params, 4);
768 open_time = make_unix_date3(params+8);
769 #endif
770 open_ofun = SVAL(params,12);
771 open_size = IVAL(params,14);
772 pname = &params[28];
774 if (IS_IPC(conn)) {
775 return(ERROR_DOS(ERRSRV,ERRaccess));
778 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
779 if (!NT_STATUS_IS_OK(status)) {
780 return ERROR_NT(status);
783 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
784 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
785 (unsigned int)open_ofun, open_size));
787 /* XXXX we need to handle passed times, sattr and flags */
789 unix_convert(fname,conn,0,&bad_path,&sbuf);
790 if (bad_path) {
791 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
794 if (!check_name(fname,conn)) {
795 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
798 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
799 &access_mask,
800 &share_mode,
801 &create_disposition,
802 &create_options)) {
803 return ERROR_DOS(ERRDOS, ERRbadaccess);
806 /* Any data in this call is an EA list. */
807 if (total_data && !lp_ea_support(SNUM(conn))) {
808 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
811 if (total_data) {
812 if (total_data < 10) {
813 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
816 if (IVAL(pdata,0) > total_data) {
817 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
818 IVAL(pdata,0), (unsigned int)total_data));
819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
822 ctx = talloc_init("TRANS2_OPEN_SET_EA");
823 if (!ctx) {
824 return ERROR_NT(NT_STATUS_NO_MEMORY);
826 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
827 if (!ea_list) {
828 talloc_destroy(ctx);
829 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
833 fsp = open_file_ntcreate(conn,fname,&sbuf,
834 access_mask,
835 share_mode,
836 create_disposition,
837 create_options,
838 open_attr,
839 oplock_request,
840 &smb_action);
842 if (!fsp) {
843 talloc_destroy(ctx);
844 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
845 /* We have re-scheduled this call. */
846 return -1;
848 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
851 size = get_file_size(sbuf);
852 fattr = dos_mode(conn,fname,&sbuf);
853 mtime = sbuf.st_mtime;
854 inode = sbuf.st_ino;
855 if (fattr & aDIR) {
856 talloc_destroy(ctx);
857 close_file(fsp,False);
858 return(ERROR_DOS(ERRDOS,ERRnoaccess));
861 if (total_data && smb_action == FILE_WAS_CREATED) {
862 status = set_ea(conn, fsp, fname, ea_list);
863 talloc_destroy(ctx);
864 if (!NT_STATUS_IS_OK(status)) {
865 close_file(fsp,False);
866 return ERROR_NT(status);
870 /* Realloc the size of parameters and data we will return */
871 params = SMB_REALLOC(*pparams, 30);
872 if( params == NULL ) {
873 return ERROR_NT(NT_STATUS_NO_MEMORY);
875 *pparams = params;
877 SSVAL(params,0,fsp->fnum);
878 SSVAL(params,2,open_attr);
879 put_dos_date2(params,4, mtime);
880 SIVAL(params,8, (uint32)size);
881 SSVAL(params,12,deny_mode);
882 SSVAL(params,14,0); /* open_type - file or directory. */
883 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
885 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
886 smb_action |= EXTENDED_OPLOCK_GRANTED;
889 SSVAL(params,18,smb_action);
892 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
894 SIVAL(params,20,inode);
895 SSVAL(params,24,0); /* Padding. */
896 if (flags & 8) {
897 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
898 SIVAL(params, 26, ea_size);
899 } else {
900 SIVAL(params, 26, 0);
903 /* Send the required number of replies */
904 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
906 return -1;
909 /*********************************************************
910 Routine to check if a given string matches exactly.
911 as a special case a mask of "." does NOT match. That
912 is required for correct wildcard semantics
913 Case can be significant or not.
914 **********************************************************/
916 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
918 if (mask[0] == '.' && mask[1] == 0)
919 return False;
920 if (case_sig)
921 return strcmp(str,mask)==0;
922 if (StrCaseCmp(str,mask) != 0) {
923 return False;
925 if (ms_has_wild(str)) {
926 return False;
928 return True;
931 /****************************************************************************
932 Return the filetype for UNIX extensions.
933 ****************************************************************************/
935 static uint32 unix_filetype(mode_t mode)
937 if(S_ISREG(mode))
938 return UNIX_TYPE_FILE;
939 else if(S_ISDIR(mode))
940 return UNIX_TYPE_DIR;
941 #ifdef S_ISLNK
942 else if(S_ISLNK(mode))
943 return UNIX_TYPE_SYMLINK;
944 #endif
945 #ifdef S_ISCHR
946 else if(S_ISCHR(mode))
947 return UNIX_TYPE_CHARDEV;
948 #endif
949 #ifdef S_ISBLK
950 else if(S_ISBLK(mode))
951 return UNIX_TYPE_BLKDEV;
952 #endif
953 #ifdef S_ISFIFO
954 else if(S_ISFIFO(mode))
955 return UNIX_TYPE_FIFO;
956 #endif
957 #ifdef S_ISSOCK
958 else if(S_ISSOCK(mode))
959 return UNIX_TYPE_SOCKET;
960 #endif
962 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
963 return UNIX_TYPE_UNKNOWN;
966 /****************************************************************************
967 Map wire perms onto standard UNIX permissions. Obey share restrictions.
968 ****************************************************************************/
970 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
972 mode_t ret = 0;
974 if (perms == SMB_MODE_NO_CHANGE)
975 return pst->st_mode;
977 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
978 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
979 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
980 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
981 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
982 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
983 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
984 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
985 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
986 #ifdef S_ISVTX
987 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
988 #endif
989 #ifdef S_ISGID
990 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
991 #endif
992 #ifdef S_ISUID
993 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
994 #endif
996 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
997 ret &= lp_dir_mask(SNUM(conn));
998 /* Add in force bits */
999 ret |= lp_force_dir_mode(SNUM(conn));
1000 } else {
1001 /* Apply mode mask */
1002 ret &= lp_create_mask(SNUM(conn));
1003 /* Add in force bits */
1004 ret |= lp_force_create_mode(SNUM(conn));
1007 return ret;
1010 /****************************************************************************
1011 Get a level dependent lanman2 dir entry.
1012 ****************************************************************************/
1014 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1015 void *inbuf, void *outbuf,
1016 char *path_mask,uint32 dirtype,int info_level,
1017 int requires_resume_key,
1018 BOOL dont_descend,char **ppdata,
1019 char *base_data, int space_remaining,
1020 BOOL *out_of_space, BOOL *got_exact_match,
1021 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1023 const char *dname;
1024 BOOL found = False;
1025 SMB_STRUCT_STAT sbuf;
1026 pstring mask;
1027 pstring pathreal;
1028 pstring fname;
1029 char *p, *q, *pdata = *ppdata;
1030 uint32 reskey=0;
1031 long prev_dirpos=0;
1032 uint32 mode=0;
1033 SMB_OFF_T file_size = 0;
1034 SMB_BIG_UINT allocation_size = 0;
1035 uint32 len;
1036 time_t mdate=0, adate=0, cdate=0;
1037 char *nameptr;
1038 char *last_entry_ptr;
1039 BOOL was_8_3;
1040 uint32 nt_extmode; /* Used for NT connections instead of mode */
1041 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1042 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1044 *fname = 0;
1045 *out_of_space = False;
1046 *got_exact_match = False;
1048 if (!conn->dirptr)
1049 return(False);
1051 p = strrchr_m(path_mask,'/');
1052 if(p != NULL) {
1053 if(p[1] == '\0')
1054 pstrcpy(mask,"*.*");
1055 else
1056 pstrcpy(mask, p+1);
1057 } else
1058 pstrcpy(mask, path_mask);
1061 while (!found) {
1062 BOOL got_match;
1063 /* Needed if we run out of space */
1064 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1065 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1068 * Due to bugs in NT client redirectors we are not using
1069 * resume keys any more - set them to zero.
1070 * Check out the related comments in findfirst/findnext.
1071 * JRA.
1074 reskey = 0;
1076 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1077 (long)conn->dirptr,curr_dirpos));
1079 if (!dname)
1080 return(False);
1082 pstrcpy(fname,dname);
1084 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1085 got_match = mask_match(fname, mask, conn->case_sensitive);
1087 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1090 * It turns out that NT matches wildcards against
1091 * both long *and* short names. This may explain some
1092 * of the wildcard wierdness from old DOS clients
1093 * that some people have been seeing.... JRA.
1096 pstring newname;
1097 pstrcpy( newname, fname);
1098 mangle_map( newname, True, False, SNUM(conn));
1099 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1100 got_match = mask_match(newname, mask, conn->case_sensitive);
1103 if(got_match) {
1104 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1105 if (dont_descend && !isdots)
1106 continue;
1108 pstrcpy(pathreal,conn->dirpath);
1109 if(needslash)
1110 pstrcat(pathreal,"/");
1111 pstrcat(pathreal,dname);
1113 if (INFO_LEVEL_IS_UNIX(info_level)) {
1114 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1115 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1116 pathreal,strerror(errno)));
1117 continue;
1119 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1121 /* Needed to show the msdfs symlinks as
1122 * directories */
1124 if(lp_host_msdfs() &&
1125 lp_msdfs_root(SNUM(conn)) &&
1126 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1127 &sbuf)) {
1129 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1130 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1132 } else {
1134 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1135 pathreal,strerror(errno)));
1136 continue;
1140 mode = dos_mode(conn,pathreal,&sbuf);
1142 if (!dir_check_ftype(conn,mode,dirtype)) {
1143 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1144 continue;
1147 file_size = get_file_size(sbuf);
1148 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1149 mdate = sbuf.st_mtime;
1150 adate = sbuf.st_atime;
1151 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1153 if (lp_dos_filetime_resolution(SNUM(conn))) {
1154 cdate &= ~1;
1155 mdate &= ~1;
1156 adate &= ~1;
1159 if(mode & aDIR) {
1160 /* This is necessary, as otherwise the
1161 * desktop.ini file in this folder is
1162 * ignored */
1163 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1164 file_size = 0;
1167 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1169 found = True;
1173 mangle_map(fname,False,True,SNUM(conn));
1175 p = pdata;
1176 last_entry_ptr = p;
1178 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1180 switch (info_level) {
1181 case SMB_FIND_INFO_STANDARD:
1182 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1183 if(requires_resume_key) {
1184 SIVAL(p,0,reskey);
1185 p += 4;
1187 put_dos_date2(p,0,cdate);
1188 put_dos_date2(p,4,adate);
1189 put_dos_date2(p,8,mdate);
1190 SIVAL(p,12,(uint32)file_size);
1191 SIVAL(p,16,(uint32)allocation_size);
1192 SSVAL(p,20,mode);
1193 p += 23;
1194 nameptr = p;
1195 p += align_string(outbuf, p, 0);
1196 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1197 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1198 if (len > 2) {
1199 SCVAL(nameptr, -1, len - 2);
1200 } else {
1201 SCVAL(nameptr, -1, 0);
1203 } else {
1204 if (len > 1) {
1205 SCVAL(nameptr, -1, len - 1);
1206 } else {
1207 SCVAL(nameptr, -1, 0);
1210 p += len;
1211 break;
1213 case SMB_FIND_EA_SIZE:
1214 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1215 if(requires_resume_key) {
1216 SIVAL(p,0,reskey);
1217 p += 4;
1219 put_dos_date2(p,0,cdate);
1220 put_dos_date2(p,4,adate);
1221 put_dos_date2(p,8,mdate);
1222 SIVAL(p,12,(uint32)file_size);
1223 SIVAL(p,16,(uint32)allocation_size);
1224 SSVAL(p,20,mode);
1226 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1227 SIVAL(p,22,ea_size); /* Extended attributes */
1229 p += 27;
1230 nameptr = p - 1;
1231 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1232 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1233 if (len > 2) {
1234 len -= 2;
1235 } else {
1236 len = 0;
1238 } else {
1239 if (len > 1) {
1240 len -= 1;
1241 } else {
1242 len = 0;
1245 SCVAL(nameptr,0,len);
1246 p += len;
1247 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1248 break;
1250 case SMB_FIND_EA_LIST:
1252 struct ea_list *file_list = NULL;
1253 size_t ea_len = 0;
1255 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1256 if (!name_list) {
1257 return False;
1259 if(requires_resume_key) {
1260 SIVAL(p,0,reskey);
1261 p += 4;
1263 put_dos_date2(p,0,cdate);
1264 put_dos_date2(p,4,adate);
1265 put_dos_date2(p,8,mdate);
1266 SIVAL(p,12,(uint32)file_size);
1267 SIVAL(p,16,(uint32)allocation_size);
1268 SSVAL(p,20,mode);
1269 p += 22; /* p now points to the EA area. */
1271 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1272 name_list = ea_list_union(name_list, file_list, &ea_len);
1274 /* We need to determine if this entry will fit in the space available. */
1275 /* Max string size is 255 bytes. */
1276 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1277 /* Move the dirptr back to prev_dirpos */
1278 dptr_SeekDir(conn->dirptr, prev_dirpos);
1279 *out_of_space = True;
1280 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1281 return False; /* Not finished - just out of space */
1284 /* Push the ea_data followed by the name. */
1285 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1286 nameptr = p;
1287 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1288 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1289 if (len > 2) {
1290 len -= 2;
1291 } else {
1292 len = 0;
1294 } else {
1295 if (len > 1) {
1296 len -= 1;
1297 } else {
1298 len = 0;
1301 SCVAL(nameptr,0,len);
1302 p += len + 1;
1303 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1304 break;
1307 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1308 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1309 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1310 p += 4;
1311 SIVAL(p,0,reskey); p += 4;
1312 put_long_date(p,cdate); p += 8;
1313 put_long_date(p,adate); p += 8;
1314 put_long_date(p,mdate); p += 8;
1315 put_long_date(p,mdate); p += 8;
1316 SOFF_T(p,0,file_size); p += 8;
1317 SOFF_T(p,0,allocation_size); p += 8;
1318 SIVAL(p,0,nt_extmode); p += 4;
1319 q = p; p += 4; /* q is placeholder for name length. */
1321 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1322 SIVAL(p,0,ea_size); /* Extended attributes */
1323 p += 4;
1325 /* Clear the short name buffer. This is
1326 * IMPORTANT as not doing so will trigger
1327 * a Win2k client bug. JRA.
1329 if (!was_8_3 && check_mangled_names) {
1330 pstring mangled_name;
1331 pstrcpy(mangled_name, fname);
1332 mangle_map(mangled_name,True,True,SNUM(conn));
1333 mangled_name[12] = 0;
1334 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1335 if (len < 24) {
1336 memset(p + 2 + len,'\0',24 - len);
1338 SSVAL(p, 0, len);
1339 } else {
1340 memset(p,'\0',26);
1342 p += 2 + 24;
1343 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1344 SIVAL(q,0,len);
1345 p += len;
1346 SIVAL(p,0,0); /* Ensure any padding is null. */
1347 len = PTR_DIFF(p, pdata);
1348 len = (len + 3) & ~3;
1349 SIVAL(pdata,0,len);
1350 p = pdata + len;
1351 break;
1353 case SMB_FIND_FILE_DIRECTORY_INFO:
1354 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1355 p += 4;
1356 SIVAL(p,0,reskey); p += 4;
1357 put_long_date(p,cdate); p += 8;
1358 put_long_date(p,adate); p += 8;
1359 put_long_date(p,mdate); p += 8;
1360 put_long_date(p,mdate); p += 8;
1361 SOFF_T(p,0,file_size); p += 8;
1362 SOFF_T(p,0,allocation_size); p += 8;
1363 SIVAL(p,0,nt_extmode); p += 4;
1364 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1365 SIVAL(p,0,len);
1366 p += 4 + len;
1367 SIVAL(p,0,0); /* Ensure any padding is null. */
1368 len = PTR_DIFF(p, pdata);
1369 len = (len + 3) & ~3;
1370 SIVAL(pdata,0,len);
1371 p = pdata + len;
1372 break;
1374 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1375 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1376 p += 4;
1377 SIVAL(p,0,reskey); p += 4;
1378 put_long_date(p,cdate); p += 8;
1379 put_long_date(p,adate); p += 8;
1380 put_long_date(p,mdate); p += 8;
1381 put_long_date(p,mdate); p += 8;
1382 SOFF_T(p,0,file_size); p += 8;
1383 SOFF_T(p,0,allocation_size); p += 8;
1384 SIVAL(p,0,nt_extmode); p += 4;
1385 q = p; p += 4; /* q is placeholder for name length. */
1387 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1388 SIVAL(p,0,ea_size); /* Extended attributes */
1389 p +=4;
1391 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1392 SIVAL(q, 0, len);
1393 p += len;
1395 SIVAL(p,0,0); /* Ensure any padding is null. */
1396 len = PTR_DIFF(p, pdata);
1397 len = (len + 3) & ~3;
1398 SIVAL(pdata,0,len);
1399 p = pdata + len;
1400 break;
1402 case SMB_FIND_FILE_NAMES_INFO:
1403 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1404 p += 4;
1405 SIVAL(p,0,reskey); p += 4;
1406 p += 4;
1407 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1408 acl on a dir (tridge) */
1409 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1410 SIVAL(p, -4, len);
1411 p += len;
1412 SIVAL(p,0,0); /* Ensure any padding is null. */
1413 len = PTR_DIFF(p, pdata);
1414 len = (len + 3) & ~3;
1415 SIVAL(pdata,0,len);
1416 p = pdata + len;
1417 break;
1419 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1420 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1421 p += 4;
1422 SIVAL(p,0,reskey); p += 4;
1423 put_long_date(p,cdate); p += 8;
1424 put_long_date(p,adate); p += 8;
1425 put_long_date(p,mdate); p += 8;
1426 put_long_date(p,mdate); p += 8;
1427 SOFF_T(p,0,file_size); p += 8;
1428 SOFF_T(p,0,allocation_size); p += 8;
1429 SIVAL(p,0,nt_extmode); p += 4;
1430 q = p; p += 4; /* q is placeholder for name length. */
1432 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1433 SIVAL(p,0,ea_size); /* Extended attributes */
1434 p +=4;
1436 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1437 SIVAL(p,0,sbuf.st_dev); p += 4;
1438 SIVAL(p,0,sbuf.st_ino); p += 4;
1439 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1440 SIVAL(q, 0, len);
1441 p += len;
1442 SIVAL(p,0,0); /* Ensure any padding is null. */
1443 len = PTR_DIFF(p, pdata);
1444 len = (len + 3) & ~3;
1445 SIVAL(pdata,0,len);
1446 p = pdata + len;
1447 break;
1449 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1450 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1451 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1452 p += 4;
1453 SIVAL(p,0,reskey); p += 4;
1454 put_long_date(p,cdate); p += 8;
1455 put_long_date(p,adate); p += 8;
1456 put_long_date(p,mdate); p += 8;
1457 put_long_date(p,mdate); p += 8;
1458 SOFF_T(p,0,file_size); p += 8;
1459 SOFF_T(p,0,allocation_size); p += 8;
1460 SIVAL(p,0,nt_extmode); p += 4;
1461 q = p; p += 4; /* q is placeholder for name length */
1463 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1464 SIVAL(p,0,ea_size); /* Extended attributes */
1465 p +=4;
1467 /* Clear the short name buffer. This is
1468 * IMPORTANT as not doing so will trigger
1469 * a Win2k client bug. JRA.
1471 if (!was_8_3 && check_mangled_names) {
1472 pstring mangled_name;
1473 pstrcpy(mangled_name, fname);
1474 mangle_map(mangled_name,True,True,SNUM(conn));
1475 mangled_name[12] = 0;
1476 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1477 SSVAL(p, 0, len);
1478 if (len < 24) {
1479 memset(p + 2 + len,'\0',24 - len);
1481 SSVAL(p, 0, len);
1482 } else {
1483 memset(p,'\0',26);
1485 p += 26;
1486 SSVAL(p,0,0); p += 2; /* Reserved ? */
1487 SIVAL(p,0,sbuf.st_dev); p += 4;
1488 SIVAL(p,0,sbuf.st_ino); p += 4;
1489 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1490 SIVAL(q,0,len);
1491 p += len;
1492 SIVAL(p,0,0); /* Ensure any padding is null. */
1493 len = PTR_DIFF(p, pdata);
1494 len = (len + 3) & ~3;
1495 SIVAL(pdata,0,len);
1496 p = pdata + len;
1497 break;
1499 /* CIFS UNIX Extension. */
1501 case SMB_FIND_FILE_UNIX:
1502 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1503 p+= 4;
1504 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1506 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1507 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1508 p+= 8;
1510 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1511 p+= 8;
1513 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1514 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1515 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1516 p+= 24;
1518 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1519 SIVAL(p,4,0);
1520 p+= 8;
1522 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1523 SIVAL(p,4,0);
1524 p+= 8;
1526 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1527 p+= 4;
1529 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1530 SIVAL(p,4,0);
1531 p+= 8;
1533 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1534 SIVAL(p,4,0);
1535 p+= 8;
1537 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1538 p+= 8;
1540 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1541 SIVAL(p,4,0);
1542 p+= 8;
1544 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1545 SIVAL(p,4,0);
1546 p+= 8;
1548 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1549 p += len;
1550 SIVAL(p,0,0); /* Ensure any padding is null. */
1552 len = PTR_DIFF(p, pdata);
1553 len = (len + 3) & ~3;
1554 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1555 p = pdata + len;
1556 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1558 break;
1560 default:
1561 return(False);
1565 if (PTR_DIFF(p,pdata) > space_remaining) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568 *out_of_space = True;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False; /* Not finished - just out of space */
1573 /* Setup the last entry pointer, as an offset from base_data */
1574 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1575 /* Advance the data pointer to the next slot */
1576 *ppdata = p;
1578 return(found);
1581 /****************************************************************************
1582 Reply to a TRANS2_FINDFIRST.
1583 ****************************************************************************/
1585 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1586 char **pparams, int total_params, char **ppdata, int total_data,
1587 unsigned int max_data_bytes)
1589 /* We must be careful here that we don't return more than the
1590 allowed number of data bytes. If this means returning fewer than
1591 maxentries then so be it. We assume that the redirector has
1592 enough room for the fixed number of parameter bytes it has
1593 requested. */
1594 char *params = *pparams;
1595 char *pdata = *ppdata;
1596 uint32 dirtype = SVAL(params,0);
1597 int maxentries = SVAL(params,2);
1598 uint16 findfirst_flags = SVAL(params,4);
1599 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1600 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1601 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1602 int info_level = SVAL(params,6);
1603 pstring directory;
1604 pstring mask;
1605 char *p;
1606 int last_entry_off=0;
1607 int dptr_num = -1;
1608 int numentries = 0;
1609 int i;
1610 BOOL finished = False;
1611 BOOL dont_descend = False;
1612 BOOL out_of_space = False;
1613 int space_remaining;
1614 BOOL bad_path = False;
1615 SMB_STRUCT_STAT sbuf;
1616 TALLOC_CTX *ea_ctx = NULL;
1617 struct ea_list *ea_list = NULL;
1618 NTSTATUS ntstatus = NT_STATUS_OK;
1620 if (total_params < 12) {
1621 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1624 *directory = *mask = 0;
1626 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1627 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1628 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1629 info_level, max_data_bytes));
1631 if (!maxentries) {
1632 /* W2K3 seems to treat zero as 1. */
1633 maxentries = 1;
1636 switch (info_level) {
1637 case SMB_FIND_INFO_STANDARD:
1638 case SMB_FIND_EA_SIZE:
1639 case SMB_FIND_EA_LIST:
1640 case SMB_FIND_FILE_DIRECTORY_INFO:
1641 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1642 case SMB_FIND_FILE_NAMES_INFO:
1643 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1644 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1645 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1646 break;
1647 case SMB_FIND_FILE_UNIX:
1648 if (!lp_unix_extensions())
1649 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1650 break;
1651 default:
1652 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1655 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1656 if (!NT_STATUS_IS_OK(ntstatus)) {
1657 return ERROR_NT(ntstatus);
1660 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1662 unix_convert(directory,conn,0,&bad_path,&sbuf);
1663 if (bad_path) {
1664 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1666 if(!check_name(directory,conn)) {
1667 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1670 p = strrchr_m(directory,'/');
1671 if(p == NULL) {
1672 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1673 if((directory[0] == '.') && (directory[1] == '\0'))
1674 pstrcpy(mask,"*");
1675 else
1676 pstrcpy(mask,directory);
1677 pstrcpy(directory,"./");
1678 } else {
1679 pstrcpy(mask,p+1);
1680 *p = 0;
1683 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1685 if (info_level == SMB_FIND_EA_LIST) {
1686 uint32 ea_size;
1688 if (total_data < 4) {
1689 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1692 ea_size = IVAL(pdata,0);
1693 if (ea_size != total_data) {
1694 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1695 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1696 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1699 if (!lp_ea_support(SNUM(conn))) {
1700 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1703 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1704 return ERROR_NT(NT_STATUS_NO_MEMORY);
1707 /* Pull out the list of names. */
1708 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1709 if (!ea_list) {
1710 talloc_destroy(ea_ctx);
1711 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1715 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1716 if( pdata == NULL ) {
1717 talloc_destroy(ea_ctx);
1718 return ERROR_NT(NT_STATUS_NO_MEMORY);
1721 *ppdata = pdata;
1723 /* Realloc the params space */
1724 params = SMB_REALLOC(*pparams, 10);
1725 if (params == NULL) {
1726 talloc_destroy(ea_ctx);
1727 return ERROR_NT(NT_STATUS_NO_MEMORY);
1729 *pparams = params;
1731 /* Save the wildcard match and attribs we are using on this directory -
1732 needed as lanman2 assumes these are being saved between calls */
1734 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype);
1735 if (dptr_num < 0) {
1736 talloc_destroy(ea_ctx);
1737 return(UNIXERROR(ERRDOS,ERRbadfile));
1740 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1742 /* We don't need to check for VOL here as this is returned by
1743 a different TRANS2 call. */
1745 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1746 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1747 dont_descend = True;
1749 p = pdata;
1750 space_remaining = max_data_bytes;
1751 out_of_space = False;
1753 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1754 BOOL got_exact_match = False;
1756 /* this is a heuristic to avoid seeking the dirptr except when
1757 absolutely necessary. It allows for a filename of about 40 chars */
1758 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1759 out_of_space = True;
1760 finished = False;
1761 } else {
1762 finished = !get_lanman2_dir_entry(conn,
1763 inbuf, outbuf,
1764 mask,dirtype,info_level,
1765 requires_resume_key,dont_descend,
1766 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1767 &last_entry_off, ea_list, ea_ctx);
1770 if (finished && out_of_space)
1771 finished = False;
1773 if (!finished && !out_of_space)
1774 numentries++;
1777 * As an optimisation if we know we aren't looking
1778 * for a wildcard name (ie. the name matches the wildcard exactly)
1779 * then we can finish on any (first) match.
1780 * This speeds up large directory searches. JRA.
1783 if(got_exact_match)
1784 finished = True;
1786 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1789 talloc_destroy(ea_ctx);
1791 /* Check if we can close the dirptr */
1792 if(close_after_first || (finished && close_if_end)) {
1793 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1794 dptr_close(&dptr_num);
1798 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1799 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1800 * the protocol level is less than NT1. Tested with smbclient. JRA.
1801 * This should fix the OS/2 client bug #2335.
1804 if(numentries == 0) {
1805 dptr_close(&dptr_num);
1806 if (Protocol < PROTOCOL_NT1) {
1807 return ERROR_DOS(ERRDOS,ERRnofiles);
1808 } else {
1809 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1813 /* At this point pdata points to numentries directory entries. */
1815 /* Set up the return parameter block */
1816 SSVAL(params,0,dptr_num);
1817 SSVAL(params,2,numentries);
1818 SSVAL(params,4,finished);
1819 SSVAL(params,6,0); /* Never an EA error */
1820 SSVAL(params,8,last_entry_off);
1822 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1824 if ((! *directory) && dptr_path(dptr_num))
1825 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1827 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1828 smb_fn_name(CVAL(inbuf,smb_com)),
1829 mask, directory, dirtype, numentries ) );
1832 * Force a name mangle here to ensure that the
1833 * mask as an 8.3 name is top of the mangled cache.
1834 * The reasons for this are subtle. Don't remove
1835 * this code unless you know what you are doing
1836 * (see PR#13758). JRA.
1839 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1840 mangle_map(mask, True, True, SNUM(conn));
1842 return(-1);
1845 /****************************************************************************
1846 Reply to a TRANS2_FINDNEXT.
1847 ****************************************************************************/
1849 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1850 char **pparams, int total_params, char **ppdata, int total_data,
1851 unsigned int max_data_bytes)
1853 /* We must be careful here that we don't return more than the
1854 allowed number of data bytes. If this means returning fewer than
1855 maxentries then so be it. We assume that the redirector has
1856 enough room for the fixed number of parameter bytes it has
1857 requested. */
1858 char *params = *pparams;
1859 char *pdata = *ppdata;
1860 int dptr_num = SVAL(params,0);
1861 int maxentries = SVAL(params,2);
1862 uint16 info_level = SVAL(params,4);
1863 uint32 resume_key = IVAL(params,6);
1864 uint16 findnext_flags = SVAL(params,10);
1865 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1866 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1867 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1868 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1869 pstring resume_name;
1870 pstring mask;
1871 pstring directory;
1872 char *p;
1873 uint16 dirtype;
1874 int numentries = 0;
1875 int i, last_entry_off=0;
1876 BOOL finished = False;
1877 BOOL dont_descend = False;
1878 BOOL out_of_space = False;
1879 int space_remaining;
1880 TALLOC_CTX *ea_ctx = NULL;
1881 struct ea_list *ea_list = NULL;
1882 NTSTATUS ntstatus = NT_STATUS_OK;
1884 if (total_params < 12) {
1885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1888 *mask = *directory = *resume_name = 0;
1890 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1891 if (!NT_STATUS_IS_OK(ntstatus)) {
1892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1893 complain (it thinks we're asking for the directory above the shared
1894 path or an invalid name). Catch this as the resume name is only compared, never used in
1895 a file access. JRA. */
1896 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1897 pstrcpy(resume_name, "..");
1898 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1899 pstrcpy(resume_name, ".");
1900 } else {
1901 return ERROR_NT(ntstatus);
1905 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1906 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1907 resume_key = %d resume name = %s continue=%d level = %d\n",
1908 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1909 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1911 if (!maxentries) {
1912 /* W2K3 seems to treat zero as 1. */
1913 maxentries = 1;
1916 switch (info_level) {
1917 case SMB_FIND_INFO_STANDARD:
1918 case SMB_FIND_EA_SIZE:
1919 case SMB_FIND_EA_LIST:
1920 case SMB_FIND_FILE_DIRECTORY_INFO:
1921 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1922 case SMB_FIND_FILE_NAMES_INFO:
1923 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1924 break;
1925 case SMB_FIND_FILE_UNIX:
1926 if (!lp_unix_extensions())
1927 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1928 break;
1929 default:
1930 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1933 if (info_level == SMB_FIND_EA_LIST) {
1934 uint32 ea_size;
1936 if (total_data < 4) {
1937 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1940 ea_size = IVAL(pdata,0);
1941 if (ea_size != total_data) {
1942 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1943 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1947 if (!lp_ea_support(SNUM(conn))) {
1948 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1951 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1952 return ERROR_NT(NT_STATUS_NO_MEMORY);
1955 /* Pull out the list of names. */
1956 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1957 if (!ea_list) {
1958 talloc_destroy(ea_ctx);
1959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1963 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1964 if(pdata == NULL) {
1965 talloc_destroy(ea_ctx);
1966 return ERROR_NT(NT_STATUS_NO_MEMORY);
1969 *ppdata = pdata;
1971 /* Realloc the params space */
1972 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1973 if( params == NULL ) {
1974 talloc_destroy(ea_ctx);
1975 return ERROR_NT(NT_STATUS_NO_MEMORY);
1978 *pparams = params;
1980 /* Check that the dptr is valid */
1981 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1982 talloc_destroy(ea_ctx);
1983 return ERROR_DOS(ERRDOS,ERRnofiles);
1986 string_set(&conn->dirpath,dptr_path(dptr_num));
1988 /* Get the wildcard mask from the dptr */
1989 if((p = dptr_wcard(dptr_num))== NULL) {
1990 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1991 talloc_destroy(ea_ctx);
1992 return ERROR_DOS(ERRDOS,ERRnofiles);
1995 pstrcpy(mask, p);
1996 pstrcpy(directory,conn->dirpath);
1998 /* Get the attr mask from the dptr */
1999 dirtype = dptr_attr(dptr_num);
2001 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2002 dptr_num, mask, dirtype,
2003 (long)conn->dirptr,
2004 dptr_TellDir(conn->dirptr)));
2006 /* We don't need to check for VOL here as this is returned by
2007 a different TRANS2 call. */
2009 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2010 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2011 dont_descend = True;
2013 p = pdata;
2014 space_remaining = max_data_bytes;
2015 out_of_space = False;
2018 * Seek to the correct position. We no longer use the resume key but
2019 * depend on the last file name instead.
2022 if(*resume_name && !continue_bit) {
2023 SMB_STRUCT_STAT st;
2025 long current_pos = 0;
2027 * Remember, mangle_map is called by
2028 * get_lanman2_dir_entry(), so the resume name
2029 * could be mangled. Ensure we check the unmangled name.
2032 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2033 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2037 * Fix for NT redirector problem triggered by resume key indexes
2038 * changing between directory scans. We now return a resume key of 0
2039 * and instead look for the filename to continue from (also given
2040 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2041 * findfirst/findnext (as is usual) then the directory pointer
2042 * should already be at the correct place.
2045 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2046 } /* end if resume_name && !continue_bit */
2048 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2049 BOOL got_exact_match = False;
2051 /* this is a heuristic to avoid seeking the dirptr except when
2052 absolutely necessary. It allows for a filename of about 40 chars */
2053 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2054 out_of_space = True;
2055 finished = False;
2056 } else {
2057 finished = !get_lanman2_dir_entry(conn,
2058 inbuf, outbuf,
2059 mask,dirtype,info_level,
2060 requires_resume_key,dont_descend,
2061 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2062 &last_entry_off, ea_list, ea_ctx);
2065 if (finished && out_of_space)
2066 finished = False;
2068 if (!finished && !out_of_space)
2069 numentries++;
2072 * As an optimisation if we know we aren't looking
2073 * for a wildcard name (ie. the name matches the wildcard exactly)
2074 * then we can finish on any (first) match.
2075 * This speeds up large directory searches. JRA.
2078 if(got_exact_match)
2079 finished = True;
2081 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2084 talloc_destroy(ea_ctx);
2086 /* Check if we can close the dirptr */
2087 if(close_after_request || (finished && close_if_end)) {
2088 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2089 dptr_close(&dptr_num); /* This frees up the saved mask */
2092 /* Set up the return parameter block */
2093 SSVAL(params,0,numentries);
2094 SSVAL(params,2,finished);
2095 SSVAL(params,4,0); /* Never an EA error */
2096 SSVAL(params,6,last_entry_off);
2098 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2100 if ((! *directory) && dptr_path(dptr_num))
2101 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2103 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2104 smb_fn_name(CVAL(inbuf,smb_com)),
2105 mask, directory, dirtype, numentries ) );
2107 return(-1);
2110 /****************************************************************************
2111 Reply to a TRANS2_QFSINFO (query filesystem info).
2112 ****************************************************************************/
2114 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2115 char **pparams, int total_params, char **ppdata, int total_data,
2116 unsigned int max_data_bytes)
2118 char *pdata = *ppdata;
2119 char *params = *pparams;
2120 uint16 info_level = SVAL(params,0);
2121 int data_len, len;
2122 SMB_STRUCT_STAT st;
2123 char *vname = volume_label(SNUM(conn));
2124 int snum = SNUM(conn);
2125 char *fstype = lp_fstype(SNUM(conn));
2126 int quota_flag = 0;
2128 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2130 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2131 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2132 return ERROR_DOS(ERRSRV,ERRinvdevice);
2135 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2136 if ( pdata == NULL ) {
2137 return ERROR_NT(NT_STATUS_NO_MEMORY);
2140 *ppdata = pdata;
2141 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2143 switch (info_level) {
2144 case SMB_INFO_ALLOCATION:
2146 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2147 data_len = 18;
2148 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2149 return(UNIXERROR(ERRHRD,ERRgeneral));
2152 block_size = lp_block_size(snum);
2153 if (bsize < block_size) {
2154 SMB_BIG_UINT factor = block_size/bsize;
2155 bsize = block_size;
2156 dsize /= factor;
2157 dfree /= factor;
2159 if (bsize > block_size) {
2160 SMB_BIG_UINT factor = bsize/block_size;
2161 bsize = block_size;
2162 dsize *= factor;
2163 dfree *= factor;
2165 bytes_per_sector = 512;
2166 sectors_per_unit = bsize/bytes_per_sector;
2168 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2169 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2170 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2172 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2173 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2174 SIVAL(pdata,l1_cUnit,dsize);
2175 SIVAL(pdata,l1_cUnitAvail,dfree);
2176 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2177 break;
2180 case SMB_INFO_VOLUME:
2181 /* Return volume name */
2183 * Add volume serial number - hash of a combination of
2184 * the called hostname and the service name.
2186 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2188 * Win2k3 and previous mess this up by sending a name length
2189 * one byte short. I believe only older clients (OS/2 Win9x) use
2190 * this call so try fixing this by adding a terminating null to
2191 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2193 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2194 SCVAL(pdata,l2_vol_cch,len);
2195 data_len = l2_vol_szVolLabel + len;
2196 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2197 (unsigned)st.st_ctime, len, vname));
2198 break;
2200 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2201 case SMB_FS_ATTRIBUTE_INFORMATION:
2204 #if defined(HAVE_SYS_QUOTAS)
2205 quota_flag = FILE_VOLUME_QUOTAS;
2206 #endif
2208 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2209 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2210 quota_flag); /* FS ATTRIBUTES */
2212 SIVAL(pdata,4,255); /* Max filename component length */
2213 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2214 and will think we can't do long filenames */
2215 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2216 SIVAL(pdata,8,len);
2217 data_len = 12 + len;
2218 break;
2220 case SMB_QUERY_FS_LABEL_INFO:
2221 case SMB_FS_LABEL_INFORMATION:
2222 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2223 data_len = 4 + len;
2224 SIVAL(pdata,0,len);
2225 break;
2227 case SMB_QUERY_FS_VOLUME_INFO:
2228 case SMB_FS_VOLUME_INFORMATION:
2231 * Add volume serial number - hash of a combination of
2232 * the called hostname and the service name.
2234 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2235 (str_checksum(get_local_machine_name())<<16));
2237 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2238 SIVAL(pdata,12,len);
2239 data_len = 18+len;
2240 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2241 (int)strlen(vname),vname, lp_servicename(snum)));
2242 break;
2244 case SMB_QUERY_FS_SIZE_INFO:
2245 case SMB_FS_SIZE_INFORMATION:
2247 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2248 data_len = 24;
2249 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2250 return(UNIXERROR(ERRHRD,ERRgeneral));
2252 block_size = lp_block_size(snum);
2253 if (bsize < block_size) {
2254 SMB_BIG_UINT factor = block_size/bsize;
2255 bsize = block_size;
2256 dsize /= factor;
2257 dfree /= factor;
2259 if (bsize > block_size) {
2260 SMB_BIG_UINT factor = bsize/block_size;
2261 bsize = block_size;
2262 dsize *= factor;
2263 dfree *= factor;
2265 bytes_per_sector = 512;
2266 sectors_per_unit = bsize/bytes_per_sector;
2267 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2268 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2269 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2270 SBIG_UINT(pdata,0,dsize);
2271 SBIG_UINT(pdata,8,dfree);
2272 SIVAL(pdata,16,sectors_per_unit);
2273 SIVAL(pdata,20,bytes_per_sector);
2274 break;
2277 case SMB_FS_FULL_SIZE_INFORMATION:
2279 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2280 data_len = 32;
2281 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2282 return(UNIXERROR(ERRHRD,ERRgeneral));
2284 block_size = lp_block_size(snum);
2285 if (bsize < block_size) {
2286 SMB_BIG_UINT factor = block_size/bsize;
2287 bsize = block_size;
2288 dsize /= factor;
2289 dfree /= factor;
2291 if (bsize > block_size) {
2292 SMB_BIG_UINT factor = bsize/block_size;
2293 bsize = block_size;
2294 dsize *= factor;
2295 dfree *= factor;
2297 bytes_per_sector = 512;
2298 sectors_per_unit = bsize/bytes_per_sector;
2299 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2300 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2301 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2302 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2303 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2304 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2305 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2306 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2307 break;
2310 case SMB_QUERY_FS_DEVICE_INFO:
2311 case SMB_FS_DEVICE_INFORMATION:
2312 data_len = 8;
2313 SIVAL(pdata,0,0); /* dev type */
2314 SIVAL(pdata,4,0); /* characteristics */
2315 break;
2317 #ifdef HAVE_SYS_QUOTAS
2318 case SMB_FS_QUOTA_INFORMATION:
2320 * what we have to send --metze:
2322 * Unknown1: 24 NULL bytes
2323 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2324 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2325 * Quota Flags: 2 byte :
2326 * Unknown3: 6 NULL bytes
2328 * 48 bytes total
2330 * details for Quota Flags:
2332 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2333 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2334 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2335 * 0x0001 Enable Quotas: enable quota for this fs
2339 /* we need to fake up a fsp here,
2340 * because its not send in this call
2342 files_struct fsp;
2343 SMB_NTQUOTA_STRUCT quotas;
2345 ZERO_STRUCT(fsp);
2346 ZERO_STRUCT(quotas);
2348 fsp.conn = conn;
2349 fsp.fnum = -1;
2350 fsp.fh->fd = -1;
2352 /* access check */
2353 if (current_user.uid != 0) {
2354 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2355 lp_servicename(SNUM(conn)),conn->user));
2356 return ERROR_DOS(ERRDOS,ERRnoaccess);
2359 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2360 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2361 return ERROR_DOS(ERRSRV,ERRerror);
2364 data_len = 48;
2366 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2368 /* Unknown1 24 NULL bytes*/
2369 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2370 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2371 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2373 /* Default Soft Quota 8 bytes */
2374 SBIG_UINT(pdata,24,quotas.softlim);
2376 /* Default Hard Quota 8 bytes */
2377 SBIG_UINT(pdata,32,quotas.hardlim);
2379 /* Quota flag 2 bytes */
2380 SSVAL(pdata,40,quotas.qflags);
2382 /* Unknown3 6 NULL bytes */
2383 SSVAL(pdata,42,0);
2384 SIVAL(pdata,44,0);
2386 break;
2388 #endif /* HAVE_SYS_QUOTAS */
2389 case SMB_FS_OBJECTID_INFORMATION:
2390 data_len = 64;
2391 break;
2394 * Query the version and capabilities of the CIFS UNIX extensions
2395 * in use.
2398 case SMB_QUERY_CIFS_UNIX_INFO:
2399 if (!lp_unix_extensions())
2400 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2401 data_len = 12;
2402 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2403 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2404 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2405 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2406 break;
2408 case SMB_MAC_QUERY_FS_INFO:
2410 * Thursby MAC extension... ONLY on NTFS filesystems
2411 * once we do streams then we don't need this
2413 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2414 data_len = 88;
2415 SIVAL(pdata,84,0x100); /* Don't support mac... */
2416 break;
2418 /* drop through */
2419 default:
2420 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2424 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2426 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2428 return -1;
2431 /****************************************************************************
2432 Reply to a TRANS2_SETFSINFO (set filesystem info).
2433 ****************************************************************************/
2435 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2436 char **pparams, int total_params, char **ppdata, int total_data,
2437 unsigned int max_data_bytes)
2439 char *pdata = *ppdata;
2440 char *params = *pparams;
2441 uint16 info_level;
2442 int outsize;
2444 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2446 /* */
2447 if (total_params < 4) {
2448 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2449 total_params));
2450 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2453 info_level = SVAL(params,2);
2455 switch(info_level) {
2456 case SMB_SET_CIFS_UNIX_INFO:
2458 uint16 client_unix_major;
2459 uint16 client_unix_minor;
2460 uint32 client_unix_cap_low;
2461 uint32 client_unix_cap_high;
2463 if (!lp_unix_extensions()) {
2464 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2467 /* There should be 12 bytes of capabilities set. */
2468 if (total_data < 8) {
2469 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2471 client_unix_major = SVAL(pdata,0);
2472 client_unix_minor = SVAL(pdata,2);
2473 client_unix_cap_low = IVAL(pdata,4);
2474 client_unix_cap_high = IVAL(pdata,8);
2475 /* Just print these values for now. */
2476 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2477 cap_low = 0x%x, cap_high = 0x%x\n",
2478 (unsigned int)client_unix_major,
2479 (unsigned int)client_unix_minor,
2480 (unsigned int)client_unix_cap_low,
2481 (unsigned int)client_unix_cap_high ));
2483 /* Here is where we must switch to posix pathname processing... */
2484 lp_set_posix_pathnames();
2485 mangle_change_to_posix();
2486 break;
2488 case SMB_FS_QUOTA_INFORMATION:
2490 files_struct *fsp = NULL;
2491 SMB_NTQUOTA_STRUCT quotas;
2493 ZERO_STRUCT(quotas);
2495 /* access check */
2496 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2497 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2498 lp_servicename(SNUM(conn)),conn->user));
2499 return ERROR_DOS(ERRSRV,ERRaccess);
2502 /* note: normaly there're 48 bytes,
2503 * but we didn't use the last 6 bytes for now
2504 * --metze
2506 fsp = file_fsp(params,0);
2507 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2508 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2509 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2512 if (total_data < 42) {
2513 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2514 total_data));
2515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2518 /* unknown_1 24 NULL bytes in pdata*/
2520 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2521 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2522 #ifdef LARGE_SMB_OFF_T
2523 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2524 #else /* LARGE_SMB_OFF_T */
2525 if ((IVAL(pdata,28) != 0)&&
2526 ((quotas.softlim != 0xFFFFFFFF)||
2527 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2528 /* more than 32 bits? */
2529 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2531 #endif /* LARGE_SMB_OFF_T */
2533 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2534 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2535 #ifdef LARGE_SMB_OFF_T
2536 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2537 #else /* LARGE_SMB_OFF_T */
2538 if ((IVAL(pdata,36) != 0)&&
2539 ((quotas.hardlim != 0xFFFFFFFF)||
2540 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2541 /* more than 32 bits? */
2542 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2544 #endif /* LARGE_SMB_OFF_T */
2546 /* quota_flags 2 bytes **/
2547 quotas.qflags = SVAL(pdata,40);
2549 /* unknown_2 6 NULL bytes follow*/
2551 /* now set the quotas */
2552 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2553 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2554 return ERROR_DOS(ERRSRV,ERRerror);
2557 break;
2559 default:
2560 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2561 info_level));
2562 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2563 break;
2567 * sending this reply works fine,
2568 * but I'm not sure it's the same
2569 * like windows do...
2570 * --metze
2572 outsize = set_message(outbuf,10,0,True);
2574 return outsize;
2577 /****************************************************************************
2578 Utility function to set bad path error.
2579 ****************************************************************************/
2581 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2583 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2584 err, (int)bad_path ));
2586 if(err == ENOENT) {
2587 if (bad_path) {
2588 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2589 } else {
2590 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2593 return UNIXERROR(def_class,def_code);
2596 #if defined(HAVE_POSIX_ACLS)
2597 /****************************************************************************
2598 Utility function to count the number of entries in a POSIX acl.
2599 ****************************************************************************/
2601 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2603 unsigned int ace_count = 0;
2604 int entry_id = SMB_ACL_FIRST_ENTRY;
2605 SMB_ACL_ENTRY_T entry;
2607 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2608 /* get_next... */
2609 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2610 entry_id = SMB_ACL_NEXT_ENTRY;
2612 ace_count++;
2614 return ace_count;
2617 /****************************************************************************
2618 Utility function to marshall a POSIX acl into wire format.
2619 ****************************************************************************/
2621 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2623 int entry_id = SMB_ACL_FIRST_ENTRY;
2624 SMB_ACL_ENTRY_T entry;
2626 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2627 SMB_ACL_TAG_T tagtype;
2628 SMB_ACL_PERMSET_T permset;
2629 unsigned char perms = 0;
2630 unsigned int own_grp;
2632 /* get_next... */
2633 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2634 entry_id = SMB_ACL_NEXT_ENTRY;
2637 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2638 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2639 return False;
2642 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2643 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2644 return False;
2647 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2648 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2649 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2651 SCVAL(pdata,1,perms);
2653 switch (tagtype) {
2654 case SMB_ACL_USER_OBJ:
2655 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2656 own_grp = (unsigned int)pst->st_uid;
2657 SIVAL(pdata,2,own_grp);
2658 SIVAL(pdata,6,0);
2659 break;
2660 case SMB_ACL_USER:
2662 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2663 if (!puid) {
2664 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2666 own_grp = (unsigned int)*puid;
2667 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2668 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2669 SIVAL(pdata,2,own_grp);
2670 SIVAL(pdata,6,0);
2671 break;
2673 case SMB_ACL_GROUP_OBJ:
2674 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2675 own_grp = (unsigned int)pst->st_gid;
2676 SIVAL(pdata,2,own_grp);
2677 SIVAL(pdata,6,0);
2678 break;
2679 case SMB_ACL_GROUP:
2681 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2682 if (!pgid) {
2683 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2685 own_grp = (unsigned int)*pgid;
2686 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2687 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2688 SIVAL(pdata,2,own_grp);
2689 SIVAL(pdata,6,0);
2690 break;
2692 case SMB_ACL_MASK:
2693 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2694 SIVAL(pdata,2,0xFFFFFFFF);
2695 SIVAL(pdata,6,0xFFFFFFFF);
2696 break;
2697 case SMB_ACL_OTHER:
2698 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2699 SIVAL(pdata,2,0xFFFFFFFF);
2700 SIVAL(pdata,6,0xFFFFFFFF);
2701 break;
2702 default:
2703 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2704 return False;
2706 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2709 return True;
2711 #endif
2713 /****************************************************************************
2714 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2715 file name or file id).
2716 ****************************************************************************/
2718 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2719 unsigned int tran_call,
2720 char **pparams, int total_params, char **ppdata, int total_data,
2721 unsigned int max_data_bytes)
2723 char *params = *pparams;
2724 char *pdata = *ppdata;
2725 uint16 info_level;
2726 int mode=0;
2727 int nlink;
2728 SMB_OFF_T file_size=0;
2729 SMB_BIG_UINT allocation_size=0;
2730 unsigned int data_size = 0;
2731 unsigned int param_size = 2;
2732 SMB_STRUCT_STAT sbuf;
2733 pstring fname, dos_fname;
2734 char *fullpathname;
2735 char *base_name;
2736 char *p;
2737 SMB_OFF_T pos = 0;
2738 BOOL bad_path = False;
2739 BOOL delete_pending = False;
2740 int len;
2741 time_t c_time;
2742 files_struct *fsp = NULL;
2743 TALLOC_CTX *ea_ctx = NULL;
2744 struct ea_list *ea_list = NULL;
2745 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2747 if (!params)
2748 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2750 ZERO_STRUCT(sbuf);
2752 if (tran_call == TRANSACT2_QFILEINFO) {
2753 if (total_params < 4) {
2754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2757 fsp = file_fsp(params,0);
2758 info_level = SVAL(params,2);
2760 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2762 if(fsp && (fsp->fake_file_handle)) {
2764 * This is actually for the QUOTA_FAKE_FILE --metze
2767 pstrcpy(fname, fsp->fsp_name);
2768 /* We know this name is ok, it's already passed the checks. */
2770 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2772 * This is actually a QFILEINFO on a directory
2773 * handle (returned from an NT SMB). NT5.0 seems
2774 * to do this call. JRA.
2776 /* We know this name is ok, it's already passed the checks. */
2777 pstrcpy(fname, fsp->fsp_name);
2779 if (INFO_LEVEL_IS_UNIX(info_level)) {
2780 /* Always do lstat for UNIX calls. */
2781 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2782 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2783 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2785 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2786 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2787 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2790 delete_pending =
2791 get_delete_on_close_flag(sbuf.st_dev,
2792 sbuf.st_ino);
2793 } else {
2795 * Original code - this is an open file.
2797 CHECK_FSP(fsp,conn);
2799 pstrcpy(fname, fsp->fsp_name);
2800 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2801 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2802 return(UNIXERROR(ERRDOS,ERRbadfid));
2804 pos = fsp->fh->position_information;
2805 delete_pending =
2806 get_delete_on_close_flag(sbuf.st_dev,
2807 sbuf.st_ino);
2808 access_mask = fsp->access_mask;
2810 } else {
2811 NTSTATUS status = NT_STATUS_OK;
2813 /* qpathinfo */
2814 if (total_params < 6) {
2815 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2818 info_level = SVAL(params,0);
2820 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2822 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2823 if (!NT_STATUS_IS_OK(status)) {
2824 return ERROR_NT(status);
2827 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2829 unix_convert(fname,conn,0,&bad_path,&sbuf);
2830 if (bad_path) {
2831 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2833 if (!check_name(fname,conn)) {
2834 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2835 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2838 if (INFO_LEVEL_IS_UNIX(info_level)) {
2839 /* Always do lstat for UNIX calls. */
2840 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2841 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2842 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2844 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2845 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2846 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2849 delete_pending = get_delete_on_close_flag(sbuf.st_dev,
2850 sbuf.st_ino);
2851 if (delete_pending) {
2852 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2856 nlink = sbuf.st_nlink;
2858 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2859 /* NTFS does not seem to count ".." */
2860 nlink -= 1;
2863 if ((nlink > 0) && delete_pending) {
2864 nlink -= 1;
2867 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2868 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2870 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2871 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2873 p = strrchr_m(fname,'/');
2874 if (!p)
2875 base_name = fname;
2876 else
2877 base_name = p+1;
2879 mode = dos_mode(conn,fname,&sbuf);
2880 if (!mode)
2881 mode = FILE_ATTRIBUTE_NORMAL;
2883 fullpathname = fname;
2884 file_size = get_file_size(sbuf);
2885 if (mode & aDIR) {
2886 /* This is necessary, as otherwise the desktop.ini file in
2887 * this folder is ignored */
2888 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2889 file_size = 0;
2892 /* Pull any EA list from the data portion. */
2893 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2894 uint32 ea_size;
2896 if (total_data < 4) {
2897 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2899 ea_size = IVAL(pdata,0);
2901 if (total_data > 0 && ea_size != total_data) {
2902 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2903 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2904 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2907 if (!lp_ea_support(SNUM(conn))) {
2908 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2911 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2912 return ERROR_NT(NT_STATUS_NO_MEMORY);
2915 /* Pull out the list of names. */
2916 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2917 if (!ea_list) {
2918 talloc_destroy(ea_ctx);
2919 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2923 params = SMB_REALLOC(*pparams,2);
2924 if (params == NULL) {
2925 talloc_destroy(ea_ctx);
2926 return ERROR_NT(NT_STATUS_NO_MEMORY);
2928 *pparams = params;
2929 SSVAL(params,0,0);
2930 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2931 pdata = SMB_REALLOC(*ppdata, data_size);
2932 if ( pdata == NULL ) {
2933 talloc_destroy(ea_ctx);
2934 return ERROR_NT(NT_STATUS_NO_MEMORY);
2936 *ppdata = pdata;
2938 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2940 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2942 if (fsp) {
2943 if (fsp->pending_modtime) {
2944 /* the pending modtime overrides the current modtime */
2945 sbuf.st_mtime = fsp->pending_modtime;
2947 } else {
2948 /* Do we have this path open ? */
2949 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2950 if (fsp1 && fsp1->pending_modtime) {
2951 /* the pending modtime overrides the current modtime */
2952 sbuf.st_mtime = fsp1->pending_modtime;
2954 if (fsp1 && fsp1->initial_allocation_size) {
2955 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2959 if (lp_dos_filetime_resolution(SNUM(conn))) {
2960 c_time &= ~1;
2961 sbuf.st_atime &= ~1;
2962 sbuf.st_ctime &= ~1;
2963 sbuf.st_mtime &= ~1;
2966 /* NT expects the name to be in an exact form of the *full*
2967 filename. See the trans2 torture test */
2968 if (strequal(base_name,".")) {
2969 pstrcpy(dos_fname, "\\");
2970 } else {
2971 pstr_sprintf(dos_fname, "\\%s", fname);
2972 string_replace(dos_fname, '/', '\\');
2975 switch (info_level) {
2976 case SMB_INFO_STANDARD:
2977 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2978 data_size = 22;
2979 put_dos_date2(pdata,l1_fdateCreation,c_time);
2980 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2981 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2982 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2983 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2984 SSVAL(pdata,l1_attrFile,mode);
2985 break;
2987 case SMB_INFO_QUERY_EA_SIZE:
2989 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2990 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2991 data_size = 26;
2992 put_dos_date2(pdata,0,c_time);
2993 put_dos_date2(pdata,4,sbuf.st_atime);
2994 put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
2995 SIVAL(pdata,12,(uint32)file_size);
2996 SIVAL(pdata,16,(uint32)allocation_size);
2997 SSVAL(pdata,20,mode);
2998 SIVAL(pdata,22,ea_size);
2999 break;
3002 case SMB_INFO_IS_NAME_VALID:
3003 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3004 if (tran_call == TRANSACT2_QFILEINFO) {
3005 /* os/2 needs this ? really ?*/
3006 return ERROR_DOS(ERRDOS,ERRbadfunc);
3008 data_size = 0;
3009 param_size = 0;
3010 break;
3012 case SMB_INFO_QUERY_EAS_FROM_LIST:
3014 size_t total_ea_len = 0;
3015 struct ea_list *ea_file_list = NULL;
3017 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3019 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3020 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3022 if (!ea_list || (total_ea_len > data_size)) {
3023 talloc_destroy(ea_ctx);
3024 data_size = 4;
3025 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3026 break;
3029 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3030 talloc_destroy(ea_ctx);
3031 break;
3034 case SMB_INFO_QUERY_ALL_EAS:
3036 /* We have data_size bytes to put EA's into. */
3037 size_t total_ea_len = 0;
3039 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3041 ea_ctx = talloc_init("ea_ctx");
3042 if (!ea_ctx) {
3043 return ERROR_NT(NT_STATUS_NO_MEMORY);
3046 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3047 if (!ea_list || (total_ea_len > data_size)) {
3048 talloc_destroy(ea_ctx);
3049 data_size = 4;
3050 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3051 break;
3054 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3055 talloc_destroy(ea_ctx);
3056 break;
3059 case SMB_FILE_BASIC_INFORMATION:
3060 case SMB_QUERY_FILE_BASIC_INFO:
3062 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3063 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3064 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3065 } else {
3066 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3067 data_size = 40;
3068 SIVAL(pdata,36,0);
3070 put_long_date(pdata,c_time);
3071 put_long_date(pdata+8,sbuf.st_atime);
3072 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3073 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3074 SIVAL(pdata,32,mode);
3076 DEBUG(5,("SMB_QFBI - "));
3078 time_t create_time = c_time;
3079 DEBUG(5,("create: %s ", ctime(&create_time)));
3081 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3082 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3083 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3084 DEBUG(5,("mode: %x\n", mode));
3085 break;
3087 case SMB_FILE_STANDARD_INFORMATION:
3088 case SMB_QUERY_FILE_STANDARD_INFO:
3090 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3091 data_size = 24;
3092 SOFF_T(pdata,0,allocation_size);
3093 SOFF_T(pdata,8,file_size);
3094 SIVAL(pdata,16,nlink);
3095 SCVAL(pdata,20,delete_pending?1:0);
3096 SCVAL(pdata,21,(mode&aDIR)?1:0);
3097 SSVAL(pdata,22,0); /* Padding. */
3098 break;
3100 case SMB_FILE_EA_INFORMATION:
3101 case SMB_QUERY_FILE_EA_INFO:
3103 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3104 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3105 data_size = 4;
3106 SIVAL(pdata,0,ea_size);
3107 break;
3110 /* Get the 8.3 name - used if NT SMB was negotiated. */
3111 case SMB_QUERY_FILE_ALT_NAME_INFO:
3112 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3114 pstring short_name;
3116 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3117 pstrcpy(short_name,base_name);
3118 /* Mangle if not already 8.3 */
3119 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3120 mangle_map(short_name,True,True,SNUM(conn));
3122 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3123 data_size = 4 + len;
3124 SIVAL(pdata,0,len);
3125 break;
3128 case SMB_QUERY_FILE_NAME_INFO:
3130 this must be *exactly* right for ACLs on mapped drives to work
3132 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3133 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3134 data_size = 4 + len;
3135 SIVAL(pdata,0,len);
3136 break;
3138 case SMB_FILE_ALLOCATION_INFORMATION:
3139 case SMB_QUERY_FILE_ALLOCATION_INFO:
3140 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3141 data_size = 8;
3142 SOFF_T(pdata,0,allocation_size);
3143 break;
3145 case SMB_FILE_END_OF_FILE_INFORMATION:
3146 case SMB_QUERY_FILE_END_OF_FILEINFO:
3147 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3148 data_size = 8;
3149 SOFF_T(pdata,0,file_size);
3150 break;
3152 case SMB_QUERY_FILE_ALL_INFO:
3153 case SMB_FILE_ALL_INFORMATION:
3155 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3156 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3157 put_long_date(pdata,c_time);
3158 put_long_date(pdata+8,sbuf.st_atime);
3159 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3160 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3161 SIVAL(pdata,32,mode);
3162 SIVAL(pdata,36,0); /* padding. */
3163 pdata += 40;
3164 SOFF_T(pdata,0,allocation_size);
3165 SOFF_T(pdata,8,file_size);
3166 SIVAL(pdata,16,nlink);
3167 SCVAL(pdata,20,delete_pending);
3168 SCVAL(pdata,21,(mode&aDIR)?1:0);
3169 SSVAL(pdata,22,0);
3170 pdata += 24;
3171 SIVAL(pdata,0,ea_size);
3172 pdata += 4; /* EA info */
3173 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3174 SIVAL(pdata,0,len);
3175 pdata += 4 + len;
3176 data_size = PTR_DIFF(pdata,(*ppdata));
3177 break;
3179 case SMB_FILE_INTERNAL_INFORMATION:
3180 /* This should be an index number - looks like
3181 dev/ino to me :-)
3183 I think this causes us to fail the IFSKIT
3184 BasicFileInformationTest. -tpot */
3186 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3187 SIVAL(pdata,0,sbuf.st_dev);
3188 SIVAL(pdata,4,sbuf.st_ino);
3189 data_size = 8;
3190 break;
3192 case SMB_FILE_ACCESS_INFORMATION:
3193 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3194 SIVAL(pdata,0,access_mask);
3195 data_size = 4;
3196 break;
3198 case SMB_FILE_NAME_INFORMATION:
3199 /* Pathname with leading '\'. */
3201 size_t byte_len;
3202 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3203 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3204 SIVAL(pdata,0,byte_len);
3205 data_size = 4 + byte_len;
3206 break;
3209 case SMB_FILE_DISPOSITION_INFORMATION:
3210 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3211 data_size = 1;
3212 SCVAL(pdata,0,delete_pending);
3213 break;
3215 case SMB_FILE_POSITION_INFORMATION:
3216 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3217 data_size = 8;
3218 SOFF_T(pdata,0,pos);
3219 break;
3221 case SMB_FILE_MODE_INFORMATION:
3222 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3223 SIVAL(pdata,0,mode);
3224 data_size = 4;
3225 break;
3227 case SMB_FILE_ALIGNMENT_INFORMATION:
3228 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3229 SIVAL(pdata,0,0); /* No alignment needed. */
3230 data_size = 4;
3231 break;
3233 #if 0
3235 * NT4 server just returns "invalid query" to this - if we try to answer
3236 * it then NTws gets a BSOD! (tridge).
3237 * W2K seems to want this. JRA.
3239 case SMB_QUERY_FILE_STREAM_INFO:
3240 #endif
3241 case SMB_FILE_STREAM_INFORMATION:
3242 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3243 if (mode & aDIR) {
3244 data_size = 0;
3245 } else {
3246 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3247 SIVAL(pdata,0,0); /* ??? */
3248 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3249 SOFF_T(pdata,8,file_size);
3250 SIVAL(pdata,16,allocation_size);
3251 SIVAL(pdata,20,0); /* ??? */
3252 data_size = 24 + byte_len;
3254 break;
3256 case SMB_QUERY_COMPRESSION_INFO:
3257 case SMB_FILE_COMPRESSION_INFORMATION:
3258 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3259 SOFF_T(pdata,0,file_size);
3260 SIVAL(pdata,8,0); /* ??? */
3261 SIVAL(pdata,12,0); /* ??? */
3262 data_size = 16;
3263 break;
3265 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3266 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3267 put_long_date(pdata,c_time);
3268 put_long_date(pdata+8,sbuf.st_atime);
3269 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3270 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3271 SIVAL(pdata,32,allocation_size);
3272 SOFF_T(pdata,40,file_size);
3273 SIVAL(pdata,48,mode);
3274 SIVAL(pdata,52,0); /* ??? */
3275 data_size = 56;
3276 break;
3278 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3279 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3280 SIVAL(pdata,0,mode);
3281 SIVAL(pdata,4,0);
3282 data_size = 8;
3283 break;
3286 * CIFS UNIX Extensions.
3289 case SMB_QUERY_FILE_UNIX_BASIC:
3291 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3292 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3294 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3295 pdata += 8;
3297 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3298 pdata += 8;
3300 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3301 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3302 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3303 pdata += 24;
3305 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3306 SIVAL(pdata,4,0);
3307 pdata += 8;
3309 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3310 SIVAL(pdata,4,0);
3311 pdata += 8;
3313 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3314 pdata += 4;
3316 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3317 SIVAL(pdata,4,0);
3318 pdata += 8;
3320 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3321 SIVAL(pdata,4,0);
3322 pdata += 8;
3324 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3325 pdata += 8;
3327 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3328 SIVAL(pdata,4,0);
3329 pdata += 8;
3331 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3332 SIVAL(pdata,4,0);
3333 pdata += 8+1;
3334 data_size = PTR_DIFF(pdata,(*ppdata));
3337 int i;
3338 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3340 for (i=0; i<100; i++)
3341 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3342 DEBUG(4,("\n"));
3345 break;
3347 case SMB_QUERY_FILE_UNIX_LINK:
3349 pstring buffer;
3351 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3352 #ifdef S_ISLNK
3353 if(!S_ISLNK(sbuf.st_mode))
3354 return(UNIXERROR(ERRSRV,ERRbadlink));
3355 #else
3356 return(UNIXERROR(ERRDOS,ERRbadlink));
3357 #endif
3358 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3359 if (len == -1)
3360 return(UNIXERROR(ERRDOS,ERRnoaccess));
3361 buffer[len] = 0;
3362 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3363 pdata += len;
3364 data_size = PTR_DIFF(pdata,(*ppdata));
3366 break;
3369 #if defined(HAVE_POSIX_ACLS)
3370 case SMB_QUERY_POSIX_ACL:
3372 SMB_ACL_T file_acl = NULL;
3373 SMB_ACL_T def_acl = NULL;
3374 uint16 num_file_acls = 0;
3375 uint16 num_def_acls = 0;
3377 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3378 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3379 } else {
3380 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3383 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3384 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3385 fname ));
3386 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3389 if (S_ISDIR(sbuf.st_mode)) {
3390 if (fsp && fsp->is_directory) {
3391 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3392 } else {
3393 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3395 def_acl = free_empty_sys_acl(conn, def_acl);
3398 num_file_acls = count_acl_entries(conn, file_acl);
3399 num_def_acls = count_acl_entries(conn, def_acl);
3401 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3402 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3403 data_size,
3404 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3405 SMB_POSIX_ACL_HEADER_SIZE) ));
3406 if (file_acl) {
3407 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3409 if (def_acl) {
3410 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3412 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3415 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3416 SSVAL(pdata,2,num_file_acls);
3417 SSVAL(pdata,4,num_def_acls);
3418 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3419 if (file_acl) {
3420 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3422 if (def_acl) {
3423 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3425 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3427 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3428 if (file_acl) {
3429 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3431 if (def_acl) {
3432 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3434 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3437 if (file_acl) {
3438 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3440 if (def_acl) {
3441 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3443 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3444 break;
3446 #endif
3448 default:
3449 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3452 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3454 return(-1);
3457 /****************************************************************************
3458 Deal with the internal needs of setting the delete on close flag. Note that
3459 as the tdb locking is recursive, it is safe to call this from within
3460 open_file_shared. JRA.
3461 ****************************************************************************/
3463 NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
3464 uint32 dosmode)
3466 if (!delete_on_close) {
3467 return NT_STATUS_OK;
3471 * Only allow delete on close for writable files.
3474 if ((dosmode & aRONLY) &&
3475 !lp_delete_readonly(SNUM(fsp->conn))) {
3476 DEBUG(10,("can_set_delete_on_close: file %s delete on close "
3477 "flag set but file attribute is readonly.\n",
3478 fsp->fsp_name ));
3479 return NT_STATUS_CANNOT_DELETE;
3483 * Only allow delete on close for writable shares.
3486 if (!CAN_WRITE(fsp->conn)) {
3487 DEBUG(10,("can_set_delete_on_close: file %s delete on "
3488 "close flag set but write access denied on share.\n",
3489 fsp->fsp_name ));
3490 return NT_STATUS_ACCESS_DENIED;
3494 * Only allow delete on close for files/directories opened with delete
3495 * intent.
3498 if (!(fsp->access_mask & DELETE_ACCESS)) {
3499 DEBUG(10,("can_set_delete_on_close: file %s delete on "
3500 "close flag set but delete access denied.\n",
3501 fsp->fsp_name ));
3502 return NT_STATUS_ACCESS_DENIED;
3505 return NT_STATUS_OK;
3508 /****************************************************************************
3509 Sets the delete on close flag over all share modes on this file.
3510 Modify the share mode entry for all files open
3511 on this device and inode to tell other smbds we have
3512 changed the delete on close flag. This will be noticed
3513 in the close code, the last closer will delete the file
3514 if flag is set.
3515 ****************************************************************************/
3517 NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
3519 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
3520 "fnum = %d, file %s\n",
3521 delete_on_close ? "Adding" : "Removing", fsp->fnum,
3522 fsp->fsp_name ));
3524 if (fsp->is_directory || fsp->is_stat)
3525 return NT_STATUS_OK;
3527 if (lock_share_entry_fsp(fsp) == False)
3528 return NT_STATUS_ACCESS_DENIED;
3530 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3531 DEBUG(0,("set_delete_on_close: failed to change delete "
3532 "on close flag for file %s\n",
3533 fsp->fsp_name ));
3534 unlock_share_entry_fsp(fsp);
3535 return NT_STATUS_ACCESS_DENIED;
3538 unlock_share_entry_fsp(fsp);
3539 return NT_STATUS_OK;
3542 /****************************************************************************
3543 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3544 code.
3545 ****************************************************************************/
3547 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3549 BOOL bad_path_oldname = False;
3550 BOOL bad_path_newname = False;
3551 SMB_STRUCT_STAT sbuf1, sbuf2;
3552 pstring last_component_oldname;
3553 pstring last_component_newname;
3554 NTSTATUS status = NT_STATUS_OK;
3556 ZERO_STRUCT(sbuf1);
3557 ZERO_STRUCT(sbuf2);
3559 /* No wildcards. */
3560 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3561 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3564 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3565 if (bad_path_oldname) {
3566 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3569 /* Quick check for "." and ".." */
3570 if (last_component_oldname[0] == '.') {
3571 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3572 return NT_STATUS_OBJECT_NAME_INVALID;
3576 /* source must already exist. */
3577 if (!VALID_STAT(sbuf1)) {
3578 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3581 if (!check_name(oldname,conn)) {
3582 return NT_STATUS_ACCESS_DENIED;
3585 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3586 if (bad_path_newname) {
3587 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3590 /* Quick check for "." and ".." */
3591 if (last_component_newname[0] == '.') {
3592 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3593 return NT_STATUS_OBJECT_NAME_INVALID;
3597 /* Disallow if newname already exists. */
3598 if (VALID_STAT(sbuf2)) {
3599 return NT_STATUS_OBJECT_NAME_COLLISION;
3602 if (!check_name(newname,conn)) {
3603 return NT_STATUS_ACCESS_DENIED;
3606 /* No links from a directory. */
3607 if (S_ISDIR(sbuf1.st_mode)) {
3608 return NT_STATUS_FILE_IS_A_DIRECTORY;
3611 /* Ensure this is within the share. */
3612 if (!reduce_name(conn, oldname) != 0)
3613 return NT_STATUS_ACCESS_DENIED;
3615 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3617 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3618 status = map_nt_error_from_unix(errno);
3619 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3620 nt_errstr(status), newname, oldname));
3623 return status;
3626 /****************************************************************************
3627 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3628 ****************************************************************************/
3630 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3631 unsigned int tran_call,
3632 char **pparams, int total_params, char **ppdata, int total_data,
3633 unsigned int max_data_bytes)
3635 char *params = *pparams;
3636 char *pdata = *ppdata;
3637 uint16 info_level;
3638 int dosmode=0;
3639 SMB_OFF_T size=0;
3640 struct utimbuf tvs;
3641 SMB_STRUCT_STAT sbuf;
3642 pstring fname;
3643 int fd = -1;
3644 BOOL bad_path = False;
3645 files_struct *fsp = NULL;
3646 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3647 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3648 mode_t unixmode = 0;
3649 NTSTATUS status = NT_STATUS_OK;
3651 if (!params)
3652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3654 ZERO_STRUCT(sbuf);
3655 ZERO_STRUCT(tvs);
3657 if (tran_call == TRANSACT2_SETFILEINFO) {
3658 if (total_params < 4) {
3659 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3662 fsp = file_fsp(params,0);
3663 info_level = SVAL(params,2);
3665 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3667 * This is actually a SETFILEINFO on a directory
3668 * handle (returned from an NT SMB). NT5.0 seems
3669 * to do this call. JRA.
3671 pstrcpy(fname, fsp->fsp_name);
3672 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3673 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3674 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3676 } else if (fsp && fsp->print_file) {
3678 * Doing a DELETE_ON_CLOSE should cancel a print job.
3680 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3681 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3683 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3685 SSVAL(params,0,0);
3686 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3687 return(-1);
3688 } else
3689 return (UNIXERROR(ERRDOS,ERRbadpath));
3690 } else {
3692 * Original code - this is an open file.
3694 CHECK_FSP(fsp,conn);
3696 pstrcpy(fname, fsp->fsp_name);
3697 fd = fsp->fh->fd;
3699 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3700 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3701 return(UNIXERROR(ERRDOS,ERRbadfid));
3704 } else {
3705 /* set path info */
3706 if (total_params < 6) {
3707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3710 info_level = SVAL(params,0);
3711 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 return ERROR_NT(status);
3715 unix_convert(fname,conn,0,&bad_path,&sbuf);
3716 if (bad_path) {
3717 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3721 * For CIFS UNIX extensions the target name may not exist.
3724 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3725 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3726 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3729 if(!check_name(fname, conn)) {
3730 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3735 if (!CAN_WRITE(conn))
3736 return ERROR_DOS(ERRSRV,ERRaccess);
3738 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3739 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3741 if (VALID_STAT(sbuf))
3742 unixmode = sbuf.st_mode;
3744 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3745 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3747 /* Realloc the parameter size */
3748 params = SMB_REALLOC(*pparams,2);
3749 if(params == NULL) {
3750 return ERROR_NT(NT_STATUS_NO_MEMORY);
3752 *pparams = params;
3754 SSVAL(params,0,0);
3756 if (fsp && fsp->pending_modtime) {
3757 /* the pending modtime overrides the current modtime */
3758 sbuf.st_mtime = fsp->pending_modtime;
3761 size = get_file_size(sbuf);
3762 tvs.modtime = sbuf.st_mtime;
3763 tvs.actime = sbuf.st_atime;
3764 dosmode = dos_mode(conn,fname,&sbuf);
3765 unixmode = sbuf.st_mode;
3767 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3768 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3770 switch (info_level) {
3771 case SMB_INFO_STANDARD:
3773 if (total_data < 12) {
3774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3777 /* access time */
3778 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3779 /* write time */
3780 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3781 break;
3784 case SMB_INFO_SET_EA:
3786 struct ea_list *ea_list = NULL;
3787 TALLOC_CTX *ctx = NULL;
3789 if (total_data < 10) {
3790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3793 if (IVAL(pdata,0) > total_data) {
3794 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3795 IVAL(pdata,0), (unsigned int)total_data));
3796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3799 ctx = talloc_init("SMB_INFO_SET_EA");
3800 if (!ctx) {
3801 return ERROR_NT(NT_STATUS_NO_MEMORY);
3803 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3804 if (!ea_list) {
3805 talloc_destroy(ctx);
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3808 status = set_ea(conn, fsp, fname, ea_list);
3809 talloc_destroy(ctx);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 return ERROR_NT(status);
3815 /* We're done. We only get EA info in this call. */
3816 SSVAL(params,0,0);
3817 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3818 return(-1);
3821 #if 0
3822 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3823 /* XXXX um, i don't think this is right.
3824 it's also not in the cifs6.txt spec.
3826 case SMB_INFO_QUERY_EAS_FROM_LIST:
3827 if (total_data < 28)
3828 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3830 tvs.actime = make_unix_date2(pdata+8);
3831 tvs.modtime = make_unix_date2(pdata+12);
3832 size = IVAL(pdata,16);
3833 dosmode = IVAL(pdata,24);
3834 break;
3836 /* XXXX nor this. not in cifs6.txt, either. */
3837 case SMB_INFO_QUERY_ALL_EAS:
3838 if (total_data < 28)
3839 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3841 tvs.actime = make_unix_date2(pdata+8);
3842 tvs.modtime = make_unix_date2(pdata+12);
3843 size = IVAL(pdata,16);
3844 dosmode = IVAL(pdata,24);
3845 break;
3846 #endif
3848 case SMB_SET_FILE_BASIC_INFO:
3849 case SMB_FILE_BASIC_INFORMATION:
3851 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3852 time_t write_time;
3853 time_t changed_time;
3855 if (total_data < 36) {
3856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3859 /* Ignore create time at offset pdata. */
3861 /* access time */
3862 tvs.actime = interpret_long_date(pdata+8);
3864 write_time = interpret_long_date(pdata+16);
3865 changed_time = interpret_long_date(pdata+24);
3867 tvs.modtime = MIN(write_time, changed_time);
3869 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3870 tvs.modtime = write_time;
3872 /* Prefer a defined time to an undefined one. */
3873 if (null_mtime(tvs.modtime)) {
3874 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3877 /* attributes */
3878 dosmode = IVAL(pdata,32);
3879 break;
3882 case SMB_FILE_ALLOCATION_INFORMATION:
3883 case SMB_SET_FILE_ALLOCATION_INFO:
3885 int ret = -1;
3886 SMB_BIG_UINT allocation_size;
3888 if (total_data < 8) {
3889 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3892 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3893 #ifdef LARGE_SMB_OFF_T
3894 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3895 #else /* LARGE_SMB_OFF_T */
3896 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3897 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3898 #endif /* LARGE_SMB_OFF_T */
3899 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3900 fname, (double)allocation_size ));
3902 if (allocation_size) {
3903 allocation_size = smb_roundup(conn, allocation_size);
3906 if(allocation_size != get_file_size(sbuf)) {
3907 SMB_STRUCT_STAT new_sbuf;
3909 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3910 fname, (double)allocation_size ));
3912 if (fd == -1) {
3913 files_struct *new_fsp = NULL;
3915 if(global_oplock_break) {
3916 /* Queue this file modify as we are the process of an oplock break. */
3918 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3919 DEBUGADD(2,( "in oplock break state.\n"));
3921 push_oplock_pending_smb_message(inbuf, length);
3922 return -1;
3925 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3926 FILE_WRITE_DATA,
3927 FILE_SHARE_READ|FILE_SHARE_WRITE,
3928 FILE_OPEN,
3930 FILE_ATTRIBUTE_NORMAL,
3931 INTERNAL_OPEN_ONLY,
3932 NULL);
3934 if (new_fsp == NULL) {
3935 return(UNIXERROR(ERRDOS,ERRbadpath));
3937 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3938 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3939 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3940 new_fsp->fnum, strerror(errno)));
3941 ret = -1;
3943 close_file(new_fsp,True);
3944 } else {
3945 ret = vfs_allocate_file_space(fsp, allocation_size);
3946 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3947 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3948 fsp->fnum, strerror(errno)));
3949 ret = -1;
3952 if (ret == -1)
3953 return ERROR_NT(NT_STATUS_DISK_FULL);
3955 /* Allocate can truncate size... */
3956 size = get_file_size(new_sbuf);
3959 break;
3962 case SMB_FILE_END_OF_FILE_INFORMATION:
3963 case SMB_SET_FILE_END_OF_FILE_INFO:
3965 if (total_data < 8) {
3966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3969 size = IVAL(pdata,0);
3970 #ifdef LARGE_SMB_OFF_T
3971 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3972 #else /* LARGE_SMB_OFF_T */
3973 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3974 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3975 #endif /* LARGE_SMB_OFF_T */
3976 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3977 break;
3980 case SMB_FILE_DISPOSITION_INFORMATION:
3981 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3983 BOOL delete_on_close;
3985 if (total_data < 1) {
3986 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3989 delete_on_close = (CVAL(pdata,0) ? True : False);
3991 /* Just ignore this set on a path. */
3992 if (tran_call != TRANSACT2_SETFILEINFO)
3993 break;
3995 if (fsp == NULL)
3996 return(UNIXERROR(ERRDOS,ERRbadfid));
3998 status = can_set_delete_on_close(fsp, delete_on_close,
3999 dosmode);
4001 if (!NT_STATUS_IS_OK(status)) {
4002 return ERROR_NT(status);
4005 /* The set is across all open files on this dev/inode pair. */
4006 status =set_delete_on_close(fsp, delete_on_close);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 return ERROR_NT(status);
4011 SSVAL(params,0,0);
4012 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4013 return(-1);
4016 case SMB_FILE_POSITION_INFORMATION:
4018 SMB_BIG_UINT position_information;
4020 if (total_data < 8) {
4021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4024 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4025 #ifdef LARGE_SMB_OFF_T
4026 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4027 #else /* LARGE_SMB_OFF_T */
4028 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4029 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4030 #endif /* LARGE_SMB_OFF_T */
4031 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4032 fname, (double)position_information ));
4033 if (fsp) {
4034 fsp->fh->position_information = position_information;
4037 /* We're done. We only get position info in this call. */
4038 SSVAL(params,0,0);
4039 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4040 return(-1);
4043 /* From tridge Samba4 :
4044 * MODE_INFORMATION in setfileinfo (I have no
4045 * idea what "mode information" on a file is - it takes a value of 0,
4046 * 2, 4 or 6. What could it be?).
4049 case SMB_FILE_MODE_INFORMATION:
4051 uint32 mode;
4053 if (total_data < 4) {
4054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4056 mode = IVAL(pdata,0);
4057 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4058 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4061 /* We're done. We only get mode info in this call. */
4062 SSVAL(params,0,0);
4063 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4064 return(-1);
4068 * CIFS UNIX extensions.
4071 case SMB_SET_FILE_UNIX_BASIC:
4073 uint32 raw_unixmode;
4075 if (total_data < 100) {
4076 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4079 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4080 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4081 size=IVAL(pdata,0); /* first 8 Bytes are size */
4082 #ifdef LARGE_SMB_OFF_T
4083 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4084 #else /* LARGE_SMB_OFF_T */
4085 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4086 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4087 #endif /* LARGE_SMB_OFF_T */
4089 pdata+=24; /* ctime & st_blocks are not changed */
4090 tvs.actime = interpret_long_date(pdata); /* access_time */
4091 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4092 pdata+=16;
4093 set_owner = (uid_t)IVAL(pdata,0);
4094 pdata += 8;
4095 set_grp = (gid_t)IVAL(pdata,0);
4096 pdata += 8;
4097 raw_unixmode = IVAL(pdata,28);
4098 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4099 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4101 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4102 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4103 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4105 if (!VALID_STAT(sbuf)) {
4108 * The only valid use of this is to create character and block
4109 * devices, and named pipes. This is deprecated (IMHO) and
4110 * a new info level should be used for mknod. JRA.
4113 uint32 file_type = IVAL(pdata,0);
4114 #if defined(HAVE_MAKEDEV)
4115 uint32 dev_major = IVAL(pdata,4);
4116 uint32 dev_minor = IVAL(pdata,12);
4117 #endif
4119 uid_t myuid = geteuid();
4120 gid_t mygid = getegid();
4121 SMB_DEV_T dev = (SMB_DEV_T)0;
4123 if (tran_call == TRANSACT2_SETFILEINFO)
4124 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4126 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4127 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4130 #if defined(HAVE_MAKEDEV)
4131 dev = makedev(dev_major, dev_minor);
4132 #endif
4134 /* We can only create as the owner/group we are. */
4136 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4137 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4138 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4139 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4141 switch (file_type) {
4142 #if defined(S_IFIFO)
4143 case UNIX_TYPE_FIFO:
4144 unixmode |= S_IFIFO;
4145 break;
4146 #endif
4147 #if defined(S_IFSOCK)
4148 case UNIX_TYPE_SOCKET:
4149 unixmode |= S_IFSOCK;
4150 break;
4151 #endif
4152 #if defined(S_IFCHR)
4153 case UNIX_TYPE_CHARDEV:
4154 unixmode |= S_IFCHR;
4155 break;
4156 #endif
4157 #if defined(S_IFBLK)
4158 case UNIX_TYPE_BLKDEV:
4159 unixmode |= S_IFBLK;
4160 break;
4161 #endif
4162 default:
4163 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4166 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4167 0%o for file %s\n", (double)dev, unixmode, fname ));
4169 /* Ok - do the mknod. */
4170 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4171 return(UNIXERROR(ERRDOS,ERRnoaccess));
4173 inherit_access_acl(conn, fname, unixmode);
4175 SSVAL(params,0,0);
4176 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4177 return(-1);
4181 * Deal with the UNIX specific mode set.
4184 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4185 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4186 (unsigned int)unixmode, fname ));
4187 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4188 return(UNIXERROR(ERRDOS,ERRnoaccess));
4192 * Deal with the UNIX specific uid set.
4195 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4196 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4197 (unsigned int)set_owner, fname ));
4198 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4199 return(UNIXERROR(ERRDOS,ERRnoaccess));
4203 * Deal with the UNIX specific gid set.
4206 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4207 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4208 (unsigned int)set_owner, fname ));
4209 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4210 return(UNIXERROR(ERRDOS,ERRnoaccess));
4212 break;
4215 case SMB_SET_FILE_UNIX_LINK:
4217 pstring link_target;
4218 char *newname = fname;
4220 /* Set a symbolic link. */
4221 /* Don't allow this if follow links is false. */
4223 if (!lp_symlinks(SNUM(conn)))
4224 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4226 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4228 /* !widelinks forces the target path to be within the share. */
4229 /* This means we can interpret the target as a pathname. */
4230 if (!lp_widelinks(SNUM(conn))) {
4231 pstring rel_name;
4232 char *last_dirp = NULL;
4234 unix_format(link_target);
4235 if (*link_target == '/') {
4236 /* No absolute paths allowed. */
4237 return(UNIXERROR(ERRDOS,ERRnoaccess));
4239 pstrcpy(rel_name, newname);
4240 last_dirp = strrchr_m(rel_name, '/');
4241 if (last_dirp) {
4242 last_dirp[1] = '\0';
4243 } else {
4244 pstrcpy(rel_name, "./");
4246 pstrcat(rel_name, link_target);
4248 if (!check_name(rel_name, conn)) {
4249 return(UNIXERROR(ERRDOS,ERRnoaccess));
4253 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4254 fname, link_target ));
4256 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4257 return(UNIXERROR(ERRDOS,ERRnoaccess));
4258 SSVAL(params,0,0);
4259 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4260 return(-1);
4263 case SMB_SET_FILE_UNIX_HLINK:
4265 pstring oldname;
4266 char *newname = fname;
4268 /* Set a hard link. */
4269 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4270 if (!NT_STATUS_IS_OK(status)) {
4271 return ERROR_NT(status);
4274 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4275 fname, oldname));
4277 status = hardlink_internals(conn, oldname, newname);
4278 if (!NT_STATUS_IS_OK(status)) {
4279 return ERROR_NT(status);
4282 SSVAL(params,0,0);
4283 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4284 return(-1);
4287 case SMB_FILE_RENAME_INFORMATION:
4289 BOOL overwrite;
4290 uint32 root_fid;
4291 uint32 len;
4292 pstring newname;
4293 pstring base_name;
4294 char *p;
4296 if (total_data < 12) {
4297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4300 overwrite = (CVAL(pdata,0) ? True : False);
4301 root_fid = IVAL(pdata,4);
4302 len = IVAL(pdata,8);
4303 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4304 if (!NT_STATUS_IS_OK(status)) {
4305 return ERROR_NT(status);
4308 /* Check the new name has no '/' characters. */
4309 if (strchr_m(newname, '/'))
4310 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4312 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4314 /* Create the base directory. */
4315 pstrcpy(base_name, fname);
4316 p = strrchr_m(base_name, '/');
4317 if (p)
4318 *p = '\0';
4319 /* Append the new name. */
4320 pstrcat(base_name, "/");
4321 pstrcat(base_name, newname);
4323 if (fsp) {
4324 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4325 fsp->fnum, fsp->fsp_name, base_name ));
4326 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4327 } else {
4328 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4329 fname, newname ));
4330 status = rename_internals(conn, fname, base_name, 0, overwrite);
4332 if (!NT_STATUS_IS_OK(status)) {
4333 return ERROR_NT(status);
4335 process_pending_change_notify_queue((time_t)0);
4336 SSVAL(params,0,0);
4337 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4338 return(-1);
4341 #if defined(HAVE_POSIX_ACLS)
4342 case SMB_SET_POSIX_ACL:
4344 uint16 posix_acl_version;
4345 uint16 num_file_acls;
4346 uint16 num_def_acls;
4347 BOOL valid_file_acls = True;
4348 BOOL valid_def_acls = True;
4350 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4351 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4353 posix_acl_version = SVAL(pdata,0);
4354 num_file_acls = SVAL(pdata,2);
4355 num_def_acls = SVAL(pdata,4);
4357 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4358 valid_file_acls = False;
4359 num_file_acls = 0;
4362 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4363 valid_def_acls = False;
4364 num_def_acls = 0;
4367 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4368 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4371 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4372 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4373 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4376 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4377 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4378 return(UNIXERROR(ERRDOS,ERRnoaccess));
4381 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4382 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4383 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4384 return(UNIXERROR(ERRDOS,ERRnoaccess));
4387 SSVAL(params,0,0);
4388 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4389 return(-1);
4391 #endif
4393 default:
4394 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4397 /* get some defaults (no modifications) if any info is zero or -1. */
4398 if (null_mtime(tvs.actime)) {
4399 tvs.actime = sbuf.st_atime;
4402 if (null_mtime(tvs.modtime)) {
4403 tvs.modtime = sbuf.st_mtime;
4406 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4407 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4408 DEBUG(6,("size: %.0f ", (double)size));
4410 if (dosmode) {
4411 if (S_ISDIR(sbuf.st_mode))
4412 dosmode |= aDIR;
4413 else
4414 dosmode &= ~aDIR;
4417 DEBUG(6,("dosmode: %x\n" , dosmode));
4419 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4420 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4421 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4422 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4425 * Only do this test if we are not explicitly
4426 * changing the size of a file.
4428 if (!size)
4429 size = get_file_size(sbuf);
4433 * Try and set the times, size and mode of this file -
4434 * if they are different from the current values
4437 /* check the mode isn't different, before changing it */
4438 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4440 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4442 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4443 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4444 return(UNIXERROR(ERRDOS,ERRnoaccess));
4448 /* Now the size. */
4449 if (size != get_file_size(sbuf)) {
4451 int ret;
4453 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4454 fname, (double)size ));
4456 if (fd == -1) {
4457 files_struct *new_fsp = NULL;
4459 if(global_oplock_break) {
4460 /* Queue this file modify as we are the process of an oplock break. */
4462 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4463 DEBUGADD(2,( "in oplock break state.\n"));
4465 push_oplock_pending_smb_message(inbuf, length);
4466 return -1;
4469 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4470 FILE_WRITE_DATA,
4471 FILE_SHARE_READ|FILE_SHARE_WRITE,
4472 FILE_OPEN,
4474 FILE_ATTRIBUTE_NORMAL,
4475 INTERNAL_OPEN_ONLY,
4476 NULL);
4478 if (new_fsp == NULL) {
4479 return(UNIXERROR(ERRDOS,ERRbadpath));
4481 ret = vfs_set_filelen(new_fsp, size);
4482 close_file(new_fsp,True);
4483 } else {
4484 ret = vfs_set_filelen(fsp, size);
4487 if (ret == -1) {
4488 return (UNIXERROR(ERRHRD,ERRdiskfull));
4493 * Finally the times.
4495 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4496 if(fsp != NULL) {
4498 * This was a setfileinfo on an open file.
4499 * NT does this a lot. We also need to
4500 * set the time here, as it can be read by
4501 * FindFirst/FindNext and with the patch for bug #2045
4502 * in smbd/fileio.c it ensures that this timestamp is
4503 * kept sticky even after a write. We save the request
4504 * away and will set it on file close and after a write. JRA.
4507 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4508 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4509 fsp_set_pending_modtime(fsp, tvs.modtime);
4513 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4515 if(file_utime(conn, fname, &tvs)!=0) {
4516 return(UNIXERROR(ERRDOS,ERRnoaccess));
4520 SSVAL(params,0,0);
4521 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4523 return(-1);
4526 /****************************************************************************
4527 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4528 ****************************************************************************/
4530 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4531 char **pparams, int total_params, char **ppdata, int total_data,
4532 unsigned int max_data_bytes)
4534 char *params = *pparams;
4535 char *pdata = *ppdata;
4536 pstring directory;
4537 int ret = -1;
4538 SMB_STRUCT_STAT sbuf;
4539 BOOL bad_path = False;
4540 NTSTATUS status = NT_STATUS_OK;
4541 TALLOC_CTX *ctx = NULL;
4542 struct ea_list *ea_list = NULL;
4544 if (!CAN_WRITE(conn))
4545 return ERROR_DOS(ERRSRV,ERRaccess);
4547 if (total_params < 4) {
4548 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4551 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4552 if (!NT_STATUS_IS_OK(status)) {
4553 return ERROR_NT(status);
4556 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4558 unix_convert(directory,conn,0,&bad_path,&sbuf);
4559 if (bad_path) {
4560 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4563 /* Any data in this call is an EA list. */
4564 if (total_data && !lp_ea_support(SNUM(conn))) {
4565 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4568 if (total_data) {
4569 if (total_data < 10) {
4570 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4573 if (IVAL(pdata,0) > total_data) {
4574 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4575 IVAL(pdata,0), (unsigned int)total_data));
4576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4579 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4580 if (!ctx) {
4581 return ERROR_NT(NT_STATUS_NO_MEMORY);
4583 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4584 if (!ea_list) {
4585 talloc_destroy(ctx);
4586 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4590 if (check_name(directory,conn)) {
4591 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4594 if(ret < 0) {
4595 talloc_destroy(ctx);
4596 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4597 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4600 /* Try and set any given EA. */
4601 if (total_data) {
4602 status = set_ea(conn, NULL, directory, ea_list);
4603 talloc_destroy(ctx);
4604 if (!NT_STATUS_IS_OK(status)) {
4605 return ERROR_NT(status);
4609 /* Realloc the parameter and data sizes */
4610 params = SMB_REALLOC(*pparams,2);
4611 if(params == NULL) {
4612 return ERROR_NT(NT_STATUS_NO_MEMORY);
4614 *pparams = params;
4616 SSVAL(params,0,0);
4618 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4620 return(-1);
4623 /****************************************************************************
4624 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4625 We don't actually do this - we just send a null response.
4626 ****************************************************************************/
4628 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4629 char **pparams, int total_params, char **ppdata, int total_data,
4630 unsigned int max_data_bytes)
4632 static uint16 fnf_handle = 257;
4633 char *params = *pparams;
4634 uint16 info_level;
4636 if (total_params < 6) {
4637 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4640 info_level = SVAL(params,4);
4641 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4643 switch (info_level) {
4644 case 1:
4645 case 2:
4646 break;
4647 default:
4648 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4651 /* Realloc the parameter and data sizes */
4652 params = SMB_REALLOC(*pparams,6);
4653 if(params == NULL) {
4654 return ERROR_NT(NT_STATUS_NO_MEMORY);
4656 *pparams = params;
4658 SSVAL(params,0,fnf_handle);
4659 SSVAL(params,2,0); /* No changes */
4660 SSVAL(params,4,0); /* No EA errors */
4662 fnf_handle++;
4664 if(fnf_handle == 0)
4665 fnf_handle = 257;
4667 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4669 return(-1);
4672 /****************************************************************************
4673 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4674 changes). Currently this does nothing.
4675 ****************************************************************************/
4677 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4678 char **pparams, int total_params, char **ppdata, int total_data,
4679 unsigned int max_data_bytes)
4681 char *params = *pparams;
4683 DEBUG(3,("call_trans2findnotifynext\n"));
4685 /* Realloc the parameter and data sizes */
4686 params = SMB_REALLOC(*pparams,4);
4687 if(params == NULL) {
4688 return ERROR_NT(NT_STATUS_NO_MEMORY);
4690 *pparams = params;
4692 SSVAL(params,0,0); /* No changes */
4693 SSVAL(params,2,0); /* No EA errors */
4695 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4697 return(-1);
4700 /****************************************************************************
4701 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4702 ****************************************************************************/
4704 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4705 char **pparams, int total_params, char **ppdata, int total_data,
4706 unsigned int max_data_bytes)
4708 char *params = *pparams;
4709 pstring pathname;
4710 int reply_size = 0;
4711 int max_referral_level;
4713 DEBUG(10,("call_trans2getdfsreferral\n"));
4715 if (total_params < 2) {
4716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4719 max_referral_level = SVAL(params,0);
4721 if(!lp_host_msdfs())
4722 return ERROR_DOS(ERRDOS,ERRbadfunc);
4724 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4725 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4726 return UNIXERROR(ERRDOS,ERRbadfile);
4728 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4729 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4731 return(-1);
4734 #define LMCAT_SPL 0x53
4735 #define LMFUNC_GETJOBID 0x60
4737 /****************************************************************************
4738 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4739 ****************************************************************************/
4741 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4742 char **pparams, int total_params, char **ppdata, int total_data,
4743 unsigned int max_data_bytes)
4745 char *pdata = *ppdata;
4746 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4748 /* check for an invalid fid before proceeding */
4750 if (!fsp)
4751 return(ERROR_DOS(ERRDOS,ERRbadfid));
4753 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4754 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4755 pdata = SMB_REALLOC(*ppdata, 32);
4756 if(pdata == NULL) {
4757 return ERROR_NT(NT_STATUS_NO_MEMORY);
4759 *ppdata = pdata;
4761 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4762 CAN ACCEPT THIS IN UNICODE. JRA. */
4764 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4765 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4766 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4767 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4768 return(-1);
4769 } else {
4770 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4771 return ERROR_DOS(ERRSRV,ERRerror);
4775 /****************************************************************************
4776 Reply to a SMBfindclose (stop trans2 directory search).
4777 ****************************************************************************/
4779 int reply_findclose(connection_struct *conn,
4780 char *inbuf,char *outbuf,int length,int bufsize)
4782 int outsize = 0;
4783 int dptr_num=SVALS(inbuf,smb_vwv0);
4784 START_PROFILE(SMBfindclose);
4786 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4788 dptr_close(&dptr_num);
4790 outsize = set_message(outbuf,0,0,True);
4792 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4794 END_PROFILE(SMBfindclose);
4795 return(outsize);
4798 /****************************************************************************
4799 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4800 ****************************************************************************/
4802 int reply_findnclose(connection_struct *conn,
4803 char *inbuf,char *outbuf,int length,int bufsize)
4805 int outsize = 0;
4806 int dptr_num= -1;
4807 START_PROFILE(SMBfindnclose);
4809 dptr_num = SVAL(inbuf,smb_vwv0);
4811 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4813 /* We never give out valid handles for a
4814 findnotifyfirst - so any dptr_num is ok here.
4815 Just ignore it. */
4817 outsize = set_message(outbuf,0,0,True);
4819 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4821 END_PROFILE(SMBfindnclose);
4822 return(outsize);
4825 /****************************************************************************
4826 Reply to a SMBtranss2 - just ignore it!
4827 ****************************************************************************/
4829 int reply_transs2(connection_struct *conn,
4830 char *inbuf,char *outbuf,int length,int bufsize)
4832 START_PROFILE(SMBtranss2);
4833 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4834 END_PROFILE(SMBtranss2);
4835 return(-1);
4838 /****************************************************************************
4839 Reply to a SMBtrans2.
4840 ****************************************************************************/
4842 int reply_trans2(connection_struct *conn,
4843 char *inbuf,char *outbuf,int length,int bufsize)
4845 int outsize = 0;
4846 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4847 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4848 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4849 #if 0
4850 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4851 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4852 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4853 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4854 int32 timeout = IVALS(inbuf,smb_timeout);
4855 #endif
4856 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4857 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4858 char *params = NULL, *data = NULL;
4859 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4860 START_PROFILE(SMBtrans2);
4862 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4863 /* Queue this open message as we are the process of an
4864 * oplock break. */
4866 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4867 DEBUGADD(2,( "in oplock break state.\n"));
4869 push_oplock_pending_smb_message(inbuf, length);
4870 END_PROFILE(SMBtrans2);
4871 return -1;
4874 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4875 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4876 END_PROFILE(SMBtrans2);
4877 return ERROR_DOS(ERRSRV,ERRaccess);
4880 outsize = set_message(outbuf,0,0,True);
4882 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4883 is so as a sanity check */
4884 if (suwcnt != 1) {
4886 * Need to have rc=0 for ioctl to get job id for OS/2.
4887 * Network printing will fail if function is not successful.
4888 * Similar function in reply.c will be used if protocol
4889 * is LANMAN1.0 instead of LM1.2X002.
4890 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4891 * outbuf doesn't have to be set(only job id is used).
4893 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4894 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4895 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4896 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4897 } else {
4898 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4899 DEBUG(2,("Transaction is %d\n",tran_call));
4900 END_PROFILE(SMBtrans2);
4901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4905 /* Allocate the space for the maximum needed parameters and data */
4906 if (total_params > 0)
4907 params = (char *)SMB_MALLOC(total_params);
4908 if (total_data > 0)
4909 data = (char *)SMB_MALLOC(total_data);
4911 if ((total_params && !params) || (total_data && !data)) {
4912 DEBUG(2,("Out of memory in reply_trans2\n"));
4913 SAFE_FREE(params);
4914 SAFE_FREE(data);
4915 END_PROFILE(SMBtrans2);
4916 return ERROR_NT(NT_STATUS_NO_MEMORY);
4919 /* Copy the param and data bytes sent with this request into
4920 the params buffer */
4921 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4922 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4924 if (num_params > total_params || num_data > total_data)
4925 exit_server("invalid params in reply_trans2");
4927 if(params) {
4928 unsigned int psoff = SVAL(inbuf, smb_psoff);
4929 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4930 goto bad_param;
4931 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4932 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4933 goto bad_param;
4934 memcpy( params, smb_base(inbuf) + psoff, num_params);
4936 if(data) {
4937 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4938 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4939 goto bad_param;
4940 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4941 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4942 goto bad_param;
4943 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4946 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4948 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4949 /* We need to send an interim response then receive the rest
4950 of the parameter/data bytes */
4951 outsize = set_message(outbuf,0,0,True);
4952 srv_signing_trans_stop();
4953 show_msg(outbuf);
4954 if (!send_smb(smbd_server_fd(),outbuf))
4955 exit_server("reply_trans2: send_smb failed.");
4957 while (num_data_sofar < total_data ||
4958 num_params_sofar < total_params) {
4959 BOOL ret;
4960 unsigned int param_disp;
4961 unsigned int param_off;
4962 unsigned int data_disp;
4963 unsigned int data_off;
4965 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4967 /* We need to re-calcuate the new length after we've read the secondary packet. */
4968 length = smb_len(inbuf) + 4;
4971 * The sequence number for the trans reply is always
4972 * based on the last secondary received.
4975 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4977 if ((ret &&
4978 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4979 outsize = set_message(outbuf,0,0,True);
4980 if(ret)
4981 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4982 else
4983 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4984 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4985 goto bad_param;
4988 /* Revise total_params and total_data in case
4989 they have changed downwards */
4990 if (SVAL(inbuf, smb_tpscnt) < total_params)
4991 total_params = SVAL(inbuf, smb_tpscnt);
4992 if (SVAL(inbuf, smb_tdscnt) < total_data)
4993 total_data = SVAL(inbuf, smb_tdscnt);
4995 num_params = SVAL(inbuf,smb_spscnt);
4996 param_off = SVAL(inbuf, smb_spsoff);
4997 param_disp = SVAL(inbuf, smb_spsdisp);
4998 num_params_sofar += num_params;
5000 num_data = SVAL(inbuf, smb_sdscnt);
5001 data_off = SVAL(inbuf, smb_sdsoff);
5002 data_disp = SVAL(inbuf, smb_sdsdisp);
5003 num_data_sofar += num_data;
5005 if (num_params_sofar > total_params || num_data_sofar > total_data)
5006 goto bad_param;
5008 if (num_params) {
5009 if (param_disp + num_params > total_params)
5010 goto bad_param;
5011 if ((param_disp + num_params < param_disp) ||
5012 (param_disp + num_params < num_params))
5013 goto bad_param;
5014 if (param_disp > total_params)
5015 goto bad_param;
5016 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
5017 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
5018 goto bad_param;
5019 if (params + param_disp < params)
5020 goto bad_param;
5022 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
5024 if (num_data) {
5025 if (data_disp + num_data > total_data)
5026 goto bad_param;
5027 if ((data_disp + num_data < data_disp) ||
5028 (data_disp + num_data < num_data))
5029 goto bad_param;
5030 if (data_disp > total_data)
5031 goto bad_param;
5032 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
5033 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
5034 goto bad_param;
5035 if (data + data_disp < data)
5036 goto bad_param;
5038 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
5043 if (Protocol >= PROTOCOL_NT1) {
5044 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5047 /* Now we must call the relevant TRANS2 function */
5048 switch(tran_call) {
5049 case TRANSACT2_OPEN:
5050 START_PROFILE_NESTED(Trans2_open);
5051 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
5052 &params, total_params, &data, total_data, max_data_bytes);
5053 END_PROFILE_NESTED(Trans2_open);
5054 break;
5056 case TRANSACT2_FINDFIRST:
5057 START_PROFILE_NESTED(Trans2_findfirst);
5058 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
5059 &params, total_params, &data, total_data, max_data_bytes);
5060 END_PROFILE_NESTED(Trans2_findfirst);
5061 break;
5063 case TRANSACT2_FINDNEXT:
5064 START_PROFILE_NESTED(Trans2_findnext);
5065 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
5066 &params, total_params, &data, total_data, max_data_bytes);
5067 END_PROFILE_NESTED(Trans2_findnext);
5068 break;
5070 case TRANSACT2_QFSINFO:
5071 START_PROFILE_NESTED(Trans2_qfsinfo);
5072 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
5073 &params, total_params, &data, total_data, max_data_bytes);
5074 END_PROFILE_NESTED(Trans2_qfsinfo);
5075 break;
5077 case TRANSACT2_SETFSINFO:
5078 START_PROFILE_NESTED(Trans2_setfsinfo);
5079 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5080 &params, total_params, &data, total_data, max_data_bytes);
5081 END_PROFILE_NESTED(Trans2_setfsinfo);
5082 break;
5084 case TRANSACT2_QPATHINFO:
5085 case TRANSACT2_QFILEINFO:
5086 START_PROFILE_NESTED(Trans2_qpathinfo);
5087 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5088 &params, total_params, &data, total_data, max_data_bytes);
5089 END_PROFILE_NESTED(Trans2_qpathinfo);
5090 break;
5091 case TRANSACT2_SETPATHINFO:
5092 case TRANSACT2_SETFILEINFO:
5093 START_PROFILE_NESTED(Trans2_setpathinfo);
5094 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5095 &params, total_params, &data, total_data, max_data_bytes);
5096 END_PROFILE_NESTED(Trans2_setpathinfo);
5097 break;
5099 case TRANSACT2_FINDNOTIFYFIRST:
5100 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5101 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5102 &params, total_params, &data, total_data, max_data_bytes);
5103 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5104 break;
5106 case TRANSACT2_FINDNOTIFYNEXT:
5107 START_PROFILE_NESTED(Trans2_findnotifynext);
5108 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5109 &params, total_params, &data, total_data, max_data_bytes);
5110 END_PROFILE_NESTED(Trans2_findnotifynext);
5111 break;
5112 case TRANSACT2_MKDIR:
5113 START_PROFILE_NESTED(Trans2_mkdir);
5114 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5115 &params, total_params, &data, total_data, max_data_bytes);
5116 END_PROFILE_NESTED(Trans2_mkdir);
5117 break;
5119 case TRANSACT2_GET_DFS_REFERRAL:
5120 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5121 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5122 &params, total_params, &data, total_data, max_data_bytes);
5123 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5124 break;
5125 case TRANSACT2_IOCTL:
5126 START_PROFILE_NESTED(Trans2_ioctl);
5127 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5128 &params, total_params, &data, total_data, max_data_bytes);
5129 END_PROFILE_NESTED(Trans2_ioctl);
5130 break;
5131 default:
5132 /* Error in request */
5133 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5134 SAFE_FREE(params);
5135 SAFE_FREE(data);
5136 END_PROFILE(SMBtrans2);
5137 srv_signing_trans_stop();
5138 return ERROR_DOS(ERRSRV,ERRerror);
5141 /* As we do not know how many data packets will need to be
5142 returned here the various call_trans2xxxx calls
5143 must send their own. Thus a call_trans2xxx routine only
5144 returns a value other than -1 when it wants to send
5145 an error packet.
5148 srv_signing_trans_stop();
5150 SAFE_FREE(params);
5151 SAFE_FREE(data);
5152 END_PROFILE(SMBtrans2);
5153 return outsize; /* If a correct response was needed the
5154 call_trans2xxx calls have already sent
5155 it. If outsize != -1 then it is returning */
5157 bad_param:
5159 srv_signing_trans_stop();
5160 SAFE_FREE(params);
5161 SAFE_FREE(data);
5162 END_PROFILE(SMBtrans2);
5163 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);