r10929: tagging release
[Samba.git] / release-3-0-20b / source / smbd / trans2.c
blobdff4e4444d16a465e36ab13851f2d4afa9e5dcc7
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;
2351 /* access check */
2352 if (current_user.uid != 0) {
2353 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2354 lp_servicename(SNUM(conn)),conn->user));
2355 return ERROR_DOS(ERRDOS,ERRnoaccess);
2358 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2359 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2360 return ERROR_DOS(ERRSRV,ERRerror);
2363 data_len = 48;
2365 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2367 /* Unknown1 24 NULL bytes*/
2368 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2369 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2370 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2372 /* Default Soft Quota 8 bytes */
2373 SBIG_UINT(pdata,24,quotas.softlim);
2375 /* Default Hard Quota 8 bytes */
2376 SBIG_UINT(pdata,32,quotas.hardlim);
2378 /* Quota flag 2 bytes */
2379 SSVAL(pdata,40,quotas.qflags);
2381 /* Unknown3 6 NULL bytes */
2382 SSVAL(pdata,42,0);
2383 SIVAL(pdata,44,0);
2385 break;
2387 #endif /* HAVE_SYS_QUOTAS */
2388 case SMB_FS_OBJECTID_INFORMATION:
2389 data_len = 64;
2390 break;
2393 * Query the version and capabilities of the CIFS UNIX extensions
2394 * in use.
2397 case SMB_QUERY_CIFS_UNIX_INFO:
2398 if (!lp_unix_extensions())
2399 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2400 data_len = 12;
2401 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2402 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2403 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2404 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2405 break;
2407 case SMB_MAC_QUERY_FS_INFO:
2409 * Thursby MAC extension... ONLY on NTFS filesystems
2410 * once we do streams then we don't need this
2412 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2413 data_len = 88;
2414 SIVAL(pdata,84,0x100); /* Don't support mac... */
2415 break;
2417 /* drop through */
2418 default:
2419 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2423 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2425 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2427 return -1;
2430 /****************************************************************************
2431 Reply to a TRANS2_SETFSINFO (set filesystem info).
2432 ****************************************************************************/
2434 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2435 char **pparams, int total_params, char **ppdata, int total_data,
2436 unsigned int max_data_bytes)
2438 char *pdata = *ppdata;
2439 char *params = *pparams;
2440 uint16 info_level;
2441 int outsize;
2443 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2445 /* */
2446 if (total_params < 4) {
2447 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2448 total_params));
2449 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2452 info_level = SVAL(params,2);
2454 switch(info_level) {
2455 case SMB_SET_CIFS_UNIX_INFO:
2457 uint16 client_unix_major;
2458 uint16 client_unix_minor;
2459 uint32 client_unix_cap_low;
2460 uint32 client_unix_cap_high;
2462 if (!lp_unix_extensions()) {
2463 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2466 /* There should be 12 bytes of capabilities set. */
2467 if (total_data < 8) {
2468 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2470 client_unix_major = SVAL(pdata,0);
2471 client_unix_minor = SVAL(pdata,2);
2472 client_unix_cap_low = IVAL(pdata,4);
2473 client_unix_cap_high = IVAL(pdata,8);
2474 /* Just print these values for now. */
2475 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2476 cap_low = 0x%x, cap_high = 0x%x\n",
2477 (unsigned int)client_unix_major,
2478 (unsigned int)client_unix_minor,
2479 (unsigned int)client_unix_cap_low,
2480 (unsigned int)client_unix_cap_high ));
2482 /* Here is where we must switch to posix pathname processing... */
2483 lp_set_posix_pathnames();
2484 mangle_change_to_posix();
2485 break;
2487 case SMB_FS_QUOTA_INFORMATION:
2489 files_struct *fsp = NULL;
2490 SMB_NTQUOTA_STRUCT quotas;
2492 ZERO_STRUCT(quotas);
2494 /* access check */
2495 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2496 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2497 lp_servicename(SNUM(conn)),conn->user));
2498 return ERROR_DOS(ERRSRV,ERRaccess);
2501 /* note: normaly there're 48 bytes,
2502 * but we didn't use the last 6 bytes for now
2503 * --metze
2505 fsp = file_fsp(params,0);
2506 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2507 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2508 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2511 if (total_data < 42) {
2512 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2513 total_data));
2514 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2517 /* unknown_1 24 NULL bytes in pdata*/
2519 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2520 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2521 #ifdef LARGE_SMB_OFF_T
2522 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2523 #else /* LARGE_SMB_OFF_T */
2524 if ((IVAL(pdata,28) != 0)&&
2525 ((quotas.softlim != 0xFFFFFFFF)||
2526 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2527 /* more than 32 bits? */
2528 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2530 #endif /* LARGE_SMB_OFF_T */
2532 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2533 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2534 #ifdef LARGE_SMB_OFF_T
2535 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2536 #else /* LARGE_SMB_OFF_T */
2537 if ((IVAL(pdata,36) != 0)&&
2538 ((quotas.hardlim != 0xFFFFFFFF)||
2539 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2540 /* more than 32 bits? */
2541 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2543 #endif /* LARGE_SMB_OFF_T */
2545 /* quota_flags 2 bytes **/
2546 quotas.qflags = SVAL(pdata,40);
2548 /* unknown_2 6 NULL bytes follow*/
2550 /* now set the quotas */
2551 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2552 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2553 return ERROR_DOS(ERRSRV,ERRerror);
2556 break;
2558 default:
2559 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2560 info_level));
2561 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2562 break;
2566 * sending this reply works fine,
2567 * but I'm not sure it's the same
2568 * like windows do...
2569 * --metze
2571 outsize = set_message(outbuf,10,0,True);
2573 return outsize;
2576 /****************************************************************************
2577 Utility function to set bad path error.
2578 ****************************************************************************/
2580 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2582 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2583 err, (int)bad_path ));
2585 if(err == ENOENT) {
2586 if (bad_path) {
2587 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2588 } else {
2589 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2592 return UNIXERROR(def_class,def_code);
2595 #if defined(HAVE_POSIX_ACLS)
2596 /****************************************************************************
2597 Utility function to count the number of entries in a POSIX acl.
2598 ****************************************************************************/
2600 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2602 unsigned int ace_count = 0;
2603 int entry_id = SMB_ACL_FIRST_ENTRY;
2604 SMB_ACL_ENTRY_T entry;
2606 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2607 /* get_next... */
2608 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2609 entry_id = SMB_ACL_NEXT_ENTRY;
2611 ace_count++;
2613 return ace_count;
2616 /****************************************************************************
2617 Utility function to marshall a POSIX acl into wire format.
2618 ****************************************************************************/
2620 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2622 int entry_id = SMB_ACL_FIRST_ENTRY;
2623 SMB_ACL_ENTRY_T entry;
2625 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2626 SMB_ACL_TAG_T tagtype;
2627 SMB_ACL_PERMSET_T permset;
2628 unsigned char perms = 0;
2629 unsigned int own_grp;
2631 /* get_next... */
2632 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2633 entry_id = SMB_ACL_NEXT_ENTRY;
2636 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2637 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2638 return False;
2641 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2642 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2643 return False;
2646 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2647 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2648 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2650 SCVAL(pdata,1,perms);
2652 switch (tagtype) {
2653 case SMB_ACL_USER_OBJ:
2654 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2655 own_grp = (unsigned int)pst->st_uid;
2656 SIVAL(pdata,2,own_grp);
2657 SIVAL(pdata,6,0);
2658 break;
2659 case SMB_ACL_USER:
2661 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2662 if (!puid) {
2663 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2665 own_grp = (unsigned int)*puid;
2666 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2667 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2668 SIVAL(pdata,2,own_grp);
2669 SIVAL(pdata,6,0);
2670 break;
2672 case SMB_ACL_GROUP_OBJ:
2673 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2674 own_grp = (unsigned int)pst->st_gid;
2675 SIVAL(pdata,2,own_grp);
2676 SIVAL(pdata,6,0);
2677 break;
2678 case SMB_ACL_GROUP:
2680 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2681 if (!pgid) {
2682 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2684 own_grp = (unsigned int)*pgid;
2685 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2686 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2687 SIVAL(pdata,2,own_grp);
2688 SIVAL(pdata,6,0);
2689 break;
2691 case SMB_ACL_MASK:
2692 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2693 SIVAL(pdata,2,0xFFFFFFFF);
2694 SIVAL(pdata,6,0xFFFFFFFF);
2695 break;
2696 case SMB_ACL_OTHER:
2697 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2698 SIVAL(pdata,2,0xFFFFFFFF);
2699 SIVAL(pdata,6,0xFFFFFFFF);
2700 break;
2701 default:
2702 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2703 return False;
2705 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2708 return True;
2710 #endif
2712 /****************************************************************************
2713 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2714 file name or file id).
2715 ****************************************************************************/
2717 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2718 unsigned int tran_call,
2719 char **pparams, int total_params, char **ppdata, int total_data,
2720 unsigned int max_data_bytes)
2722 char *params = *pparams;
2723 char *pdata = *ppdata;
2724 uint16 info_level;
2725 int mode=0;
2726 int nlink;
2727 SMB_OFF_T file_size=0;
2728 SMB_BIG_UINT allocation_size=0;
2729 unsigned int data_size = 0;
2730 unsigned int param_size = 2;
2731 SMB_STRUCT_STAT sbuf;
2732 pstring fname, dos_fname;
2733 char *fullpathname;
2734 char *base_name;
2735 char *p;
2736 SMB_OFF_T pos = 0;
2737 BOOL bad_path = False;
2738 BOOL delete_pending = False;
2739 int len;
2740 time_t c_time;
2741 files_struct *fsp = NULL;
2742 TALLOC_CTX *ea_ctx = NULL;
2743 struct ea_list *ea_list = NULL;
2744 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2746 if (!params)
2747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2749 ZERO_STRUCT(sbuf);
2751 if (tran_call == TRANSACT2_QFILEINFO) {
2752 if (total_params < 4) {
2753 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2756 fsp = file_fsp(params,0);
2757 info_level = SVAL(params,2);
2759 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2761 if(fsp && (fsp->fake_file_handle)) {
2763 * This is actually for the QUOTA_FAKE_FILE --metze
2766 pstrcpy(fname, fsp->fsp_name);
2767 /* We know this name is ok, it's already passed the checks. */
2769 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2771 * This is actually a QFILEINFO on a directory
2772 * handle (returned from an NT SMB). NT5.0 seems
2773 * to do this call. JRA.
2775 /* We know this name is ok, it's already passed the checks. */
2776 pstrcpy(fname, fsp->fsp_name);
2778 if (INFO_LEVEL_IS_UNIX(info_level)) {
2779 /* Always do lstat for UNIX calls. */
2780 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2781 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2782 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2784 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2785 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2786 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2789 delete_pending =
2790 get_delete_on_close_flag(sbuf.st_dev,
2791 sbuf.st_ino);
2792 } else {
2794 * Original code - this is an open file.
2796 CHECK_FSP(fsp,conn);
2798 pstrcpy(fname, fsp->fsp_name);
2799 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2800 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2801 return(UNIXERROR(ERRDOS,ERRbadfid));
2803 pos = fsp->fh->position_information;
2804 delete_pending =
2805 get_delete_on_close_flag(sbuf.st_dev,
2806 sbuf.st_ino);
2807 access_mask = fsp->access_mask;
2809 } else {
2810 NTSTATUS status = NT_STATUS_OK;
2812 /* qpathinfo */
2813 if (total_params < 6) {
2814 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2817 info_level = SVAL(params,0);
2819 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2821 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2822 if (!NT_STATUS_IS_OK(status)) {
2823 return ERROR_NT(status);
2826 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2828 unix_convert(fname,conn,0,&bad_path,&sbuf);
2829 if (bad_path) {
2830 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2832 if (!check_name(fname,conn)) {
2833 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2834 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2837 if (INFO_LEVEL_IS_UNIX(info_level)) {
2838 /* Always do lstat for UNIX calls. */
2839 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2840 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2841 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2843 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2844 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2845 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2848 delete_pending = get_delete_on_close_flag(sbuf.st_dev,
2849 sbuf.st_ino);
2850 if (delete_pending) {
2851 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2855 nlink = sbuf.st_nlink;
2857 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2858 /* NTFS does not seem to count ".." */
2859 nlink -= 1;
2862 if ((nlink > 0) && delete_pending) {
2863 nlink -= 1;
2866 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2867 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2869 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2870 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2872 p = strrchr_m(fname,'/');
2873 if (!p)
2874 base_name = fname;
2875 else
2876 base_name = p+1;
2878 mode = dos_mode(conn,fname,&sbuf);
2879 if (!mode)
2880 mode = FILE_ATTRIBUTE_NORMAL;
2882 fullpathname = fname;
2883 file_size = get_file_size(sbuf);
2884 if (mode & aDIR) {
2885 /* This is necessary, as otherwise the desktop.ini file in
2886 * this folder is ignored */
2887 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2888 file_size = 0;
2891 /* Pull any EA list from the data portion. */
2892 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2893 uint32 ea_size;
2895 if (total_data < 4) {
2896 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2898 ea_size = IVAL(pdata,0);
2900 if (total_data > 0 && ea_size != total_data) {
2901 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2902 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2903 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2906 if (!lp_ea_support(SNUM(conn))) {
2907 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2910 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2911 return ERROR_NT(NT_STATUS_NO_MEMORY);
2914 /* Pull out the list of names. */
2915 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2916 if (!ea_list) {
2917 talloc_destroy(ea_ctx);
2918 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2922 params = SMB_REALLOC(*pparams,2);
2923 if (params == NULL) {
2924 talloc_destroy(ea_ctx);
2925 return ERROR_NT(NT_STATUS_NO_MEMORY);
2927 *pparams = params;
2928 SSVAL(params,0,0);
2929 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2930 pdata = SMB_REALLOC(*ppdata, data_size);
2931 if ( pdata == NULL ) {
2932 talloc_destroy(ea_ctx);
2933 return ERROR_NT(NT_STATUS_NO_MEMORY);
2935 *ppdata = pdata;
2937 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2939 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2941 if (fsp) {
2942 if (fsp->pending_modtime) {
2943 /* the pending modtime overrides the current modtime */
2944 sbuf.st_mtime = fsp->pending_modtime;
2946 } else {
2947 /* Do we have this path open ? */
2948 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2949 if (fsp1 && fsp1->pending_modtime) {
2950 /* the pending modtime overrides the current modtime */
2951 sbuf.st_mtime = fsp1->pending_modtime;
2953 if (fsp1 && fsp1->initial_allocation_size) {
2954 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2958 if (lp_dos_filetime_resolution(SNUM(conn))) {
2959 c_time &= ~1;
2960 sbuf.st_atime &= ~1;
2961 sbuf.st_ctime &= ~1;
2962 sbuf.st_mtime &= ~1;
2965 /* NT expects the name to be in an exact form of the *full*
2966 filename. See the trans2 torture test */
2967 if (strequal(base_name,".")) {
2968 pstrcpy(dos_fname, "\\");
2969 } else {
2970 pstr_sprintf(dos_fname, "\\%s", fname);
2971 string_replace(dos_fname, '/', '\\');
2974 switch (info_level) {
2975 case SMB_INFO_STANDARD:
2976 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2977 data_size = 22;
2978 put_dos_date2(pdata,l1_fdateCreation,c_time);
2979 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2980 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2981 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2982 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2983 SSVAL(pdata,l1_attrFile,mode);
2984 break;
2986 case SMB_INFO_QUERY_EA_SIZE:
2988 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2989 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2990 data_size = 26;
2991 put_dos_date2(pdata,0,c_time);
2992 put_dos_date2(pdata,4,sbuf.st_atime);
2993 put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
2994 SIVAL(pdata,12,(uint32)file_size);
2995 SIVAL(pdata,16,(uint32)allocation_size);
2996 SSVAL(pdata,20,mode);
2997 SIVAL(pdata,22,ea_size);
2998 break;
3001 case SMB_INFO_IS_NAME_VALID:
3002 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3003 if (tran_call == TRANSACT2_QFILEINFO) {
3004 /* os/2 needs this ? really ?*/
3005 return ERROR_DOS(ERRDOS,ERRbadfunc);
3007 data_size = 0;
3008 param_size = 0;
3009 break;
3011 case SMB_INFO_QUERY_EAS_FROM_LIST:
3013 size_t total_ea_len = 0;
3014 struct ea_list *ea_file_list = NULL;
3016 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3018 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3019 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3021 if (!ea_list || (total_ea_len > data_size)) {
3022 talloc_destroy(ea_ctx);
3023 data_size = 4;
3024 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3025 break;
3028 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3029 talloc_destroy(ea_ctx);
3030 break;
3033 case SMB_INFO_QUERY_ALL_EAS:
3035 /* We have data_size bytes to put EA's into. */
3036 size_t total_ea_len = 0;
3038 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3040 ea_ctx = talloc_init("ea_ctx");
3041 if (!ea_ctx) {
3042 return ERROR_NT(NT_STATUS_NO_MEMORY);
3045 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3046 if (!ea_list || (total_ea_len > data_size)) {
3047 talloc_destroy(ea_ctx);
3048 data_size = 4;
3049 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3050 break;
3053 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3054 talloc_destroy(ea_ctx);
3055 break;
3058 case SMB_FILE_BASIC_INFORMATION:
3059 case SMB_QUERY_FILE_BASIC_INFO:
3061 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3062 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3063 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3064 } else {
3065 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3066 data_size = 40;
3067 SIVAL(pdata,36,0);
3069 put_long_date(pdata,c_time);
3070 put_long_date(pdata+8,sbuf.st_atime);
3071 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3072 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3073 SIVAL(pdata,32,mode);
3075 DEBUG(5,("SMB_QFBI - "));
3077 time_t create_time = c_time;
3078 DEBUG(5,("create: %s ", ctime(&create_time)));
3080 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3081 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3082 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3083 DEBUG(5,("mode: %x\n", mode));
3084 break;
3086 case SMB_FILE_STANDARD_INFORMATION:
3087 case SMB_QUERY_FILE_STANDARD_INFO:
3089 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3090 data_size = 24;
3091 SOFF_T(pdata,0,allocation_size);
3092 SOFF_T(pdata,8,file_size);
3093 SIVAL(pdata,16,nlink);
3094 SCVAL(pdata,20,delete_pending?1:0);
3095 SCVAL(pdata,21,(mode&aDIR)?1:0);
3096 SSVAL(pdata,22,0); /* Padding. */
3097 break;
3099 case SMB_FILE_EA_INFORMATION:
3100 case SMB_QUERY_FILE_EA_INFO:
3102 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3103 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3104 data_size = 4;
3105 SIVAL(pdata,0,ea_size);
3106 break;
3109 /* Get the 8.3 name - used if NT SMB was negotiated. */
3110 case SMB_QUERY_FILE_ALT_NAME_INFO:
3111 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3113 pstring short_name;
3115 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3116 pstrcpy(short_name,base_name);
3117 /* Mangle if not already 8.3 */
3118 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3119 mangle_map(short_name,True,True,SNUM(conn));
3121 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3122 data_size = 4 + len;
3123 SIVAL(pdata,0,len);
3124 break;
3127 case SMB_QUERY_FILE_NAME_INFO:
3129 this must be *exactly* right for ACLs on mapped drives to work
3131 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3132 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3133 data_size = 4 + len;
3134 SIVAL(pdata,0,len);
3135 break;
3137 case SMB_FILE_ALLOCATION_INFORMATION:
3138 case SMB_QUERY_FILE_ALLOCATION_INFO:
3139 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3140 data_size = 8;
3141 SOFF_T(pdata,0,allocation_size);
3142 break;
3144 case SMB_FILE_END_OF_FILE_INFORMATION:
3145 case SMB_QUERY_FILE_END_OF_FILEINFO:
3146 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3147 data_size = 8;
3148 SOFF_T(pdata,0,file_size);
3149 break;
3151 case SMB_QUERY_FILE_ALL_INFO:
3152 case SMB_FILE_ALL_INFORMATION:
3154 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3155 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3156 put_long_date(pdata,c_time);
3157 put_long_date(pdata+8,sbuf.st_atime);
3158 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3159 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3160 SIVAL(pdata,32,mode);
3161 SIVAL(pdata,36,0); /* padding. */
3162 pdata += 40;
3163 SOFF_T(pdata,0,allocation_size);
3164 SOFF_T(pdata,8,file_size);
3165 SIVAL(pdata,16,nlink);
3166 SCVAL(pdata,20,delete_pending);
3167 SCVAL(pdata,21,(mode&aDIR)?1:0);
3168 SSVAL(pdata,22,0);
3169 pdata += 24;
3170 SIVAL(pdata,0,ea_size);
3171 pdata += 4; /* EA info */
3172 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3173 SIVAL(pdata,0,len);
3174 pdata += 4 + len;
3175 data_size = PTR_DIFF(pdata,(*ppdata));
3176 break;
3178 case SMB_FILE_INTERNAL_INFORMATION:
3179 /* This should be an index number - looks like
3180 dev/ino to me :-)
3182 I think this causes us to fail the IFSKIT
3183 BasicFileInformationTest. -tpot */
3185 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3186 SIVAL(pdata,0,sbuf.st_dev);
3187 SIVAL(pdata,4,sbuf.st_ino);
3188 data_size = 8;
3189 break;
3191 case SMB_FILE_ACCESS_INFORMATION:
3192 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3193 SIVAL(pdata,0,access_mask);
3194 data_size = 4;
3195 break;
3197 case SMB_FILE_NAME_INFORMATION:
3198 /* Pathname with leading '\'. */
3200 size_t byte_len;
3201 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3202 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3203 SIVAL(pdata,0,byte_len);
3204 data_size = 4 + byte_len;
3205 break;
3208 case SMB_FILE_DISPOSITION_INFORMATION:
3209 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3210 data_size = 1;
3211 SCVAL(pdata,0,delete_pending);
3212 break;
3214 case SMB_FILE_POSITION_INFORMATION:
3215 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3216 data_size = 8;
3217 SOFF_T(pdata,0,pos);
3218 break;
3220 case SMB_FILE_MODE_INFORMATION:
3221 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3222 SIVAL(pdata,0,mode);
3223 data_size = 4;
3224 break;
3226 case SMB_FILE_ALIGNMENT_INFORMATION:
3227 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3228 SIVAL(pdata,0,0); /* No alignment needed. */
3229 data_size = 4;
3230 break;
3232 #if 0
3234 * NT4 server just returns "invalid query" to this - if we try to answer
3235 * it then NTws gets a BSOD! (tridge).
3236 * W2K seems to want this. JRA.
3238 case SMB_QUERY_FILE_STREAM_INFO:
3239 #endif
3240 case SMB_FILE_STREAM_INFORMATION:
3241 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3242 if (mode & aDIR) {
3243 data_size = 0;
3244 } else {
3245 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3246 SIVAL(pdata,0,0); /* ??? */
3247 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3248 SOFF_T(pdata,8,file_size);
3249 SIVAL(pdata,16,allocation_size);
3250 SIVAL(pdata,20,0); /* ??? */
3251 data_size = 24 + byte_len;
3253 break;
3255 case SMB_QUERY_COMPRESSION_INFO:
3256 case SMB_FILE_COMPRESSION_INFORMATION:
3257 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3258 SOFF_T(pdata,0,file_size);
3259 SIVAL(pdata,8,0); /* ??? */
3260 SIVAL(pdata,12,0); /* ??? */
3261 data_size = 16;
3262 break;
3264 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3265 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3266 put_long_date(pdata,c_time);
3267 put_long_date(pdata+8,sbuf.st_atime);
3268 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3269 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3270 SIVAL(pdata,32,allocation_size);
3271 SOFF_T(pdata,40,file_size);
3272 SIVAL(pdata,48,mode);
3273 SIVAL(pdata,52,0); /* ??? */
3274 data_size = 56;
3275 break;
3277 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3278 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3279 SIVAL(pdata,0,mode);
3280 SIVAL(pdata,4,0);
3281 data_size = 8;
3282 break;
3285 * CIFS UNIX Extensions.
3288 case SMB_QUERY_FILE_UNIX_BASIC:
3290 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3291 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3293 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3294 pdata += 8;
3296 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3297 pdata += 8;
3299 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3300 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3301 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3302 pdata += 24;
3304 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3305 SIVAL(pdata,4,0);
3306 pdata += 8;
3308 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3309 SIVAL(pdata,4,0);
3310 pdata += 8;
3312 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3313 pdata += 4;
3315 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3316 SIVAL(pdata,4,0);
3317 pdata += 8;
3319 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3320 SIVAL(pdata,4,0);
3321 pdata += 8;
3323 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3324 pdata += 8;
3326 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3327 SIVAL(pdata,4,0);
3328 pdata += 8;
3330 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3331 SIVAL(pdata,4,0);
3332 pdata += 8+1;
3333 data_size = PTR_DIFF(pdata,(*ppdata));
3336 int i;
3337 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3339 for (i=0; i<100; i++)
3340 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3341 DEBUG(4,("\n"));
3344 break;
3346 case SMB_QUERY_FILE_UNIX_LINK:
3348 pstring buffer;
3350 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3351 #ifdef S_ISLNK
3352 if(!S_ISLNK(sbuf.st_mode))
3353 return(UNIXERROR(ERRSRV,ERRbadlink));
3354 #else
3355 return(UNIXERROR(ERRDOS,ERRbadlink));
3356 #endif
3357 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3358 if (len == -1)
3359 return(UNIXERROR(ERRDOS,ERRnoaccess));
3360 buffer[len] = 0;
3361 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3362 pdata += len;
3363 data_size = PTR_DIFF(pdata,(*ppdata));
3365 break;
3368 #if defined(HAVE_POSIX_ACLS)
3369 case SMB_QUERY_POSIX_ACL:
3371 SMB_ACL_T file_acl = NULL;
3372 SMB_ACL_T def_acl = NULL;
3373 uint16 num_file_acls = 0;
3374 uint16 num_def_acls = 0;
3376 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3377 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3378 } else {
3379 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3382 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3383 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3384 fname ));
3385 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3388 if (S_ISDIR(sbuf.st_mode)) {
3389 if (fsp && fsp->is_directory) {
3390 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3391 } else {
3392 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3394 def_acl = free_empty_sys_acl(conn, def_acl);
3397 num_file_acls = count_acl_entries(conn, file_acl);
3398 num_def_acls = count_acl_entries(conn, def_acl);
3400 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3401 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3402 data_size,
3403 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3404 SMB_POSIX_ACL_HEADER_SIZE) ));
3405 if (file_acl) {
3406 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3408 if (def_acl) {
3409 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3411 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3414 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3415 SSVAL(pdata,2,num_file_acls);
3416 SSVAL(pdata,4,num_def_acls);
3417 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3418 if (file_acl) {
3419 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3421 if (def_acl) {
3422 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3424 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3426 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3427 if (file_acl) {
3428 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3430 if (def_acl) {
3431 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3433 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3436 if (file_acl) {
3437 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3439 if (def_acl) {
3440 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3442 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3443 break;
3445 #endif
3447 default:
3448 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3451 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3453 return(-1);
3456 /****************************************************************************
3457 Deal with the internal needs of setting the delete on close flag. Note that
3458 as the tdb locking is recursive, it is safe to call this from within
3459 open_file_shared. JRA.
3460 ****************************************************************************/
3462 NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
3463 uint32 dosmode)
3465 if (!delete_on_close) {
3466 return NT_STATUS_OK;
3470 * Only allow delete on close for writable files.
3473 if ((dosmode & aRONLY) &&
3474 !lp_delete_readonly(SNUM(fsp->conn))) {
3475 DEBUG(10,("can_set_delete_on_close: file %s delete on close "
3476 "flag set but file attribute is readonly.\n",
3477 fsp->fsp_name ));
3478 return NT_STATUS_CANNOT_DELETE;
3482 * Only allow delete on close for writable shares.
3485 if (!CAN_WRITE(fsp->conn)) {
3486 DEBUG(10,("can_set_delete_on_close: file %s delete on "
3487 "close flag set but write access denied on share.\n",
3488 fsp->fsp_name ));
3489 return NT_STATUS_ACCESS_DENIED;
3493 * Only allow delete on close for files/directories opened with delete
3494 * intent.
3497 if (!(fsp->access_mask & DELETE_ACCESS)) {
3498 DEBUG(10,("can_set_delete_on_close: file %s delete on "
3499 "close flag set but delete access denied.\n",
3500 fsp->fsp_name ));
3501 return NT_STATUS_ACCESS_DENIED;
3504 return NT_STATUS_OK;
3507 /****************************************************************************
3508 Sets the delete on close flag over all share modes on this file.
3509 Modify the share mode entry for all files open
3510 on this device and inode to tell other smbds we have
3511 changed the delete on close flag. This will be noticed
3512 in the close code, the last closer will delete the file
3513 if flag is set.
3514 ****************************************************************************/
3516 NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
3518 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
3519 "fnum = %d, file %s\n",
3520 delete_on_close ? "Adding" : "Removing", fsp->fnum,
3521 fsp->fsp_name ));
3523 if (fsp->is_directory || fsp->is_stat)
3524 return NT_STATUS_OK;
3526 if (lock_share_entry_fsp(fsp) == False)
3527 return NT_STATUS_ACCESS_DENIED;
3529 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3530 DEBUG(0,("set_delete_on_close: failed to change delete "
3531 "on close flag for file %s\n",
3532 fsp->fsp_name ));
3533 unlock_share_entry_fsp(fsp);
3534 return NT_STATUS_ACCESS_DENIED;
3537 unlock_share_entry_fsp(fsp);
3538 return NT_STATUS_OK;
3541 /****************************************************************************
3542 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3543 code.
3544 ****************************************************************************/
3546 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3548 BOOL bad_path_oldname = False;
3549 BOOL bad_path_newname = False;
3550 SMB_STRUCT_STAT sbuf1, sbuf2;
3551 pstring last_component_oldname;
3552 pstring last_component_newname;
3553 NTSTATUS status = NT_STATUS_OK;
3555 ZERO_STRUCT(sbuf1);
3556 ZERO_STRUCT(sbuf2);
3558 /* No wildcards. */
3559 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3560 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3563 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3564 if (bad_path_oldname) {
3565 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3568 /* Quick check for "." and ".." */
3569 if (last_component_oldname[0] == '.') {
3570 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3571 return NT_STATUS_OBJECT_NAME_INVALID;
3575 /* source must already exist. */
3576 if (!VALID_STAT(sbuf1)) {
3577 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3580 if (!check_name(oldname,conn)) {
3581 return NT_STATUS_ACCESS_DENIED;
3584 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3585 if (bad_path_newname) {
3586 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3589 /* Quick check for "." and ".." */
3590 if (last_component_newname[0] == '.') {
3591 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3592 return NT_STATUS_OBJECT_NAME_INVALID;
3596 /* Disallow if newname already exists. */
3597 if (VALID_STAT(sbuf2)) {
3598 return NT_STATUS_OBJECT_NAME_COLLISION;
3601 if (!check_name(newname,conn)) {
3602 return NT_STATUS_ACCESS_DENIED;
3605 /* No links from a directory. */
3606 if (S_ISDIR(sbuf1.st_mode)) {
3607 return NT_STATUS_FILE_IS_A_DIRECTORY;
3610 /* Ensure this is within the share. */
3611 if (!reduce_name(conn, oldname) != 0)
3612 return NT_STATUS_ACCESS_DENIED;
3614 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3616 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3617 status = map_nt_error_from_unix(errno);
3618 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3619 nt_errstr(status), newname, oldname));
3622 return status;
3625 /****************************************************************************
3626 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3627 ****************************************************************************/
3629 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3630 unsigned int tran_call,
3631 char **pparams, int total_params, char **ppdata, int total_data,
3632 unsigned int max_data_bytes)
3634 char *params = *pparams;
3635 char *pdata = *ppdata;
3636 uint16 info_level;
3637 int dosmode=0;
3638 SMB_OFF_T size=0;
3639 struct utimbuf tvs;
3640 SMB_STRUCT_STAT sbuf;
3641 pstring fname;
3642 int fd = -1;
3643 BOOL bad_path = False;
3644 files_struct *fsp = NULL;
3645 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3646 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3647 mode_t unixmode = 0;
3648 NTSTATUS status = NT_STATUS_OK;
3650 if (!params)
3651 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3653 ZERO_STRUCT(sbuf);
3654 ZERO_STRUCT(tvs);
3656 if (tran_call == TRANSACT2_SETFILEINFO) {
3657 if (total_params < 4) {
3658 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3661 fsp = file_fsp(params,0);
3662 info_level = SVAL(params,2);
3664 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3666 * This is actually a SETFILEINFO on a directory
3667 * handle (returned from an NT SMB). NT5.0 seems
3668 * to do this call. JRA.
3670 pstrcpy(fname, fsp->fsp_name);
3671 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3672 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3673 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3675 } else if (fsp && fsp->print_file) {
3677 * Doing a DELETE_ON_CLOSE should cancel a print job.
3679 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3680 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3682 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3684 SSVAL(params,0,0);
3685 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3686 return(-1);
3687 } else
3688 return (UNIXERROR(ERRDOS,ERRbadpath));
3689 } else {
3691 * Original code - this is an open file.
3693 CHECK_FSP(fsp,conn);
3695 pstrcpy(fname, fsp->fsp_name);
3696 fd = fsp->fh->fd;
3698 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3699 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3700 return(UNIXERROR(ERRDOS,ERRbadfid));
3703 } else {
3704 /* set path info */
3705 if (total_params < 6) {
3706 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3709 info_level = SVAL(params,0);
3710 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3711 if (!NT_STATUS_IS_OK(status)) {
3712 return ERROR_NT(status);
3714 unix_convert(fname,conn,0,&bad_path,&sbuf);
3715 if (bad_path) {
3716 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3720 * For CIFS UNIX extensions the target name may not exist.
3723 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3724 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3725 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3728 if(!check_name(fname, conn)) {
3729 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3734 if (!CAN_WRITE(conn))
3735 return ERROR_DOS(ERRSRV,ERRaccess);
3737 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3738 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3740 if (VALID_STAT(sbuf))
3741 unixmode = sbuf.st_mode;
3743 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3744 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3746 /* Realloc the parameter size */
3747 params = SMB_REALLOC(*pparams,2);
3748 if(params == NULL) {
3749 return ERROR_NT(NT_STATUS_NO_MEMORY);
3751 *pparams = params;
3753 SSVAL(params,0,0);
3755 if (fsp && fsp->pending_modtime) {
3756 /* the pending modtime overrides the current modtime */
3757 sbuf.st_mtime = fsp->pending_modtime;
3760 size = get_file_size(sbuf);
3761 tvs.modtime = sbuf.st_mtime;
3762 tvs.actime = sbuf.st_atime;
3763 dosmode = dos_mode(conn,fname,&sbuf);
3764 unixmode = sbuf.st_mode;
3766 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3767 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3769 switch (info_level) {
3770 case SMB_INFO_STANDARD:
3772 if (total_data < 12) {
3773 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3776 /* access time */
3777 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3778 /* write time */
3779 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3780 break;
3783 case SMB_INFO_SET_EA:
3785 struct ea_list *ea_list = NULL;
3786 TALLOC_CTX *ctx = NULL;
3788 if (total_data < 10) {
3789 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3792 if (IVAL(pdata,0) > total_data) {
3793 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3794 IVAL(pdata,0), (unsigned int)total_data));
3795 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3798 ctx = talloc_init("SMB_INFO_SET_EA");
3799 if (!ctx) {
3800 return ERROR_NT(NT_STATUS_NO_MEMORY);
3802 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3803 if (!ea_list) {
3804 talloc_destroy(ctx);
3805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3807 status = set_ea(conn, fsp, fname, ea_list);
3808 talloc_destroy(ctx);
3810 if (!NT_STATUS_IS_OK(status)) {
3811 return ERROR_NT(status);
3814 /* We're done. We only get EA info in this call. */
3815 SSVAL(params,0,0);
3816 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3817 return(-1);
3820 #if 0
3821 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3822 /* XXXX um, i don't think this is right.
3823 it's also not in the cifs6.txt spec.
3825 case SMB_INFO_QUERY_EAS_FROM_LIST:
3826 if (total_data < 28)
3827 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3829 tvs.actime = make_unix_date2(pdata+8);
3830 tvs.modtime = make_unix_date2(pdata+12);
3831 size = IVAL(pdata,16);
3832 dosmode = IVAL(pdata,24);
3833 break;
3835 /* XXXX nor this. not in cifs6.txt, either. */
3836 case SMB_INFO_QUERY_ALL_EAS:
3837 if (total_data < 28)
3838 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3840 tvs.actime = make_unix_date2(pdata+8);
3841 tvs.modtime = make_unix_date2(pdata+12);
3842 size = IVAL(pdata,16);
3843 dosmode = IVAL(pdata,24);
3844 break;
3845 #endif
3847 case SMB_SET_FILE_BASIC_INFO:
3848 case SMB_FILE_BASIC_INFORMATION:
3850 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3851 time_t write_time;
3852 time_t changed_time;
3854 if (total_data < 36) {
3855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3858 /* Ignore create time at offset pdata. */
3860 /* access time */
3861 tvs.actime = interpret_long_date(pdata+8);
3863 write_time = interpret_long_date(pdata+16);
3864 changed_time = interpret_long_date(pdata+24);
3866 tvs.modtime = MIN(write_time, changed_time);
3868 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3869 tvs.modtime = write_time;
3871 /* Prefer a defined time to an undefined one. */
3872 if (null_mtime(tvs.modtime)) {
3873 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3876 /* attributes */
3877 dosmode = IVAL(pdata,32);
3878 break;
3881 case SMB_FILE_ALLOCATION_INFORMATION:
3882 case SMB_SET_FILE_ALLOCATION_INFO:
3884 int ret = -1;
3885 SMB_BIG_UINT allocation_size;
3887 if (total_data < 8) {
3888 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3891 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3892 #ifdef LARGE_SMB_OFF_T
3893 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3894 #else /* LARGE_SMB_OFF_T */
3895 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3896 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3897 #endif /* LARGE_SMB_OFF_T */
3898 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3899 fname, (double)allocation_size ));
3901 if (allocation_size) {
3902 allocation_size = smb_roundup(conn, allocation_size);
3905 if(allocation_size != get_file_size(sbuf)) {
3906 SMB_STRUCT_STAT new_sbuf;
3908 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3909 fname, (double)allocation_size ));
3911 if (fd == -1) {
3912 files_struct *new_fsp = NULL;
3914 if(global_oplock_break) {
3915 /* Queue this file modify as we are the process of an oplock break. */
3917 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3918 DEBUGADD(2,( "in oplock break state.\n"));
3920 push_oplock_pending_smb_message(inbuf, length);
3921 return -1;
3924 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3925 FILE_WRITE_DATA,
3926 FILE_SHARE_READ|FILE_SHARE_WRITE,
3927 FILE_OPEN,
3929 FILE_ATTRIBUTE_NORMAL,
3930 INTERNAL_OPEN_ONLY,
3931 NULL);
3933 if (new_fsp == NULL) {
3934 return(UNIXERROR(ERRDOS,ERRbadpath));
3936 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3937 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3938 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3939 new_fsp->fnum, strerror(errno)));
3940 ret = -1;
3942 close_file(new_fsp,True);
3943 } else {
3944 ret = vfs_allocate_file_space(fsp, allocation_size);
3945 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3946 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3947 fsp->fnum, strerror(errno)));
3948 ret = -1;
3951 if (ret == -1)
3952 return ERROR_NT(NT_STATUS_DISK_FULL);
3954 /* Allocate can truncate size... */
3955 size = get_file_size(new_sbuf);
3958 break;
3961 case SMB_FILE_END_OF_FILE_INFORMATION:
3962 case SMB_SET_FILE_END_OF_FILE_INFO:
3964 if (total_data < 8) {
3965 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3968 size = IVAL(pdata,0);
3969 #ifdef LARGE_SMB_OFF_T
3970 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3971 #else /* LARGE_SMB_OFF_T */
3972 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3973 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3974 #endif /* LARGE_SMB_OFF_T */
3975 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3976 break;
3979 case SMB_FILE_DISPOSITION_INFORMATION:
3980 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3982 BOOL delete_on_close;
3984 if (total_data < 1) {
3985 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3988 delete_on_close = (CVAL(pdata,0) ? True : False);
3990 /* Just ignore this set on a path. */
3991 if (tran_call != TRANSACT2_SETFILEINFO)
3992 break;
3994 if (fsp == NULL)
3995 return(UNIXERROR(ERRDOS,ERRbadfid));
3997 status = can_set_delete_on_close(fsp, delete_on_close,
3998 dosmode);
4000 if (!NT_STATUS_IS_OK(status)) {
4001 return ERROR_NT(status);
4004 /* The set is across all open files on this dev/inode pair. */
4005 status =set_delete_on_close(fsp, delete_on_close);
4006 if (!NT_STATUS_IS_OK(status)) {
4007 return ERROR_NT(status);
4010 SSVAL(params,0,0);
4011 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4012 return(-1);
4015 case SMB_FILE_POSITION_INFORMATION:
4017 SMB_BIG_UINT position_information;
4019 if (total_data < 8) {
4020 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4023 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4024 #ifdef LARGE_SMB_OFF_T
4025 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4026 #else /* LARGE_SMB_OFF_T */
4027 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4028 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4029 #endif /* LARGE_SMB_OFF_T */
4030 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4031 fname, (double)position_information ));
4032 if (fsp) {
4033 fsp->fh->position_information = position_information;
4036 /* We're done. We only get position info in this call. */
4037 SSVAL(params,0,0);
4038 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4039 return(-1);
4042 /* From tridge Samba4 :
4043 * MODE_INFORMATION in setfileinfo (I have no
4044 * idea what "mode information" on a file is - it takes a value of 0,
4045 * 2, 4 or 6. What could it be?).
4048 case SMB_FILE_MODE_INFORMATION:
4050 uint32 mode;
4052 if (total_data < 4) {
4053 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4055 mode = IVAL(pdata,0);
4056 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4057 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4060 /* We're done. We only get mode info in this call. */
4061 SSVAL(params,0,0);
4062 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4063 return(-1);
4067 * CIFS UNIX extensions.
4070 case SMB_SET_FILE_UNIX_BASIC:
4072 uint32 raw_unixmode;
4074 if (total_data < 100) {
4075 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4078 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4079 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4080 size=IVAL(pdata,0); /* first 8 Bytes are size */
4081 #ifdef LARGE_SMB_OFF_T
4082 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4083 #else /* LARGE_SMB_OFF_T */
4084 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4085 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4086 #endif /* LARGE_SMB_OFF_T */
4088 pdata+=24; /* ctime & st_blocks are not changed */
4089 tvs.actime = interpret_long_date(pdata); /* access_time */
4090 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4091 pdata+=16;
4092 set_owner = (uid_t)IVAL(pdata,0);
4093 pdata += 8;
4094 set_grp = (gid_t)IVAL(pdata,0);
4095 pdata += 8;
4096 raw_unixmode = IVAL(pdata,28);
4097 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4098 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4100 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4101 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4102 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4104 if (!VALID_STAT(sbuf)) {
4107 * The only valid use of this is to create character and block
4108 * devices, and named pipes. This is deprecated (IMHO) and
4109 * a new info level should be used for mknod. JRA.
4112 uint32 file_type = IVAL(pdata,0);
4113 #if defined(HAVE_MAKEDEV)
4114 uint32 dev_major = IVAL(pdata,4);
4115 uint32 dev_minor = IVAL(pdata,12);
4116 #endif
4118 uid_t myuid = geteuid();
4119 gid_t mygid = getegid();
4120 SMB_DEV_T dev = (SMB_DEV_T)0;
4122 if (tran_call == TRANSACT2_SETFILEINFO)
4123 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4125 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4126 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4129 #if defined(HAVE_MAKEDEV)
4130 dev = makedev(dev_major, dev_minor);
4131 #endif
4133 /* We can only create as the owner/group we are. */
4135 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4136 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4137 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4138 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4140 switch (file_type) {
4141 #if defined(S_IFIFO)
4142 case UNIX_TYPE_FIFO:
4143 unixmode |= S_IFIFO;
4144 break;
4145 #endif
4146 #if defined(S_IFSOCK)
4147 case UNIX_TYPE_SOCKET:
4148 unixmode |= S_IFSOCK;
4149 break;
4150 #endif
4151 #if defined(S_IFCHR)
4152 case UNIX_TYPE_CHARDEV:
4153 unixmode |= S_IFCHR;
4154 break;
4155 #endif
4156 #if defined(S_IFBLK)
4157 case UNIX_TYPE_BLKDEV:
4158 unixmode |= S_IFBLK;
4159 break;
4160 #endif
4161 default:
4162 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4165 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4166 0%o for file %s\n", (double)dev, unixmode, fname ));
4168 /* Ok - do the mknod. */
4169 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4170 return(UNIXERROR(ERRDOS,ERRnoaccess));
4172 inherit_access_acl(conn, fname, unixmode);
4174 SSVAL(params,0,0);
4175 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4176 return(-1);
4180 * Deal with the UNIX specific mode set.
4183 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4184 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4185 (unsigned int)unixmode, fname ));
4186 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4187 return(UNIXERROR(ERRDOS,ERRnoaccess));
4191 * Deal with the UNIX specific uid set.
4194 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4195 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4196 (unsigned int)set_owner, fname ));
4197 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4198 return(UNIXERROR(ERRDOS,ERRnoaccess));
4202 * Deal with the UNIX specific gid set.
4205 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4206 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4207 (unsigned int)set_owner, fname ));
4208 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4209 return(UNIXERROR(ERRDOS,ERRnoaccess));
4211 break;
4214 case SMB_SET_FILE_UNIX_LINK:
4216 pstring link_target;
4217 char *newname = fname;
4219 /* Set a symbolic link. */
4220 /* Don't allow this if follow links is false. */
4222 if (!lp_symlinks(SNUM(conn)))
4223 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4225 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4227 /* !widelinks forces the target path to be within the share. */
4228 /* This means we can interpret the target as a pathname. */
4229 if (!lp_widelinks(SNUM(conn))) {
4230 pstring rel_name;
4231 char *last_dirp = NULL;
4233 unix_format(link_target);
4234 if (*link_target == '/') {
4235 /* No absolute paths allowed. */
4236 return(UNIXERROR(ERRDOS,ERRnoaccess));
4238 pstrcpy(rel_name, newname);
4239 last_dirp = strrchr_m(rel_name, '/');
4240 if (last_dirp) {
4241 last_dirp[1] = '\0';
4242 } else {
4243 pstrcpy(rel_name, "./");
4245 pstrcat(rel_name, link_target);
4247 if (!check_name(rel_name, conn)) {
4248 return(UNIXERROR(ERRDOS,ERRnoaccess));
4252 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4253 fname, link_target ));
4255 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4256 return(UNIXERROR(ERRDOS,ERRnoaccess));
4257 SSVAL(params,0,0);
4258 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4259 return(-1);
4262 case SMB_SET_FILE_UNIX_HLINK:
4264 pstring oldname;
4265 char *newname = fname;
4267 /* Set a hard link. */
4268 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 return ERROR_NT(status);
4273 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4274 fname, oldname));
4276 status = hardlink_internals(conn, oldname, newname);
4277 if (!NT_STATUS_IS_OK(status)) {
4278 return ERROR_NT(status);
4281 SSVAL(params,0,0);
4282 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4283 return(-1);
4286 case SMB_FILE_RENAME_INFORMATION:
4288 BOOL overwrite;
4289 uint32 root_fid;
4290 uint32 len;
4291 pstring newname;
4292 pstring base_name;
4293 char *p;
4295 if (total_data < 12) {
4296 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4299 overwrite = (CVAL(pdata,0) ? True : False);
4300 root_fid = IVAL(pdata,4);
4301 len = IVAL(pdata,8);
4302 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4303 if (!NT_STATUS_IS_OK(status)) {
4304 return ERROR_NT(status);
4307 /* Check the new name has no '/' characters. */
4308 if (strchr_m(newname, '/'))
4309 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4311 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4313 /* Create the base directory. */
4314 pstrcpy(base_name, fname);
4315 p = strrchr_m(base_name, '/');
4316 if (p)
4317 *p = '\0';
4318 /* Append the new name. */
4319 pstrcat(base_name, "/");
4320 pstrcat(base_name, newname);
4322 if (fsp) {
4323 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4324 fsp->fnum, fsp->fsp_name, base_name ));
4325 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4326 } else {
4327 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4328 fname, newname ));
4329 status = rename_internals(conn, fname, base_name, 0, overwrite);
4331 if (!NT_STATUS_IS_OK(status)) {
4332 return ERROR_NT(status);
4334 process_pending_change_notify_queue((time_t)0);
4335 SSVAL(params,0,0);
4336 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4337 return(-1);
4340 #if defined(HAVE_POSIX_ACLS)
4341 case SMB_SET_POSIX_ACL:
4343 uint16 posix_acl_version;
4344 uint16 num_file_acls;
4345 uint16 num_def_acls;
4346 BOOL valid_file_acls = True;
4347 BOOL valid_def_acls = True;
4349 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4350 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4352 posix_acl_version = SVAL(pdata,0);
4353 num_file_acls = SVAL(pdata,2);
4354 num_def_acls = SVAL(pdata,4);
4356 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4357 valid_file_acls = False;
4358 num_file_acls = 0;
4361 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4362 valid_def_acls = False;
4363 num_def_acls = 0;
4366 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4367 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4370 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4371 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4372 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4375 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4376 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4377 return(UNIXERROR(ERRDOS,ERRnoaccess));
4380 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4381 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4382 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4383 return(UNIXERROR(ERRDOS,ERRnoaccess));
4386 SSVAL(params,0,0);
4387 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4388 return(-1);
4390 #endif
4392 default:
4393 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4396 /* get some defaults (no modifications) if any info is zero or -1. */
4397 if (null_mtime(tvs.actime)) {
4398 tvs.actime = sbuf.st_atime;
4401 if (null_mtime(tvs.modtime)) {
4402 tvs.modtime = sbuf.st_mtime;
4405 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4406 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4407 DEBUG(6,("size: %.0f ", (double)size));
4409 if (dosmode) {
4410 if (S_ISDIR(sbuf.st_mode))
4411 dosmode |= aDIR;
4412 else
4413 dosmode &= ~aDIR;
4416 DEBUG(6,("dosmode: %x\n" , dosmode));
4418 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4419 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4420 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4421 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4424 * Only do this test if we are not explicitly
4425 * changing the size of a file.
4427 if (!size)
4428 size = get_file_size(sbuf);
4432 * Try and set the times, size and mode of this file -
4433 * if they are different from the current values
4436 /* check the mode isn't different, before changing it */
4437 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4439 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4441 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4442 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4443 return(UNIXERROR(ERRDOS,ERRnoaccess));
4447 /* Now the size. */
4448 if (size != get_file_size(sbuf)) {
4450 int ret;
4452 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4453 fname, (double)size ));
4455 if (fd == -1) {
4456 files_struct *new_fsp = NULL;
4458 if(global_oplock_break) {
4459 /* Queue this file modify as we are the process of an oplock break. */
4461 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4462 DEBUGADD(2,( "in oplock break state.\n"));
4464 push_oplock_pending_smb_message(inbuf, length);
4465 return -1;
4468 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4469 FILE_WRITE_DATA,
4470 FILE_SHARE_READ|FILE_SHARE_WRITE,
4471 FILE_OPEN,
4473 FILE_ATTRIBUTE_NORMAL,
4474 INTERNAL_OPEN_ONLY,
4475 NULL);
4477 if (new_fsp == NULL) {
4478 return(UNIXERROR(ERRDOS,ERRbadpath));
4480 ret = vfs_set_filelen(new_fsp, size);
4481 close_file(new_fsp,True);
4482 } else {
4483 ret = vfs_set_filelen(fsp, size);
4486 if (ret == -1) {
4487 return (UNIXERROR(ERRHRD,ERRdiskfull));
4492 * Finally the times.
4494 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4495 if(fsp != NULL) {
4497 * This was a setfileinfo on an open file.
4498 * NT does this a lot. We also need to
4499 * set the time here, as it can be read by
4500 * FindFirst/FindNext and with the patch for bug #2045
4501 * in smbd/fileio.c it ensures that this timestamp is
4502 * kept sticky even after a write. We save the request
4503 * away and will set it on file close and after a write. JRA.
4506 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4507 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4508 fsp_set_pending_modtime(fsp, tvs.modtime);
4512 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4514 if(file_utime(conn, fname, &tvs)!=0) {
4515 return(UNIXERROR(ERRDOS,ERRnoaccess));
4519 SSVAL(params,0,0);
4520 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4522 return(-1);
4525 /****************************************************************************
4526 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4527 ****************************************************************************/
4529 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4530 char **pparams, int total_params, char **ppdata, int total_data,
4531 unsigned int max_data_bytes)
4533 char *params = *pparams;
4534 char *pdata = *ppdata;
4535 pstring directory;
4536 int ret = -1;
4537 SMB_STRUCT_STAT sbuf;
4538 BOOL bad_path = False;
4539 NTSTATUS status = NT_STATUS_OK;
4540 TALLOC_CTX *ctx = NULL;
4541 struct ea_list *ea_list = NULL;
4543 if (!CAN_WRITE(conn))
4544 return ERROR_DOS(ERRSRV,ERRaccess);
4546 if (total_params < 4) {
4547 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4550 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4551 if (!NT_STATUS_IS_OK(status)) {
4552 return ERROR_NT(status);
4555 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4557 unix_convert(directory,conn,0,&bad_path,&sbuf);
4558 if (bad_path) {
4559 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4562 /* Any data in this call is an EA list. */
4563 if (total_data && !lp_ea_support(SNUM(conn))) {
4564 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4567 if (total_data) {
4568 if (total_data < 10) {
4569 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4572 if (IVAL(pdata,0) > total_data) {
4573 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4574 IVAL(pdata,0), (unsigned int)total_data));
4575 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4578 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4579 if (!ctx) {
4580 return ERROR_NT(NT_STATUS_NO_MEMORY);
4582 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4583 if (!ea_list) {
4584 talloc_destroy(ctx);
4585 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4589 if (check_name(directory,conn)) {
4590 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4593 if(ret < 0) {
4594 talloc_destroy(ctx);
4595 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4596 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4599 /* Try and set any given EA. */
4600 if (total_data) {
4601 status = set_ea(conn, NULL, directory, ea_list);
4602 talloc_destroy(ctx);
4603 if (!NT_STATUS_IS_OK(status)) {
4604 return ERROR_NT(status);
4608 /* Realloc the parameter and data sizes */
4609 params = SMB_REALLOC(*pparams,2);
4610 if(params == NULL) {
4611 return ERROR_NT(NT_STATUS_NO_MEMORY);
4613 *pparams = params;
4615 SSVAL(params,0,0);
4617 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4619 return(-1);
4622 /****************************************************************************
4623 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4624 We don't actually do this - we just send a null response.
4625 ****************************************************************************/
4627 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4628 char **pparams, int total_params, char **ppdata, int total_data,
4629 unsigned int max_data_bytes)
4631 static uint16 fnf_handle = 257;
4632 char *params = *pparams;
4633 uint16 info_level;
4635 if (total_params < 6) {
4636 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4639 info_level = SVAL(params,4);
4640 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4642 switch (info_level) {
4643 case 1:
4644 case 2:
4645 break;
4646 default:
4647 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4650 /* Realloc the parameter and data sizes */
4651 params = SMB_REALLOC(*pparams,6);
4652 if(params == NULL) {
4653 return ERROR_NT(NT_STATUS_NO_MEMORY);
4655 *pparams = params;
4657 SSVAL(params,0,fnf_handle);
4658 SSVAL(params,2,0); /* No changes */
4659 SSVAL(params,4,0); /* No EA errors */
4661 fnf_handle++;
4663 if(fnf_handle == 0)
4664 fnf_handle = 257;
4666 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4668 return(-1);
4671 /****************************************************************************
4672 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4673 changes). Currently this does nothing.
4674 ****************************************************************************/
4676 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4677 char **pparams, int total_params, char **ppdata, int total_data,
4678 unsigned int max_data_bytes)
4680 char *params = *pparams;
4682 DEBUG(3,("call_trans2findnotifynext\n"));
4684 /* Realloc the parameter and data sizes */
4685 params = SMB_REALLOC(*pparams,4);
4686 if(params == NULL) {
4687 return ERROR_NT(NT_STATUS_NO_MEMORY);
4689 *pparams = params;
4691 SSVAL(params,0,0); /* No changes */
4692 SSVAL(params,2,0); /* No EA errors */
4694 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4696 return(-1);
4699 /****************************************************************************
4700 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4701 ****************************************************************************/
4703 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4704 char **pparams, int total_params, char **ppdata, int total_data,
4705 unsigned int max_data_bytes)
4707 char *params = *pparams;
4708 pstring pathname;
4709 int reply_size = 0;
4710 int max_referral_level;
4712 DEBUG(10,("call_trans2getdfsreferral\n"));
4714 if (total_params < 2) {
4715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4718 max_referral_level = SVAL(params,0);
4720 if(!lp_host_msdfs())
4721 return ERROR_DOS(ERRDOS,ERRbadfunc);
4723 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4724 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4725 return UNIXERROR(ERRDOS,ERRbadfile);
4727 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4728 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4730 return(-1);
4733 #define LMCAT_SPL 0x53
4734 #define LMFUNC_GETJOBID 0x60
4736 /****************************************************************************
4737 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4738 ****************************************************************************/
4740 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4741 char **pparams, int total_params, char **ppdata, int total_data,
4742 unsigned int max_data_bytes)
4744 char *pdata = *ppdata;
4745 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4747 /* check for an invalid fid before proceeding */
4749 if (!fsp)
4750 return(ERROR_DOS(ERRDOS,ERRbadfid));
4752 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4753 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4754 pdata = SMB_REALLOC(*ppdata, 32);
4755 if(pdata == NULL) {
4756 return ERROR_NT(NT_STATUS_NO_MEMORY);
4758 *ppdata = pdata;
4760 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4761 CAN ACCEPT THIS IN UNICODE. JRA. */
4763 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4764 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4765 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4766 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4767 return(-1);
4768 } else {
4769 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4770 return ERROR_DOS(ERRSRV,ERRerror);
4774 /****************************************************************************
4775 Reply to a SMBfindclose (stop trans2 directory search).
4776 ****************************************************************************/
4778 int reply_findclose(connection_struct *conn,
4779 char *inbuf,char *outbuf,int length,int bufsize)
4781 int outsize = 0;
4782 int dptr_num=SVALS(inbuf,smb_vwv0);
4783 START_PROFILE(SMBfindclose);
4785 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4787 dptr_close(&dptr_num);
4789 outsize = set_message(outbuf,0,0,True);
4791 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4793 END_PROFILE(SMBfindclose);
4794 return(outsize);
4797 /****************************************************************************
4798 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4799 ****************************************************************************/
4801 int reply_findnclose(connection_struct *conn,
4802 char *inbuf,char *outbuf,int length,int bufsize)
4804 int outsize = 0;
4805 int dptr_num= -1;
4806 START_PROFILE(SMBfindnclose);
4808 dptr_num = SVAL(inbuf,smb_vwv0);
4810 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4812 /* We never give out valid handles for a
4813 findnotifyfirst - so any dptr_num is ok here.
4814 Just ignore it. */
4816 outsize = set_message(outbuf,0,0,True);
4818 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4820 END_PROFILE(SMBfindnclose);
4821 return(outsize);
4824 /****************************************************************************
4825 Reply to a SMBtranss2 - just ignore it!
4826 ****************************************************************************/
4828 int reply_transs2(connection_struct *conn,
4829 char *inbuf,char *outbuf,int length,int bufsize)
4831 START_PROFILE(SMBtranss2);
4832 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4833 END_PROFILE(SMBtranss2);
4834 return(-1);
4837 /****************************************************************************
4838 Reply to a SMBtrans2.
4839 ****************************************************************************/
4841 int reply_trans2(connection_struct *conn,
4842 char *inbuf,char *outbuf,int length,int bufsize)
4844 int outsize = 0;
4845 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4846 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4847 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4848 #if 0
4849 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4850 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4851 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4852 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4853 int32 timeout = IVALS(inbuf,smb_timeout);
4854 #endif
4855 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4856 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4857 char *params = NULL, *data = NULL;
4858 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4859 START_PROFILE(SMBtrans2);
4861 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4862 /* Queue this open message as we are the process of an
4863 * oplock break. */
4865 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4866 DEBUGADD(2,( "in oplock break state.\n"));
4868 push_oplock_pending_smb_message(inbuf, length);
4869 END_PROFILE(SMBtrans2);
4870 return -1;
4873 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4874 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4875 END_PROFILE(SMBtrans2);
4876 return ERROR_DOS(ERRSRV,ERRaccess);
4879 outsize = set_message(outbuf,0,0,True);
4881 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4882 is so as a sanity check */
4883 if (suwcnt != 1) {
4885 * Need to have rc=0 for ioctl to get job id for OS/2.
4886 * Network printing will fail if function is not successful.
4887 * Similar function in reply.c will be used if protocol
4888 * is LANMAN1.0 instead of LM1.2X002.
4889 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4890 * outbuf doesn't have to be set(only job id is used).
4892 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4893 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4894 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4895 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4896 } else {
4897 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4898 DEBUG(2,("Transaction is %d\n",tran_call));
4899 END_PROFILE(SMBtrans2);
4900 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4904 /* Allocate the space for the maximum needed parameters and data */
4905 if (total_params > 0)
4906 params = (char *)SMB_MALLOC(total_params);
4907 if (total_data > 0)
4908 data = (char *)SMB_MALLOC(total_data);
4910 if ((total_params && !params) || (total_data && !data)) {
4911 DEBUG(2,("Out of memory in reply_trans2\n"));
4912 SAFE_FREE(params);
4913 SAFE_FREE(data);
4914 END_PROFILE(SMBtrans2);
4915 return ERROR_NT(NT_STATUS_NO_MEMORY);
4918 /* Copy the param and data bytes sent with this request into
4919 the params buffer */
4920 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4921 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4923 if (num_params > total_params || num_data > total_data)
4924 exit_server("invalid params in reply_trans2");
4926 if(params) {
4927 unsigned int psoff = SVAL(inbuf, smb_psoff);
4928 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4929 goto bad_param;
4930 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4931 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4932 goto bad_param;
4933 memcpy( params, smb_base(inbuf) + psoff, num_params);
4935 if(data) {
4936 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4937 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4938 goto bad_param;
4939 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4940 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4941 goto bad_param;
4942 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4945 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4947 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4948 /* We need to send an interim response then receive the rest
4949 of the parameter/data bytes */
4950 outsize = set_message(outbuf,0,0,True);
4951 srv_signing_trans_stop();
4952 show_msg(outbuf);
4953 if (!send_smb(smbd_server_fd(),outbuf))
4954 exit_server("reply_trans2: send_smb failed.");
4956 while (num_data_sofar < total_data ||
4957 num_params_sofar < total_params) {
4958 BOOL ret;
4959 unsigned int param_disp;
4960 unsigned int param_off;
4961 unsigned int data_disp;
4962 unsigned int data_off;
4964 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4966 /* We need to re-calcuate the new length after we've read the secondary packet. */
4967 length = smb_len(inbuf) + 4;
4970 * The sequence number for the trans reply is always
4971 * based on the last secondary received.
4974 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4976 if ((ret &&
4977 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4978 outsize = set_message(outbuf,0,0,True);
4979 if(ret)
4980 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4981 else
4982 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4983 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4984 goto bad_param;
4987 /* Revise total_params and total_data in case
4988 they have changed downwards */
4989 if (SVAL(inbuf, smb_tpscnt) < total_params)
4990 total_params = SVAL(inbuf, smb_tpscnt);
4991 if (SVAL(inbuf, smb_tdscnt) < total_data)
4992 total_data = SVAL(inbuf, smb_tdscnt);
4994 num_params = SVAL(inbuf,smb_spscnt);
4995 param_off = SVAL(inbuf, smb_spsoff);
4996 param_disp = SVAL(inbuf, smb_spsdisp);
4997 num_params_sofar += num_params;
4999 num_data = SVAL(inbuf, smb_sdscnt);
5000 data_off = SVAL(inbuf, smb_sdsoff);
5001 data_disp = SVAL(inbuf, smb_sdsdisp);
5002 num_data_sofar += num_data;
5004 if (num_params_sofar > total_params || num_data_sofar > total_data)
5005 goto bad_param;
5007 if (num_params) {
5008 if (param_disp + num_params > total_params)
5009 goto bad_param;
5010 if ((param_disp + num_params < param_disp) ||
5011 (param_disp + num_params < num_params))
5012 goto bad_param;
5013 if (param_disp > total_params)
5014 goto bad_param;
5015 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
5016 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
5017 goto bad_param;
5018 if (params + param_disp < params)
5019 goto bad_param;
5021 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
5023 if (num_data) {
5024 if (data_disp + num_data > total_data)
5025 goto bad_param;
5026 if ((data_disp + num_data < data_disp) ||
5027 (data_disp + num_data < num_data))
5028 goto bad_param;
5029 if (data_disp > total_data)
5030 goto bad_param;
5031 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
5032 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
5033 goto bad_param;
5034 if (data + data_disp < data)
5035 goto bad_param;
5037 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
5042 if (Protocol >= PROTOCOL_NT1) {
5043 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5046 /* Now we must call the relevant TRANS2 function */
5047 switch(tran_call) {
5048 case TRANSACT2_OPEN:
5049 START_PROFILE_NESTED(Trans2_open);
5050 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
5051 &params, total_params, &data, total_data, max_data_bytes);
5052 END_PROFILE_NESTED(Trans2_open);
5053 break;
5055 case TRANSACT2_FINDFIRST:
5056 START_PROFILE_NESTED(Trans2_findfirst);
5057 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
5058 &params, total_params, &data, total_data, max_data_bytes);
5059 END_PROFILE_NESTED(Trans2_findfirst);
5060 break;
5062 case TRANSACT2_FINDNEXT:
5063 START_PROFILE_NESTED(Trans2_findnext);
5064 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
5065 &params, total_params, &data, total_data, max_data_bytes);
5066 END_PROFILE_NESTED(Trans2_findnext);
5067 break;
5069 case TRANSACT2_QFSINFO:
5070 START_PROFILE_NESTED(Trans2_qfsinfo);
5071 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
5072 &params, total_params, &data, total_data, max_data_bytes);
5073 END_PROFILE_NESTED(Trans2_qfsinfo);
5074 break;
5076 case TRANSACT2_SETFSINFO:
5077 START_PROFILE_NESTED(Trans2_setfsinfo);
5078 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5079 &params, total_params, &data, total_data, max_data_bytes);
5080 END_PROFILE_NESTED(Trans2_setfsinfo);
5081 break;
5083 case TRANSACT2_QPATHINFO:
5084 case TRANSACT2_QFILEINFO:
5085 START_PROFILE_NESTED(Trans2_qpathinfo);
5086 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5087 &params, total_params, &data, total_data, max_data_bytes);
5088 END_PROFILE_NESTED(Trans2_qpathinfo);
5089 break;
5090 case TRANSACT2_SETPATHINFO:
5091 case TRANSACT2_SETFILEINFO:
5092 START_PROFILE_NESTED(Trans2_setpathinfo);
5093 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5094 &params, total_params, &data, total_data, max_data_bytes);
5095 END_PROFILE_NESTED(Trans2_setpathinfo);
5096 break;
5098 case TRANSACT2_FINDNOTIFYFIRST:
5099 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5100 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5101 &params, total_params, &data, total_data, max_data_bytes);
5102 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5103 break;
5105 case TRANSACT2_FINDNOTIFYNEXT:
5106 START_PROFILE_NESTED(Trans2_findnotifynext);
5107 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5108 &params, total_params, &data, total_data, max_data_bytes);
5109 END_PROFILE_NESTED(Trans2_findnotifynext);
5110 break;
5111 case TRANSACT2_MKDIR:
5112 START_PROFILE_NESTED(Trans2_mkdir);
5113 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5114 &params, total_params, &data, total_data, max_data_bytes);
5115 END_PROFILE_NESTED(Trans2_mkdir);
5116 break;
5118 case TRANSACT2_GET_DFS_REFERRAL:
5119 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5120 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5121 &params, total_params, &data, total_data, max_data_bytes);
5122 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5123 break;
5124 case TRANSACT2_IOCTL:
5125 START_PROFILE_NESTED(Trans2_ioctl);
5126 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5127 &params, total_params, &data, total_data, max_data_bytes);
5128 END_PROFILE_NESTED(Trans2_ioctl);
5129 break;
5130 default:
5131 /* Error in request */
5132 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5133 SAFE_FREE(params);
5134 SAFE_FREE(data);
5135 END_PROFILE(SMBtrans2);
5136 srv_signing_trans_stop();
5137 return ERROR_DOS(ERRSRV,ERRerror);
5140 /* As we do not know how many data packets will need to be
5141 returned here the various call_trans2xxxx calls
5142 must send their own. Thus a call_trans2xxx routine only
5143 returns a value other than -1 when it wants to send
5144 an error packet.
5147 srv_signing_trans_stop();
5149 SAFE_FREE(params);
5150 SAFE_FREE(data);
5151 END_PROFILE(SMBtrans2);
5152 return outsize; /* If a correct response was needed the
5153 call_trans2xxx calls have already sent
5154 it. If outsize != -1 then it is returning */
5156 bad_param:
5158 srv_signing_trans_stop();
5159 SAFE_FREE(params);
5160 SAFE_FREE(data);
5161 END_PROFILE(SMBtrans2);
5162 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);