r12877: Stop passing structs around in smb messages, instead
[Samba/bb.git] / source3 / smbd / trans2.c
blob8ff219b468c0dee081c0694bc2f870d99b0d5182
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
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
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);
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 && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
808 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
811 if (total_data != 4) {
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);
831 } else if (IVAL(pdata,0) != 4) {
832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
835 fsp = open_file_ntcreate(conn,fname,&sbuf,
836 access_mask,
837 share_mode,
838 create_disposition,
839 create_options,
840 open_attr,
841 oplock_request,
842 &smb_action);
844 if (!fsp) {
845 talloc_destroy(ctx);
846 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
847 /* We have re-scheduled this call. */
848 return -1;
850 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
853 size = get_file_size(sbuf);
854 fattr = dos_mode(conn,fname,&sbuf);
855 mtime = sbuf.st_mtime;
856 inode = sbuf.st_ino;
857 if (fattr & aDIR) {
858 talloc_destroy(ctx);
859 close_file(fsp,False);
860 return(ERROR_DOS(ERRDOS,ERRnoaccess));
863 if (total_data && smb_action == FILE_WAS_CREATED) {
864 status = set_ea(conn, fsp, fname, ea_list);
865 talloc_destroy(ctx);
866 if (!NT_STATUS_IS_OK(status)) {
867 close_file(fsp,False);
868 return ERROR_NT(status);
872 /* Realloc the size of parameters and data we will return */
873 params = SMB_REALLOC(*pparams, 30);
874 if( params == NULL ) {
875 return ERROR_NT(NT_STATUS_NO_MEMORY);
877 *pparams = params;
879 SSVAL(params,0,fsp->fnum);
880 SSVAL(params,2,open_attr);
881 srv_put_dos_date2(params,4, mtime);
882 SIVAL(params,8, (uint32)size);
883 SSVAL(params,12,deny_mode);
884 SSVAL(params,14,0); /* open_type - file or directory. */
885 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
887 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
888 smb_action |= EXTENDED_OPLOCK_GRANTED;
891 SSVAL(params,18,smb_action);
894 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
896 SIVAL(params,20,inode);
897 SSVAL(params,24,0); /* Padding. */
898 if (flags & 8) {
899 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
900 SIVAL(params, 26, ea_size);
901 } else {
902 SIVAL(params, 26, 0);
905 /* Send the required number of replies */
906 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
908 return -1;
911 /*********************************************************
912 Routine to check if a given string matches exactly.
913 as a special case a mask of "." does NOT match. That
914 is required for correct wildcard semantics
915 Case can be significant or not.
916 **********************************************************/
918 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
920 if (mask[0] == '.' && mask[1] == 0)
921 return False;
922 if (case_sig)
923 return strcmp(str,mask)==0;
924 if (StrCaseCmp(str,mask) != 0) {
925 return False;
927 if (ms_has_wild(str)) {
928 return False;
930 return True;
933 /****************************************************************************
934 Return the filetype for UNIX extensions.
935 ****************************************************************************/
937 static uint32 unix_filetype(mode_t mode)
939 if(S_ISREG(mode))
940 return UNIX_TYPE_FILE;
941 else if(S_ISDIR(mode))
942 return UNIX_TYPE_DIR;
943 #ifdef S_ISLNK
944 else if(S_ISLNK(mode))
945 return UNIX_TYPE_SYMLINK;
946 #endif
947 #ifdef S_ISCHR
948 else if(S_ISCHR(mode))
949 return UNIX_TYPE_CHARDEV;
950 #endif
951 #ifdef S_ISBLK
952 else if(S_ISBLK(mode))
953 return UNIX_TYPE_BLKDEV;
954 #endif
955 #ifdef S_ISFIFO
956 else if(S_ISFIFO(mode))
957 return UNIX_TYPE_FIFO;
958 #endif
959 #ifdef S_ISSOCK
960 else if(S_ISSOCK(mode))
961 return UNIX_TYPE_SOCKET;
962 #endif
964 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
965 return UNIX_TYPE_UNKNOWN;
968 /****************************************************************************
969 Map wire perms onto standard UNIX permissions. Obey share restrictions.
970 ****************************************************************************/
972 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
974 mode_t ret = 0;
976 if (perms == SMB_MODE_NO_CHANGE)
977 return pst->st_mode;
979 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
980 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
981 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
982 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
983 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
984 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
985 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
986 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
987 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
988 #ifdef S_ISVTX
989 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
990 #endif
991 #ifdef S_ISGID
992 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
993 #endif
994 #ifdef S_ISUID
995 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
996 #endif
998 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
999 ret &= lp_dir_mask(SNUM(conn));
1000 /* Add in force bits */
1001 ret |= lp_force_dir_mode(SNUM(conn));
1002 } else {
1003 /* Apply mode mask */
1004 ret &= lp_create_mask(SNUM(conn));
1005 /* Add in force bits */
1006 ret |= lp_force_create_mode(SNUM(conn));
1009 return ret;
1012 /****************************************************************************
1013 Get a level dependent lanman2 dir entry.
1014 ****************************************************************************/
1016 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1017 void *inbuf, void *outbuf,
1018 char *path_mask,uint32 dirtype,int info_level,
1019 int requires_resume_key,
1020 BOOL dont_descend,char **ppdata,
1021 char *base_data, int space_remaining,
1022 BOOL *out_of_space, BOOL *got_exact_match,
1023 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1025 const char *dname;
1026 BOOL found = False;
1027 SMB_STRUCT_STAT sbuf;
1028 pstring mask;
1029 pstring pathreal;
1030 pstring fname;
1031 char *p, *q, *pdata = *ppdata;
1032 uint32 reskey=0;
1033 long prev_dirpos=0;
1034 uint32 mode=0;
1035 SMB_OFF_T file_size = 0;
1036 SMB_BIG_UINT allocation_size = 0;
1037 uint32 len;
1038 time_t mdate=0, adate=0, cdate=0;
1039 char *nameptr;
1040 char *last_entry_ptr;
1041 BOOL was_8_3;
1042 uint32 nt_extmode; /* Used for NT connections instead of mode */
1043 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1044 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1046 *fname = 0;
1047 *out_of_space = False;
1048 *got_exact_match = False;
1050 if (!conn->dirptr)
1051 return(False);
1053 p = strrchr_m(path_mask,'/');
1054 if(p != NULL) {
1055 if(p[1] == '\0')
1056 pstrcpy(mask,"*.*");
1057 else
1058 pstrcpy(mask, p+1);
1059 } else
1060 pstrcpy(mask, path_mask);
1063 while (!found) {
1064 BOOL got_match;
1065 /* Needed if we run out of space */
1066 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1067 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1070 * Due to bugs in NT client redirectors we are not using
1071 * resume keys any more - set them to zero.
1072 * Check out the related comments in findfirst/findnext.
1073 * JRA.
1076 reskey = 0;
1078 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1079 (long)conn->dirptr,curr_dirpos));
1081 if (!dname)
1082 return(False);
1084 pstrcpy(fname,dname);
1086 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1087 got_match = mask_match(fname, mask, conn->case_sensitive);
1089 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1092 * It turns out that NT matches wildcards against
1093 * both long *and* short names. This may explain some
1094 * of the wildcard wierdness from old DOS clients
1095 * that some people have been seeing.... JRA.
1098 pstring newname;
1099 pstrcpy( newname, fname);
1100 mangle_map( newname, True, False, SNUM(conn));
1101 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1102 got_match = mask_match(newname, mask, conn->case_sensitive);
1105 if(got_match) {
1106 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1107 if (dont_descend && !isdots)
1108 continue;
1110 pstrcpy(pathreal,conn->dirpath);
1111 if(needslash)
1112 pstrcat(pathreal,"/");
1113 pstrcat(pathreal,dname);
1115 if (INFO_LEVEL_IS_UNIX(info_level)) {
1116 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1117 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1118 pathreal,strerror(errno)));
1119 continue;
1121 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1123 /* Needed to show the msdfs symlinks as
1124 * directories */
1126 if(lp_host_msdfs() &&
1127 lp_msdfs_root(SNUM(conn)) &&
1128 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1129 &sbuf)) {
1131 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1132 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1134 } else {
1136 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1137 pathreal,strerror(errno)));
1138 continue;
1142 mode = dos_mode(conn,pathreal,&sbuf);
1144 if (!dir_check_ftype(conn,mode,dirtype)) {
1145 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1146 continue;
1149 file_size = get_file_size(sbuf);
1150 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1151 mdate = sbuf.st_mtime;
1152 adate = sbuf.st_atime;
1153 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1155 if (lp_dos_filetime_resolution(SNUM(conn))) {
1156 cdate &= ~1;
1157 mdate &= ~1;
1158 adate &= ~1;
1161 if(mode & aDIR) {
1162 /* This is necessary, as otherwise the
1163 * desktop.ini file in this folder is
1164 * ignored */
1165 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1166 file_size = 0;
1169 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1171 found = True;
1175 mangle_map(fname,False,True,SNUM(conn));
1177 p = pdata;
1178 last_entry_ptr = p;
1180 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1182 switch (info_level) {
1183 case SMB_FIND_INFO_STANDARD:
1184 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1185 if(requires_resume_key) {
1186 SIVAL(p,0,reskey);
1187 p += 4;
1189 srv_put_dos_date2(p,0,cdate);
1190 srv_put_dos_date2(p,4,adate);
1191 srv_put_dos_date2(p,8,mdate);
1192 SIVAL(p,12,(uint32)file_size);
1193 SIVAL(p,16,(uint32)allocation_size);
1194 SSVAL(p,20,mode);
1195 p += 23;
1196 nameptr = p;
1197 p += align_string(outbuf, p, 0);
1198 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1199 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1200 if (len > 2) {
1201 SCVAL(nameptr, -1, len - 2);
1202 } else {
1203 SCVAL(nameptr, -1, 0);
1205 } else {
1206 if (len > 1) {
1207 SCVAL(nameptr, -1, len - 1);
1208 } else {
1209 SCVAL(nameptr, -1, 0);
1212 p += len;
1213 break;
1215 case SMB_FIND_EA_SIZE:
1216 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1217 if(requires_resume_key) {
1218 SIVAL(p,0,reskey);
1219 p += 4;
1221 srv_put_dos_date2(p,0,cdate);
1222 srv_put_dos_date2(p,4,adate);
1223 srv_put_dos_date2(p,8,mdate);
1224 SIVAL(p,12,(uint32)file_size);
1225 SIVAL(p,16,(uint32)allocation_size);
1226 SSVAL(p,20,mode);
1228 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1229 SIVAL(p,22,ea_size); /* Extended attributes */
1231 p += 27;
1232 nameptr = p - 1;
1233 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1234 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1235 if (len > 2) {
1236 len -= 2;
1237 } else {
1238 len = 0;
1240 } else {
1241 if (len > 1) {
1242 len -= 1;
1243 } else {
1244 len = 0;
1247 SCVAL(nameptr,0,len);
1248 p += len;
1249 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1250 break;
1252 case SMB_FIND_EA_LIST:
1254 struct ea_list *file_list = NULL;
1255 size_t ea_len = 0;
1257 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1258 if (!name_list) {
1259 return False;
1261 if(requires_resume_key) {
1262 SIVAL(p,0,reskey);
1263 p += 4;
1265 srv_put_dos_date2(p,0,cdate);
1266 srv_put_dos_date2(p,4,adate);
1267 srv_put_dos_date2(p,8,mdate);
1268 SIVAL(p,12,(uint32)file_size);
1269 SIVAL(p,16,(uint32)allocation_size);
1270 SSVAL(p,20,mode);
1271 p += 22; /* p now points to the EA area. */
1273 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1274 name_list = ea_list_union(name_list, file_list, &ea_len);
1276 /* We need to determine if this entry will fit in the space available. */
1277 /* Max string size is 255 bytes. */
1278 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1279 /* Move the dirptr back to prev_dirpos */
1280 dptr_SeekDir(conn->dirptr, prev_dirpos);
1281 *out_of_space = True;
1282 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1283 return False; /* Not finished - just out of space */
1286 /* Push the ea_data followed by the name. */
1287 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1288 nameptr = p;
1289 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1290 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1291 if (len > 2) {
1292 len -= 2;
1293 } else {
1294 len = 0;
1296 } else {
1297 if (len > 1) {
1298 len -= 1;
1299 } else {
1300 len = 0;
1303 SCVAL(nameptr,0,len);
1304 p += len + 1;
1305 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1306 break;
1309 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1310 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1311 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1312 p += 4;
1313 SIVAL(p,0,reskey); p += 4;
1314 put_long_date(p,cdate); p += 8;
1315 put_long_date(p,adate); p += 8;
1316 put_long_date(p,mdate); p += 8;
1317 put_long_date(p,mdate); p += 8;
1318 SOFF_T(p,0,file_size); p += 8;
1319 SOFF_T(p,0,allocation_size); p += 8;
1320 SIVAL(p,0,nt_extmode); p += 4;
1321 q = p; p += 4; /* q is placeholder for name length. */
1323 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1324 SIVAL(p,0,ea_size); /* Extended attributes */
1325 p += 4;
1327 /* Clear the short name buffer. This is
1328 * IMPORTANT as not doing so will trigger
1329 * a Win2k client bug. JRA.
1331 if (!was_8_3 && check_mangled_names) {
1332 pstring mangled_name;
1333 pstrcpy(mangled_name, fname);
1334 mangle_map(mangled_name,True,True,SNUM(conn));
1335 mangled_name[12] = 0;
1336 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1337 if (len < 24) {
1338 memset(p + 2 + len,'\0',24 - len);
1340 SSVAL(p, 0, len);
1341 } else {
1342 memset(p,'\0',26);
1344 p += 2 + 24;
1345 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1346 SIVAL(q,0,len);
1347 p += len;
1348 SIVAL(p,0,0); /* Ensure any padding is null. */
1349 len = PTR_DIFF(p, pdata);
1350 len = (len + 3) & ~3;
1351 SIVAL(pdata,0,len);
1352 p = pdata + len;
1353 break;
1355 case SMB_FIND_FILE_DIRECTORY_INFO:
1356 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1357 p += 4;
1358 SIVAL(p,0,reskey); p += 4;
1359 put_long_date(p,cdate); p += 8;
1360 put_long_date(p,adate); p += 8;
1361 put_long_date(p,mdate); p += 8;
1362 put_long_date(p,mdate); p += 8;
1363 SOFF_T(p,0,file_size); p += 8;
1364 SOFF_T(p,0,allocation_size); p += 8;
1365 SIVAL(p,0,nt_extmode); p += 4;
1366 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1367 SIVAL(p,0,len);
1368 p += 4 + len;
1369 SIVAL(p,0,0); /* Ensure any padding is null. */
1370 len = PTR_DIFF(p, pdata);
1371 len = (len + 3) & ~3;
1372 SIVAL(pdata,0,len);
1373 p = pdata + len;
1374 break;
1376 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1377 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1378 p += 4;
1379 SIVAL(p,0,reskey); p += 4;
1380 put_long_date(p,cdate); p += 8;
1381 put_long_date(p,adate); p += 8;
1382 put_long_date(p,mdate); p += 8;
1383 put_long_date(p,mdate); p += 8;
1384 SOFF_T(p,0,file_size); p += 8;
1385 SOFF_T(p,0,allocation_size); p += 8;
1386 SIVAL(p,0,nt_extmode); p += 4;
1387 q = p; p += 4; /* q is placeholder for name length. */
1389 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1390 SIVAL(p,0,ea_size); /* Extended attributes */
1391 p +=4;
1393 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1394 SIVAL(q, 0, len);
1395 p += len;
1397 SIVAL(p,0,0); /* Ensure any padding is null. */
1398 len = PTR_DIFF(p, pdata);
1399 len = (len + 3) & ~3;
1400 SIVAL(pdata,0,len);
1401 p = pdata + len;
1402 break;
1404 case SMB_FIND_FILE_NAMES_INFO:
1405 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1406 p += 4;
1407 SIVAL(p,0,reskey); p += 4;
1408 p += 4;
1409 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1410 acl on a dir (tridge) */
1411 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1412 SIVAL(p, -4, len);
1413 p += len;
1414 SIVAL(p,0,0); /* Ensure any padding is null. */
1415 len = PTR_DIFF(p, pdata);
1416 len = (len + 3) & ~3;
1417 SIVAL(pdata,0,len);
1418 p = pdata + len;
1419 break;
1421 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1422 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1423 p += 4;
1424 SIVAL(p,0,reskey); p += 4;
1425 put_long_date(p,cdate); p += 8;
1426 put_long_date(p,adate); p += 8;
1427 put_long_date(p,mdate); p += 8;
1428 put_long_date(p,mdate); p += 8;
1429 SOFF_T(p,0,file_size); p += 8;
1430 SOFF_T(p,0,allocation_size); p += 8;
1431 SIVAL(p,0,nt_extmode); p += 4;
1432 q = p; p += 4; /* q is placeholder for name length. */
1434 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1435 SIVAL(p,0,ea_size); /* Extended attributes */
1436 p +=4;
1438 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1439 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1440 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1441 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1442 SIVAL(q, 0, len);
1443 p += len;
1444 SIVAL(p,0,0); /* Ensure any padding is null. */
1445 len = PTR_DIFF(p, pdata);
1446 len = (len + 3) & ~3;
1447 SIVAL(pdata,0,len);
1448 p = pdata + len;
1449 break;
1451 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1452 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1453 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1454 p += 4;
1455 SIVAL(p,0,reskey); p += 4;
1456 put_long_date(p,cdate); p += 8;
1457 put_long_date(p,adate); p += 8;
1458 put_long_date(p,mdate); p += 8;
1459 put_long_date(p,mdate); p += 8;
1460 SOFF_T(p,0,file_size); p += 8;
1461 SOFF_T(p,0,allocation_size); p += 8;
1462 SIVAL(p,0,nt_extmode); p += 4;
1463 q = p; p += 4; /* q is placeholder for name length */
1465 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1466 SIVAL(p,0,ea_size); /* Extended attributes */
1467 p +=4;
1469 /* Clear the short name buffer. This is
1470 * IMPORTANT as not doing so will trigger
1471 * a Win2k client bug. JRA.
1473 if (!was_8_3 && check_mangled_names) {
1474 pstring mangled_name;
1475 pstrcpy(mangled_name, fname);
1476 mangle_map(mangled_name,True,True,SNUM(conn));
1477 mangled_name[12] = 0;
1478 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1479 SSVAL(p, 0, len);
1480 if (len < 24) {
1481 memset(p + 2 + len,'\0',24 - len);
1483 SSVAL(p, 0, len);
1484 } else {
1485 memset(p,'\0',26);
1487 p += 26;
1488 SSVAL(p,0,0); p += 2; /* Reserved ? */
1489 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1490 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1491 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1492 SIVAL(q,0,len);
1493 p += len;
1494 SIVAL(p,0,0); /* Ensure any padding is null. */
1495 len = PTR_DIFF(p, pdata);
1496 len = (len + 3) & ~3;
1497 SIVAL(pdata,0,len);
1498 p = pdata + len;
1499 break;
1501 /* CIFS UNIX Extension. */
1503 case SMB_FIND_FILE_UNIX:
1504 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1505 p+= 4;
1506 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1508 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1509 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1510 p+= 8;
1512 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1513 p+= 8;
1515 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1516 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1517 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1518 p+= 24;
1520 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1521 SIVAL(p,4,0);
1522 p+= 8;
1524 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1525 SIVAL(p,4,0);
1526 p+= 8;
1528 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1529 p+= 4;
1531 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1532 SIVAL(p,4,0);
1533 p+= 8;
1535 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1536 SIVAL(p,4,0);
1537 p+= 8;
1539 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1540 p+= 8;
1542 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1543 SIVAL(p,4,0);
1544 p+= 8;
1546 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1547 SIVAL(p,4,0);
1548 p+= 8;
1550 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1551 p += len;
1552 SIVAL(p,0,0); /* Ensure any padding is null. */
1554 len = PTR_DIFF(p, pdata);
1555 len = (len + 3) & ~3;
1556 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1557 p = pdata + len;
1558 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1560 break;
1562 default:
1563 return(False);
1567 if (PTR_DIFF(p,pdata) > space_remaining) {
1568 /* Move the dirptr back to prev_dirpos */
1569 dptr_SeekDir(conn->dirptr, prev_dirpos);
1570 *out_of_space = True;
1571 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1572 return False; /* Not finished - just out of space */
1575 /* Setup the last entry pointer, as an offset from base_data */
1576 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1577 /* Advance the data pointer to the next slot */
1578 *ppdata = p;
1580 return(found);
1583 /****************************************************************************
1584 Reply to a TRANS2_FINDFIRST.
1585 ****************************************************************************/
1587 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1588 char **pparams, int total_params, char **ppdata, int total_data,
1589 unsigned int max_data_bytes)
1591 /* We must be careful here that we don't return more than the
1592 allowed number of data bytes. If this means returning fewer than
1593 maxentries then so be it. We assume that the redirector has
1594 enough room for the fixed number of parameter bytes it has
1595 requested. */
1596 char *params = *pparams;
1597 char *pdata = *ppdata;
1598 uint32 dirtype = SVAL(params,0);
1599 int maxentries = SVAL(params,2);
1600 uint16 findfirst_flags = SVAL(params,4);
1601 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1602 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1603 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1604 int info_level = SVAL(params,6);
1605 pstring directory;
1606 pstring mask;
1607 char *p;
1608 int last_entry_off=0;
1609 int dptr_num = -1;
1610 int numentries = 0;
1611 int i;
1612 BOOL finished = False;
1613 BOOL dont_descend = False;
1614 BOOL out_of_space = False;
1615 int space_remaining;
1616 BOOL bad_path = False;
1617 BOOL mask_contains_wcard = False;
1618 SMB_STRUCT_STAT sbuf;
1619 TALLOC_CTX *ea_ctx = NULL;
1620 struct ea_list *ea_list = NULL;
1621 NTSTATUS ntstatus = NT_STATUS_OK;
1623 if (total_params < 12) {
1624 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1627 *directory = *mask = 0;
1629 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1630 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1631 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1632 info_level, max_data_bytes));
1634 if (!maxentries) {
1635 /* W2K3 seems to treat zero as 1. */
1636 maxentries = 1;
1639 switch (info_level) {
1640 case SMB_FIND_INFO_STANDARD:
1641 case SMB_FIND_EA_SIZE:
1642 case SMB_FIND_EA_LIST:
1643 case SMB_FIND_FILE_DIRECTORY_INFO:
1644 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1645 case SMB_FIND_FILE_NAMES_INFO:
1646 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1647 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1648 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1649 break;
1650 case SMB_FIND_FILE_UNIX:
1651 if (!lp_unix_extensions())
1652 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1653 break;
1654 default:
1655 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1658 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1659 if (!NT_STATUS_IS_OK(ntstatus)) {
1660 return ERROR_NT(ntstatus);
1663 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1665 unix_convert(directory,conn,0,&bad_path,&sbuf);
1666 if (bad_path) {
1667 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1669 if(!check_name(directory,conn)) {
1670 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1673 p = strrchr_m(directory,'/');
1674 if(p == NULL) {
1675 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1676 if((directory[0] == '.') && (directory[1] == '\0')) {
1677 pstrcpy(mask,"*");
1678 mask_contains_wcard = True;
1679 } else {
1680 pstrcpy(mask,directory);
1682 pstrcpy(directory,"./");
1683 } else {
1684 pstrcpy(mask,p+1);
1685 *p = 0;
1688 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1690 if (info_level == SMB_FIND_EA_LIST) {
1691 uint32 ea_size;
1693 if (total_data < 4) {
1694 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1697 ea_size = IVAL(pdata,0);
1698 if (ea_size != total_data) {
1699 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1700 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1701 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1704 if (!lp_ea_support(SNUM(conn))) {
1705 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1708 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1709 return ERROR_NT(NT_STATUS_NO_MEMORY);
1712 /* Pull out the list of names. */
1713 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1714 if (!ea_list) {
1715 talloc_destroy(ea_ctx);
1716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1720 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1721 if( pdata == NULL ) {
1722 talloc_destroy(ea_ctx);
1723 return ERROR_NT(NT_STATUS_NO_MEMORY);
1726 *ppdata = pdata;
1728 /* Realloc the params space */
1729 params = SMB_REALLOC(*pparams, 10);
1730 if (params == NULL) {
1731 talloc_destroy(ea_ctx);
1732 return ERROR_NT(NT_STATUS_NO_MEMORY);
1734 *pparams = params;
1736 /* Save the wildcard match and attribs we are using on this directory -
1737 needed as lanman2 assumes these are being saved between calls */
1739 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1740 if (dptr_num < 0) {
1741 talloc_destroy(ea_ctx);
1742 return(UNIXERROR(ERRDOS,ERRbadfile));
1745 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1747 /* We don't need to check for VOL here as this is returned by
1748 a different TRANS2 call. */
1750 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1751 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1752 dont_descend = True;
1754 p = pdata;
1755 space_remaining = max_data_bytes;
1756 out_of_space = False;
1758 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1759 BOOL got_exact_match = False;
1761 /* this is a heuristic to avoid seeking the dirptr except when
1762 absolutely necessary. It allows for a filename of about 40 chars */
1763 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1764 out_of_space = True;
1765 finished = False;
1766 } else {
1767 finished = !get_lanman2_dir_entry(conn,
1768 inbuf, outbuf,
1769 mask,dirtype,info_level,
1770 requires_resume_key,dont_descend,
1771 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1772 &last_entry_off, ea_list, ea_ctx);
1775 if (finished && out_of_space)
1776 finished = False;
1778 if (!finished && !out_of_space)
1779 numentries++;
1782 * As an optimisation if we know we aren't looking
1783 * for a wildcard name (ie. the name matches the wildcard exactly)
1784 * then we can finish on any (first) match.
1785 * This speeds up large directory searches. JRA.
1788 if(got_exact_match)
1789 finished = True;
1791 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1794 talloc_destroy(ea_ctx);
1796 /* Check if we can close the dirptr */
1797 if(close_after_first || (finished && close_if_end)) {
1798 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1799 dptr_close(&dptr_num);
1803 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1804 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1805 * the protocol level is less than NT1. Tested with smbclient. JRA.
1806 * This should fix the OS/2 client bug #2335.
1809 if(numentries == 0) {
1810 dptr_close(&dptr_num);
1811 if (Protocol < PROTOCOL_NT1) {
1812 return ERROR_DOS(ERRDOS,ERRnofiles);
1813 } else {
1814 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1818 /* At this point pdata points to numentries directory entries. */
1820 /* Set up the return parameter block */
1821 SSVAL(params,0,dptr_num);
1822 SSVAL(params,2,numentries);
1823 SSVAL(params,4,finished);
1824 SSVAL(params,6,0); /* Never an EA error */
1825 SSVAL(params,8,last_entry_off);
1827 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1829 if ((! *directory) && dptr_path(dptr_num))
1830 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1832 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1833 smb_fn_name(CVAL(inbuf,smb_com)),
1834 mask, directory, dirtype, numentries ) );
1837 * Force a name mangle here to ensure that the
1838 * mask as an 8.3 name is top of the mangled cache.
1839 * The reasons for this are subtle. Don't remove
1840 * this code unless you know what you are doing
1841 * (see PR#13758). JRA.
1844 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1845 mangle_map(mask, True, True, SNUM(conn));
1847 return(-1);
1850 /****************************************************************************
1851 Reply to a TRANS2_FINDNEXT.
1852 ****************************************************************************/
1854 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1855 char **pparams, int total_params, char **ppdata, int total_data,
1856 unsigned int max_data_bytes)
1858 /* We must be careful here that we don't return more than the
1859 allowed number of data bytes. If this means returning fewer than
1860 maxentries then so be it. We assume that the redirector has
1861 enough room for the fixed number of parameter bytes it has
1862 requested. */
1863 char *params = *pparams;
1864 char *pdata = *ppdata;
1865 int dptr_num = SVAL(params,0);
1866 int maxentries = SVAL(params,2);
1867 uint16 info_level = SVAL(params,4);
1868 uint32 resume_key = IVAL(params,6);
1869 uint16 findnext_flags = SVAL(params,10);
1870 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1871 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1872 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1873 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1874 BOOL mask_contains_wcard = False;
1875 pstring resume_name;
1876 pstring mask;
1877 pstring directory;
1878 char *p;
1879 uint16 dirtype;
1880 int numentries = 0;
1881 int i, last_entry_off=0;
1882 BOOL finished = False;
1883 BOOL dont_descend = False;
1884 BOOL out_of_space = False;
1885 int space_remaining;
1886 TALLOC_CTX *ea_ctx = NULL;
1887 struct ea_list *ea_list = NULL;
1888 NTSTATUS ntstatus = NT_STATUS_OK;
1890 if (total_params < 12) {
1891 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1894 *mask = *directory = *resume_name = 0;
1896 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1897 if (!NT_STATUS_IS_OK(ntstatus)) {
1898 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1899 complain (it thinks we're asking for the directory above the shared
1900 path or an invalid name). Catch this as the resume name is only compared, never used in
1901 a file access. JRA. */
1902 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1903 pstrcpy(resume_name, "..");
1904 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1905 pstrcpy(resume_name, ".");
1906 } else {
1907 return ERROR_NT(ntstatus);
1911 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1912 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1913 resume_key = %d resume name = %s continue=%d level = %d\n",
1914 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1915 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1917 if (!maxentries) {
1918 /* W2K3 seems to treat zero as 1. */
1919 maxentries = 1;
1922 switch (info_level) {
1923 case SMB_FIND_INFO_STANDARD:
1924 case SMB_FIND_EA_SIZE:
1925 case SMB_FIND_EA_LIST:
1926 case SMB_FIND_FILE_DIRECTORY_INFO:
1927 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1928 case SMB_FIND_FILE_NAMES_INFO:
1929 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1930 break;
1931 case SMB_FIND_FILE_UNIX:
1932 if (!lp_unix_extensions())
1933 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1934 break;
1935 default:
1936 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1939 if (info_level == SMB_FIND_EA_LIST) {
1940 uint32 ea_size;
1942 if (total_data < 4) {
1943 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1946 ea_size = IVAL(pdata,0);
1947 if (ea_size != total_data) {
1948 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1949 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1950 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1953 if (!lp_ea_support(SNUM(conn))) {
1954 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1957 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1958 return ERROR_NT(NT_STATUS_NO_MEMORY);
1961 /* Pull out the list of names. */
1962 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1963 if (!ea_list) {
1964 talloc_destroy(ea_ctx);
1965 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1969 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1970 if(pdata == NULL) {
1971 talloc_destroy(ea_ctx);
1972 return ERROR_NT(NT_STATUS_NO_MEMORY);
1975 *ppdata = pdata;
1977 /* Realloc the params space */
1978 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1979 if( params == NULL ) {
1980 talloc_destroy(ea_ctx);
1981 return ERROR_NT(NT_STATUS_NO_MEMORY);
1984 *pparams = params;
1986 /* Check that the dptr is valid */
1987 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1988 talloc_destroy(ea_ctx);
1989 return ERROR_DOS(ERRDOS,ERRnofiles);
1992 string_set(&conn->dirpath,dptr_path(dptr_num));
1994 /* Get the wildcard mask from the dptr */
1995 if((p = dptr_wcard(dptr_num))== NULL) {
1996 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1997 talloc_destroy(ea_ctx);
1998 return ERROR_DOS(ERRDOS,ERRnofiles);
2001 pstrcpy(mask, p);
2002 pstrcpy(directory,conn->dirpath);
2004 /* Get the attr mask from the dptr */
2005 dirtype = dptr_attr(dptr_num);
2007 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2008 dptr_num, mask, dirtype,
2009 (long)conn->dirptr,
2010 dptr_TellDir(conn->dirptr)));
2012 /* We don't need to check for VOL here as this is returned by
2013 a different TRANS2 call. */
2015 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2016 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2017 dont_descend = True;
2019 p = pdata;
2020 space_remaining = max_data_bytes;
2021 out_of_space = False;
2024 * Seek to the correct position. We no longer use the resume key but
2025 * depend on the last file name instead.
2028 if(*resume_name && !continue_bit) {
2029 SMB_STRUCT_STAT st;
2031 long current_pos = 0;
2033 * Remember, mangle_map is called by
2034 * get_lanman2_dir_entry(), so the resume name
2035 * could be mangled. Ensure we check the unmangled name.
2038 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2039 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2043 * Fix for NT redirector problem triggered by resume key indexes
2044 * changing between directory scans. We now return a resume key of 0
2045 * and instead look for the filename to continue from (also given
2046 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2047 * findfirst/findnext (as is usual) then the directory pointer
2048 * should already be at the correct place.
2051 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2052 } /* end if resume_name && !continue_bit */
2054 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2055 BOOL got_exact_match = False;
2057 /* this is a heuristic to avoid seeking the dirptr except when
2058 absolutely necessary. It allows for a filename of about 40 chars */
2059 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2060 out_of_space = True;
2061 finished = False;
2062 } else {
2063 finished = !get_lanman2_dir_entry(conn,
2064 inbuf, outbuf,
2065 mask,dirtype,info_level,
2066 requires_resume_key,dont_descend,
2067 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2068 &last_entry_off, ea_list, ea_ctx);
2071 if (finished && out_of_space)
2072 finished = False;
2074 if (!finished && !out_of_space)
2075 numentries++;
2078 * As an optimisation if we know we aren't looking
2079 * for a wildcard name (ie. the name matches the wildcard exactly)
2080 * then we can finish on any (first) match.
2081 * This speeds up large directory searches. JRA.
2084 if(got_exact_match)
2085 finished = True;
2087 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2090 talloc_destroy(ea_ctx);
2092 /* Check if we can close the dirptr */
2093 if(close_after_request || (finished && close_if_end)) {
2094 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2095 dptr_close(&dptr_num); /* This frees up the saved mask */
2098 /* Set up the return parameter block */
2099 SSVAL(params,0,numentries);
2100 SSVAL(params,2,finished);
2101 SSVAL(params,4,0); /* Never an EA error */
2102 SSVAL(params,6,last_entry_off);
2104 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2106 if ((! *directory) && dptr_path(dptr_num))
2107 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2109 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2110 smb_fn_name(CVAL(inbuf,smb_com)),
2111 mask, directory, dirtype, numentries ) );
2113 return(-1);
2116 /****************************************************************************
2117 Reply to a TRANS2_QFSINFO (query filesystem info).
2118 ****************************************************************************/
2120 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2121 char **pparams, int total_params, char **ppdata, int total_data,
2122 unsigned int max_data_bytes)
2124 char *pdata = *ppdata;
2125 char *params = *pparams;
2126 uint16 info_level = SVAL(params,0);
2127 int data_len, len;
2128 SMB_STRUCT_STAT st;
2129 char *vname = volume_label(SNUM(conn));
2130 int snum = SNUM(conn);
2131 char *fstype = lp_fstype(SNUM(conn));
2132 int quota_flag = 0;
2134 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2136 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2137 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2138 return ERROR_DOS(ERRSRV,ERRinvdevice);
2141 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2142 if ( pdata == NULL ) {
2143 return ERROR_NT(NT_STATUS_NO_MEMORY);
2146 *ppdata = pdata;
2147 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2149 switch (info_level) {
2150 case SMB_INFO_ALLOCATION:
2152 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2153 data_len = 18;
2154 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2155 return(UNIXERROR(ERRHRD,ERRgeneral));
2158 block_size = lp_block_size(snum);
2159 if (bsize < block_size) {
2160 SMB_BIG_UINT factor = block_size/bsize;
2161 bsize = block_size;
2162 dsize /= factor;
2163 dfree /= factor;
2165 if (bsize > block_size) {
2166 SMB_BIG_UINT factor = bsize/block_size;
2167 bsize = block_size;
2168 dsize *= factor;
2169 dfree *= factor;
2171 bytes_per_sector = 512;
2172 sectors_per_unit = bsize/bytes_per_sector;
2174 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2175 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2176 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2178 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2179 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2180 SIVAL(pdata,l1_cUnit,dsize);
2181 SIVAL(pdata,l1_cUnitAvail,dfree);
2182 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2183 break;
2186 case SMB_INFO_VOLUME:
2187 /* Return volume name */
2189 * Add volume serial number - hash of a combination of
2190 * the called hostname and the service name.
2192 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2194 * Win2k3 and previous mess this up by sending a name length
2195 * one byte short. I believe only older clients (OS/2 Win9x) use
2196 * this call so try fixing this by adding a terminating null to
2197 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2199 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2200 SCVAL(pdata,l2_vol_cch,len);
2201 data_len = l2_vol_szVolLabel + len;
2202 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2203 (unsigned)st.st_ctime, len, vname));
2204 break;
2206 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2207 case SMB_FS_ATTRIBUTE_INFORMATION:
2210 #if defined(HAVE_SYS_QUOTAS)
2211 quota_flag = FILE_VOLUME_QUOTAS;
2212 #endif
2214 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2215 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2216 quota_flag); /* FS ATTRIBUTES */
2218 SIVAL(pdata,4,255); /* Max filename component length */
2219 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2220 and will think we can't do long filenames */
2221 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2222 SIVAL(pdata,8,len);
2223 data_len = 12 + len;
2224 break;
2226 case SMB_QUERY_FS_LABEL_INFO:
2227 case SMB_FS_LABEL_INFORMATION:
2228 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2229 data_len = 4 + len;
2230 SIVAL(pdata,0,len);
2231 break;
2233 case SMB_QUERY_FS_VOLUME_INFO:
2234 case SMB_FS_VOLUME_INFORMATION:
2237 * Add volume serial number - hash of a combination of
2238 * the called hostname and the service name.
2240 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2241 (str_checksum(get_local_machine_name())<<16));
2243 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2244 SIVAL(pdata,12,len);
2245 data_len = 18+len;
2246 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2247 (int)strlen(vname),vname, lp_servicename(snum)));
2248 break;
2250 case SMB_QUERY_FS_SIZE_INFO:
2251 case SMB_FS_SIZE_INFORMATION:
2253 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2254 data_len = 24;
2255 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2256 return(UNIXERROR(ERRHRD,ERRgeneral));
2258 block_size = lp_block_size(snum);
2259 if (bsize < block_size) {
2260 SMB_BIG_UINT factor = block_size/bsize;
2261 bsize = block_size;
2262 dsize /= factor;
2263 dfree /= factor;
2265 if (bsize > block_size) {
2266 SMB_BIG_UINT factor = bsize/block_size;
2267 bsize = block_size;
2268 dsize *= factor;
2269 dfree *= factor;
2271 bytes_per_sector = 512;
2272 sectors_per_unit = bsize/bytes_per_sector;
2273 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2274 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2275 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2276 SBIG_UINT(pdata,0,dsize);
2277 SBIG_UINT(pdata,8,dfree);
2278 SIVAL(pdata,16,sectors_per_unit);
2279 SIVAL(pdata,20,bytes_per_sector);
2280 break;
2283 case SMB_FS_FULL_SIZE_INFORMATION:
2285 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2286 data_len = 32;
2287 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2288 return(UNIXERROR(ERRHRD,ERRgeneral));
2290 block_size = lp_block_size(snum);
2291 if (bsize < block_size) {
2292 SMB_BIG_UINT factor = block_size/bsize;
2293 bsize = block_size;
2294 dsize /= factor;
2295 dfree /= factor;
2297 if (bsize > block_size) {
2298 SMB_BIG_UINT factor = bsize/block_size;
2299 bsize = block_size;
2300 dsize *= factor;
2301 dfree *= factor;
2303 bytes_per_sector = 512;
2304 sectors_per_unit = bsize/bytes_per_sector;
2305 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2306 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2307 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2308 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2309 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2310 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2311 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2312 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2313 break;
2316 case SMB_QUERY_FS_DEVICE_INFO:
2317 case SMB_FS_DEVICE_INFORMATION:
2318 data_len = 8;
2319 SIVAL(pdata,0,0); /* dev type */
2320 SIVAL(pdata,4,0); /* characteristics */
2321 break;
2323 #ifdef HAVE_SYS_QUOTAS
2324 case SMB_FS_QUOTA_INFORMATION:
2326 * what we have to send --metze:
2328 * Unknown1: 24 NULL bytes
2329 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2330 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2331 * Quota Flags: 2 byte :
2332 * Unknown3: 6 NULL bytes
2334 * 48 bytes total
2336 * details for Quota Flags:
2338 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2339 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2340 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2341 * 0x0001 Enable Quotas: enable quota for this fs
2345 /* we need to fake up a fsp here,
2346 * because its not send in this call
2348 files_struct fsp;
2349 SMB_NTQUOTA_STRUCT quotas;
2351 ZERO_STRUCT(fsp);
2352 ZERO_STRUCT(quotas);
2354 fsp.conn = conn;
2355 fsp.fnum = -1;
2357 /* access check */
2358 if (current_user.uid != 0) {
2359 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2360 lp_servicename(SNUM(conn)),conn->user));
2361 return ERROR_DOS(ERRDOS,ERRnoaccess);
2364 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2365 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2366 return ERROR_DOS(ERRSRV,ERRerror);
2369 data_len = 48;
2371 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2373 /* Unknown1 24 NULL bytes*/
2374 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2375 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2376 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2378 /* Default Soft Quota 8 bytes */
2379 SBIG_UINT(pdata,24,quotas.softlim);
2381 /* Default Hard Quota 8 bytes */
2382 SBIG_UINT(pdata,32,quotas.hardlim);
2384 /* Quota flag 2 bytes */
2385 SSVAL(pdata,40,quotas.qflags);
2387 /* Unknown3 6 NULL bytes */
2388 SSVAL(pdata,42,0);
2389 SIVAL(pdata,44,0);
2391 break;
2393 #endif /* HAVE_SYS_QUOTAS */
2394 case SMB_FS_OBJECTID_INFORMATION:
2395 data_len = 64;
2396 break;
2399 * Query the version and capabilities of the CIFS UNIX extensions
2400 * in use.
2403 case SMB_QUERY_CIFS_UNIX_INFO:
2404 if (!lp_unix_extensions())
2405 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2406 data_len = 12;
2407 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2408 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2409 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2410 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2411 break;
2413 case SMB_QUERY_POSIX_FS_INFO:
2415 int rc;
2416 vfs_statvfs_struct svfs;
2418 if (!lp_unix_extensions())
2419 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2421 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2423 if (!rc) {
2424 data_len = 56;
2425 SIVAL(pdata,0,svfs.OptimalTransferSize);
2426 SIVAL(pdata,4,svfs.BlockSize);
2427 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2428 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2429 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2430 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2431 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2432 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2433 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2434 #ifdef EOPNOTSUPP
2435 } else if (rc == EOPNOTSUPP) {
2436 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2437 #endif /* EOPNOTSUPP */
2438 } else {
2439 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2440 return ERROR_DOS(ERRSRV,ERRerror);
2442 break;
2445 case SMB_MAC_QUERY_FS_INFO:
2447 * Thursby MAC extension... ONLY on NTFS filesystems
2448 * once we do streams then we don't need this
2450 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2451 data_len = 88;
2452 SIVAL(pdata,84,0x100); /* Don't support mac... */
2453 break;
2455 /* drop through */
2456 default:
2457 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2461 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2463 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2465 return -1;
2468 /****************************************************************************
2469 Reply to a TRANS2_SETFSINFO (set filesystem info).
2470 ****************************************************************************/
2472 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2473 char **pparams, int total_params, char **ppdata, int total_data,
2474 unsigned int max_data_bytes)
2476 char *pdata = *ppdata;
2477 char *params = *pparams;
2478 uint16 info_level;
2479 int outsize;
2481 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2483 /* */
2484 if (total_params < 4) {
2485 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2486 total_params));
2487 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2490 info_level = SVAL(params,2);
2492 switch(info_level) {
2493 case SMB_SET_CIFS_UNIX_INFO:
2495 uint16 client_unix_major;
2496 uint16 client_unix_minor;
2497 uint32 client_unix_cap_low;
2498 uint32 client_unix_cap_high;
2500 if (!lp_unix_extensions()) {
2501 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2504 /* There should be 12 bytes of capabilities set. */
2505 if (total_data < 8) {
2506 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2508 client_unix_major = SVAL(pdata,0);
2509 client_unix_minor = SVAL(pdata,2);
2510 client_unix_cap_low = IVAL(pdata,4);
2511 client_unix_cap_high = IVAL(pdata,8);
2512 /* Just print these values for now. */
2513 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2514 cap_low = 0x%x, cap_high = 0x%x\n",
2515 (unsigned int)client_unix_major,
2516 (unsigned int)client_unix_minor,
2517 (unsigned int)client_unix_cap_low,
2518 (unsigned int)client_unix_cap_high ));
2520 /* Here is where we must switch to posix pathname processing... */
2521 lp_set_posix_pathnames();
2522 mangle_change_to_posix();
2523 break;
2525 case SMB_FS_QUOTA_INFORMATION:
2527 files_struct *fsp = NULL;
2528 SMB_NTQUOTA_STRUCT quotas;
2530 ZERO_STRUCT(quotas);
2532 /* access check */
2533 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2534 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2535 lp_servicename(SNUM(conn)),conn->user));
2536 return ERROR_DOS(ERRSRV,ERRaccess);
2539 /* note: normaly there're 48 bytes,
2540 * but we didn't use the last 6 bytes for now
2541 * --metze
2543 fsp = file_fsp(params,0);
2544 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2545 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2546 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2549 if (total_data < 42) {
2550 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2551 total_data));
2552 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2555 /* unknown_1 24 NULL bytes in pdata*/
2557 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2558 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2559 #ifdef LARGE_SMB_OFF_T
2560 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2561 #else /* LARGE_SMB_OFF_T */
2562 if ((IVAL(pdata,28) != 0)&&
2563 ((quotas.softlim != 0xFFFFFFFF)||
2564 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2565 /* more than 32 bits? */
2566 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2568 #endif /* LARGE_SMB_OFF_T */
2570 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2571 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2572 #ifdef LARGE_SMB_OFF_T
2573 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2574 #else /* LARGE_SMB_OFF_T */
2575 if ((IVAL(pdata,36) != 0)&&
2576 ((quotas.hardlim != 0xFFFFFFFF)||
2577 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2578 /* more than 32 bits? */
2579 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2581 #endif /* LARGE_SMB_OFF_T */
2583 /* quota_flags 2 bytes **/
2584 quotas.qflags = SVAL(pdata,40);
2586 /* unknown_2 6 NULL bytes follow*/
2588 /* now set the quotas */
2589 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2590 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2591 return ERROR_DOS(ERRSRV,ERRerror);
2594 break;
2596 default:
2597 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2598 info_level));
2599 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2600 break;
2604 * sending this reply works fine,
2605 * but I'm not sure it's the same
2606 * like windows do...
2607 * --metze
2609 outsize = set_message(outbuf,10,0,True);
2611 return outsize;
2614 /****************************************************************************
2615 Utility function to set bad path error.
2616 ****************************************************************************/
2618 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2620 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2621 err, (int)bad_path ));
2623 if(err == ENOENT) {
2624 if (bad_path) {
2625 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2626 } else {
2627 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2630 return UNIXERROR(def_class,def_code);
2633 #if defined(HAVE_POSIX_ACLS)
2634 /****************************************************************************
2635 Utility function to count the number of entries in a POSIX acl.
2636 ****************************************************************************/
2638 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2640 unsigned int ace_count = 0;
2641 int entry_id = SMB_ACL_FIRST_ENTRY;
2642 SMB_ACL_ENTRY_T entry;
2644 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2645 /* get_next... */
2646 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2647 entry_id = SMB_ACL_NEXT_ENTRY;
2649 ace_count++;
2651 return ace_count;
2654 /****************************************************************************
2655 Utility function to marshall a POSIX acl into wire format.
2656 ****************************************************************************/
2658 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2660 int entry_id = SMB_ACL_FIRST_ENTRY;
2661 SMB_ACL_ENTRY_T entry;
2663 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2664 SMB_ACL_TAG_T tagtype;
2665 SMB_ACL_PERMSET_T permset;
2666 unsigned char perms = 0;
2667 unsigned int own_grp;
2669 /* get_next... */
2670 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2671 entry_id = SMB_ACL_NEXT_ENTRY;
2674 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2675 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2676 return False;
2679 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2680 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2681 return False;
2684 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2685 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2686 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2688 SCVAL(pdata,1,perms);
2690 switch (tagtype) {
2691 case SMB_ACL_USER_OBJ:
2692 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2693 own_grp = (unsigned int)pst->st_uid;
2694 SIVAL(pdata,2,own_grp);
2695 SIVAL(pdata,6,0);
2696 break;
2697 case SMB_ACL_USER:
2699 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2700 if (!puid) {
2701 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2703 own_grp = (unsigned int)*puid;
2704 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2705 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2706 SIVAL(pdata,2,own_grp);
2707 SIVAL(pdata,6,0);
2708 break;
2710 case SMB_ACL_GROUP_OBJ:
2711 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2712 own_grp = (unsigned int)pst->st_gid;
2713 SIVAL(pdata,2,own_grp);
2714 SIVAL(pdata,6,0);
2715 break;
2716 case SMB_ACL_GROUP:
2718 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2719 if (!pgid) {
2720 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2722 own_grp = (unsigned int)*pgid;
2723 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2724 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2725 SIVAL(pdata,2,own_grp);
2726 SIVAL(pdata,6,0);
2727 break;
2729 case SMB_ACL_MASK:
2730 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2731 SIVAL(pdata,2,0xFFFFFFFF);
2732 SIVAL(pdata,6,0xFFFFFFFF);
2733 break;
2734 case SMB_ACL_OTHER:
2735 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2736 SIVAL(pdata,2,0xFFFFFFFF);
2737 SIVAL(pdata,6,0xFFFFFFFF);
2738 break;
2739 default:
2740 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2741 return False;
2743 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2746 return True;
2748 #endif
2750 /****************************************************************************
2751 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2752 file name or file id).
2753 ****************************************************************************/
2755 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2756 unsigned int tran_call,
2757 char **pparams, int total_params, char **ppdata, int total_data,
2758 unsigned int max_data_bytes)
2760 char *params = *pparams;
2761 char *pdata = *ppdata;
2762 uint16 info_level;
2763 int mode=0;
2764 int nlink;
2765 SMB_OFF_T file_size=0;
2766 SMB_BIG_UINT allocation_size=0;
2767 unsigned int data_size = 0;
2768 unsigned int param_size = 2;
2769 SMB_STRUCT_STAT sbuf;
2770 pstring fname, dos_fname;
2771 char *fullpathname;
2772 char *base_name;
2773 char *p;
2774 SMB_OFF_T pos = 0;
2775 BOOL bad_path = False;
2776 BOOL delete_pending = False;
2777 int len;
2778 time_t c_time;
2779 files_struct *fsp = NULL;
2780 TALLOC_CTX *ea_ctx = NULL;
2781 struct ea_list *ea_list = NULL;
2782 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2784 if (!params)
2785 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2787 ZERO_STRUCT(sbuf);
2789 if (tran_call == TRANSACT2_QFILEINFO) {
2790 if (total_params < 4) {
2791 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2794 fsp = file_fsp(params,0);
2795 info_level = SVAL(params,2);
2797 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2799 if(fsp && (fsp->fake_file_handle)) {
2801 * This is actually for the QUOTA_FAKE_FILE --metze
2804 pstrcpy(fname, fsp->fsp_name);
2805 /* We know this name is ok, it's already passed the checks. */
2807 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2809 * This is actually a QFILEINFO on a directory
2810 * handle (returned from an NT SMB). NT5.0 seems
2811 * to do this call. JRA.
2813 /* We know this name is ok, it's already passed the checks. */
2814 pstrcpy(fname, fsp->fsp_name);
2816 if (INFO_LEVEL_IS_UNIX(info_level)) {
2817 /* Always do lstat for UNIX calls. */
2818 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2819 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2820 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2822 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2823 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2824 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2827 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2828 } else {
2830 * Original code - this is an open file.
2832 CHECK_FSP(fsp,conn);
2834 pstrcpy(fname, fsp->fsp_name);
2835 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2836 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2837 return(UNIXERROR(ERRDOS,ERRbadfid));
2839 pos = fsp->fh->position_information;
2840 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2841 access_mask = fsp->access_mask;
2843 } else {
2844 NTSTATUS status = NT_STATUS_OK;
2846 /* qpathinfo */
2847 if (total_params < 6) {
2848 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2851 info_level = SVAL(params,0);
2853 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2855 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2856 if (!NT_STATUS_IS_OK(status)) {
2857 return ERROR_NT(status);
2860 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2862 unix_convert(fname,conn,0,&bad_path,&sbuf);
2863 if (bad_path) {
2864 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2866 if (!check_name(fname,conn)) {
2867 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2868 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2871 if (INFO_LEVEL_IS_UNIX(info_level)) {
2872 /* Always do lstat for UNIX calls. */
2873 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2874 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2875 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2878 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2879 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2882 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2883 if (delete_pending) {
2884 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2888 nlink = sbuf.st_nlink;
2890 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2891 /* NTFS does not seem to count ".." */
2892 nlink -= 1;
2895 if ((nlink > 0) && delete_pending) {
2896 nlink -= 1;
2899 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2900 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2902 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2903 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2905 p = strrchr_m(fname,'/');
2906 if (!p)
2907 base_name = fname;
2908 else
2909 base_name = p+1;
2911 mode = dos_mode(conn,fname,&sbuf);
2912 if (!mode)
2913 mode = FILE_ATTRIBUTE_NORMAL;
2915 fullpathname = fname;
2916 file_size = get_file_size(sbuf);
2917 if (mode & aDIR) {
2918 /* This is necessary, as otherwise the desktop.ini file in
2919 * this folder is ignored */
2920 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2921 file_size = 0;
2924 /* Pull any EA list from the data portion. */
2925 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2926 uint32 ea_size;
2928 if (total_data < 4) {
2929 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2931 ea_size = IVAL(pdata,0);
2933 if (total_data > 0 && ea_size != total_data) {
2934 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2935 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2936 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2939 if (!lp_ea_support(SNUM(conn))) {
2940 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2943 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2944 return ERROR_NT(NT_STATUS_NO_MEMORY);
2947 /* Pull out the list of names. */
2948 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2949 if (!ea_list) {
2950 talloc_destroy(ea_ctx);
2951 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2955 params = SMB_REALLOC(*pparams,2);
2956 if (params == NULL) {
2957 talloc_destroy(ea_ctx);
2958 return ERROR_NT(NT_STATUS_NO_MEMORY);
2960 *pparams = params;
2961 SSVAL(params,0,0);
2962 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2963 pdata = SMB_REALLOC(*ppdata, data_size);
2964 if ( pdata == NULL ) {
2965 talloc_destroy(ea_ctx);
2966 return ERROR_NT(NT_STATUS_NO_MEMORY);
2968 *ppdata = pdata;
2970 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2972 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2974 if (fsp) {
2975 if (fsp->pending_modtime) {
2976 /* the pending modtime overrides the current modtime */
2977 sbuf.st_mtime = fsp->pending_modtime;
2979 } else {
2980 /* Do we have this path open ? */
2981 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2982 if (fsp1 && fsp1->pending_modtime) {
2983 /* the pending modtime overrides the current modtime */
2984 sbuf.st_mtime = fsp1->pending_modtime;
2986 if (fsp1 && fsp1->initial_allocation_size) {
2987 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2991 if (lp_dos_filetime_resolution(SNUM(conn))) {
2992 c_time &= ~1;
2993 sbuf.st_atime &= ~1;
2994 sbuf.st_ctime &= ~1;
2995 sbuf.st_mtime &= ~1;
2998 /* NT expects the name to be in an exact form of the *full*
2999 filename. See the trans2 torture test */
3000 if (strequal(base_name,".")) {
3001 pstrcpy(dos_fname, "\\");
3002 } else {
3003 pstr_sprintf(dos_fname, "\\%s", fname);
3004 string_replace(dos_fname, '/', '\\');
3007 switch (info_level) {
3008 case SMB_INFO_STANDARD:
3009 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3010 data_size = 22;
3011 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3012 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3013 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3014 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3015 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3016 SSVAL(pdata,l1_attrFile,mode);
3017 break;
3019 case SMB_INFO_QUERY_EA_SIZE:
3021 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3022 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3023 data_size = 26;
3024 srv_put_dos_date2(pdata,0,c_time);
3025 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3026 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3027 SIVAL(pdata,12,(uint32)file_size);
3028 SIVAL(pdata,16,(uint32)allocation_size);
3029 SSVAL(pdata,20,mode);
3030 SIVAL(pdata,22,ea_size);
3031 break;
3034 case SMB_INFO_IS_NAME_VALID:
3035 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3036 if (tran_call == TRANSACT2_QFILEINFO) {
3037 /* os/2 needs this ? really ?*/
3038 return ERROR_DOS(ERRDOS,ERRbadfunc);
3040 data_size = 0;
3041 param_size = 0;
3042 break;
3044 case SMB_INFO_QUERY_EAS_FROM_LIST:
3046 size_t total_ea_len = 0;
3047 struct ea_list *ea_file_list = NULL;
3049 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3051 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3052 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3054 if (!ea_list || (total_ea_len > data_size)) {
3055 talloc_destroy(ea_ctx);
3056 data_size = 4;
3057 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3058 break;
3061 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3062 talloc_destroy(ea_ctx);
3063 break;
3066 case SMB_INFO_QUERY_ALL_EAS:
3068 /* We have data_size bytes to put EA's into. */
3069 size_t total_ea_len = 0;
3071 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3073 ea_ctx = talloc_init("ea_ctx");
3074 if (!ea_ctx) {
3075 return ERROR_NT(NT_STATUS_NO_MEMORY);
3078 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3079 if (!ea_list || (total_ea_len > data_size)) {
3080 talloc_destroy(ea_ctx);
3081 data_size = 4;
3082 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3083 break;
3086 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3087 talloc_destroy(ea_ctx);
3088 break;
3091 case SMB_FILE_BASIC_INFORMATION:
3092 case SMB_QUERY_FILE_BASIC_INFO:
3094 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3095 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3096 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3097 } else {
3098 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3099 data_size = 40;
3100 SIVAL(pdata,36,0);
3102 put_long_date(pdata,c_time);
3103 put_long_date(pdata+8,sbuf.st_atime);
3104 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3105 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3106 SIVAL(pdata,32,mode);
3108 DEBUG(5,("SMB_QFBI - "));
3110 time_t create_time = c_time;
3111 DEBUG(5,("create: %s ", ctime(&create_time)));
3113 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3114 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3115 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3116 DEBUG(5,("mode: %x\n", mode));
3117 break;
3119 case SMB_FILE_STANDARD_INFORMATION:
3120 case SMB_QUERY_FILE_STANDARD_INFO:
3122 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3123 data_size = 24;
3124 SOFF_T(pdata,0,allocation_size);
3125 SOFF_T(pdata,8,file_size);
3126 SIVAL(pdata,16,nlink);
3127 SCVAL(pdata,20,delete_pending?1:0);
3128 SCVAL(pdata,21,(mode&aDIR)?1:0);
3129 SSVAL(pdata,22,0); /* Padding. */
3130 break;
3132 case SMB_FILE_EA_INFORMATION:
3133 case SMB_QUERY_FILE_EA_INFO:
3135 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3136 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3137 data_size = 4;
3138 SIVAL(pdata,0,ea_size);
3139 break;
3142 /* Get the 8.3 name - used if NT SMB was negotiated. */
3143 case SMB_QUERY_FILE_ALT_NAME_INFO:
3144 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3146 pstring short_name;
3148 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3149 pstrcpy(short_name,base_name);
3150 /* Mangle if not already 8.3 */
3151 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3152 mangle_map(short_name,True,True,SNUM(conn));
3154 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3155 data_size = 4 + len;
3156 SIVAL(pdata,0,len);
3157 break;
3160 case SMB_QUERY_FILE_NAME_INFO:
3162 this must be *exactly* right for ACLs on mapped drives to work
3164 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3165 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3166 data_size = 4 + len;
3167 SIVAL(pdata,0,len);
3168 break;
3170 case SMB_FILE_ALLOCATION_INFORMATION:
3171 case SMB_QUERY_FILE_ALLOCATION_INFO:
3172 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3173 data_size = 8;
3174 SOFF_T(pdata,0,allocation_size);
3175 break;
3177 case SMB_FILE_END_OF_FILE_INFORMATION:
3178 case SMB_QUERY_FILE_END_OF_FILEINFO:
3179 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3180 data_size = 8;
3181 SOFF_T(pdata,0,file_size);
3182 break;
3184 case SMB_QUERY_FILE_ALL_INFO:
3185 case SMB_FILE_ALL_INFORMATION:
3187 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3188 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3189 put_long_date(pdata,c_time);
3190 put_long_date(pdata+8,sbuf.st_atime);
3191 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3192 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3193 SIVAL(pdata,32,mode);
3194 SIVAL(pdata,36,0); /* padding. */
3195 pdata += 40;
3196 SOFF_T(pdata,0,allocation_size);
3197 SOFF_T(pdata,8,file_size);
3198 SIVAL(pdata,16,nlink);
3199 SCVAL(pdata,20,delete_pending);
3200 SCVAL(pdata,21,(mode&aDIR)?1:0);
3201 SSVAL(pdata,22,0);
3202 pdata += 24;
3203 SIVAL(pdata,0,ea_size);
3204 pdata += 4; /* EA info */
3205 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3206 SIVAL(pdata,0,len);
3207 pdata += 4 + len;
3208 data_size = PTR_DIFF(pdata,(*ppdata));
3209 break;
3211 case SMB_FILE_INTERNAL_INFORMATION:
3212 /* This should be an index number - looks like
3213 dev/ino to me :-)
3215 I think this causes us to fail the IFSKIT
3216 BasicFileInformationTest. -tpot */
3218 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3219 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3220 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3221 data_size = 8;
3222 break;
3224 case SMB_FILE_ACCESS_INFORMATION:
3225 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3226 SIVAL(pdata,0,access_mask);
3227 data_size = 4;
3228 break;
3230 case SMB_FILE_NAME_INFORMATION:
3231 /* Pathname with leading '\'. */
3233 size_t byte_len;
3234 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3235 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3236 SIVAL(pdata,0,byte_len);
3237 data_size = 4 + byte_len;
3238 break;
3241 case SMB_FILE_DISPOSITION_INFORMATION:
3242 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3243 data_size = 1;
3244 SCVAL(pdata,0,delete_pending);
3245 break;
3247 case SMB_FILE_POSITION_INFORMATION:
3248 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3249 data_size = 8;
3250 SOFF_T(pdata,0,pos);
3251 break;
3253 case SMB_FILE_MODE_INFORMATION:
3254 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3255 SIVAL(pdata,0,mode);
3256 data_size = 4;
3257 break;
3259 case SMB_FILE_ALIGNMENT_INFORMATION:
3260 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3261 SIVAL(pdata,0,0); /* No alignment needed. */
3262 data_size = 4;
3263 break;
3265 #if 0
3267 * NT4 server just returns "invalid query" to this - if we try to answer
3268 * it then NTws gets a BSOD! (tridge).
3269 * W2K seems to want this. JRA.
3271 case SMB_QUERY_FILE_STREAM_INFO:
3272 #endif
3273 case SMB_FILE_STREAM_INFORMATION:
3274 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3275 if (mode & aDIR) {
3276 data_size = 0;
3277 } else {
3278 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3279 SIVAL(pdata,0,0); /* ??? */
3280 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3281 SOFF_T(pdata,8,file_size);
3282 SIVAL(pdata,16,allocation_size);
3283 SIVAL(pdata,20,0); /* ??? */
3284 data_size = 24 + byte_len;
3286 break;
3288 case SMB_QUERY_COMPRESSION_INFO:
3289 case SMB_FILE_COMPRESSION_INFORMATION:
3290 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3291 SOFF_T(pdata,0,file_size);
3292 SIVAL(pdata,8,0); /* ??? */
3293 SIVAL(pdata,12,0); /* ??? */
3294 data_size = 16;
3295 break;
3297 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3298 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3299 put_long_date(pdata,c_time);
3300 put_long_date(pdata+8,sbuf.st_atime);
3301 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3302 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3303 SIVAL(pdata,32,allocation_size);
3304 SOFF_T(pdata,40,file_size);
3305 SIVAL(pdata,48,mode);
3306 SIVAL(pdata,52,0); /* ??? */
3307 data_size = 56;
3308 break;
3310 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3311 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3312 SIVAL(pdata,0,mode);
3313 SIVAL(pdata,4,0);
3314 data_size = 8;
3315 break;
3318 * CIFS UNIX Extensions.
3321 case SMB_QUERY_FILE_UNIX_BASIC:
3323 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3324 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3326 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3327 pdata += 8;
3329 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3330 pdata += 8;
3332 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3333 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3334 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3335 pdata += 24;
3337 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3338 SIVAL(pdata,4,0);
3339 pdata += 8;
3341 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3342 SIVAL(pdata,4,0);
3343 pdata += 8;
3345 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3346 pdata += 4;
3348 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3349 SIVAL(pdata,4,0);
3350 pdata += 8;
3352 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3353 SIVAL(pdata,4,0);
3354 pdata += 8;
3356 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3357 pdata += 8;
3359 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3360 SIVAL(pdata,4,0);
3361 pdata += 8;
3363 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3364 SIVAL(pdata,4,0);
3365 pdata += 8+1;
3366 data_size = PTR_DIFF(pdata,(*ppdata));
3369 int i;
3370 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3372 for (i=0; i<100; i++)
3373 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3374 DEBUG(4,("\n"));
3377 break;
3379 case SMB_QUERY_FILE_UNIX_LINK:
3381 pstring buffer;
3383 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3384 #ifdef S_ISLNK
3385 if(!S_ISLNK(sbuf.st_mode))
3386 return(UNIXERROR(ERRSRV,ERRbadlink));
3387 #else
3388 return(UNIXERROR(ERRDOS,ERRbadlink));
3389 #endif
3390 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3391 if (len == -1)
3392 return(UNIXERROR(ERRDOS,ERRnoaccess));
3393 buffer[len] = 0;
3394 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3395 pdata += len;
3396 data_size = PTR_DIFF(pdata,(*ppdata));
3398 break;
3401 #if defined(HAVE_POSIX_ACLS)
3402 case SMB_QUERY_POSIX_ACL:
3404 SMB_ACL_T file_acl = NULL;
3405 SMB_ACL_T def_acl = NULL;
3406 uint16 num_file_acls = 0;
3407 uint16 num_def_acls = 0;
3409 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3410 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3411 } else {
3412 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3415 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3416 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3417 fname ));
3418 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3421 if (S_ISDIR(sbuf.st_mode)) {
3422 if (fsp && fsp->is_directory) {
3423 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3424 } else {
3425 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3427 def_acl = free_empty_sys_acl(conn, def_acl);
3430 num_file_acls = count_acl_entries(conn, file_acl);
3431 num_def_acls = count_acl_entries(conn, def_acl);
3433 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3434 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3435 data_size,
3436 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3437 SMB_POSIX_ACL_HEADER_SIZE) ));
3438 if (file_acl) {
3439 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3441 if (def_acl) {
3442 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3444 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3447 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3448 SSVAL(pdata,2,num_file_acls);
3449 SSVAL(pdata,4,num_def_acls);
3450 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3451 if (file_acl) {
3452 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3454 if (def_acl) {
3455 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3457 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3459 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3460 if (file_acl) {
3461 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3463 if (def_acl) {
3464 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3466 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3469 if (file_acl) {
3470 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3472 if (def_acl) {
3473 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3475 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3476 break;
3478 #endif
3480 default:
3481 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3484 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3486 return(-1);
3489 /****************************************************************************
3490 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3491 code.
3492 ****************************************************************************/
3494 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3496 BOOL bad_path_oldname = False;
3497 BOOL bad_path_newname = False;
3498 SMB_STRUCT_STAT sbuf1, sbuf2;
3499 pstring last_component_oldname;
3500 pstring last_component_newname;
3501 NTSTATUS status = NT_STATUS_OK;
3503 ZERO_STRUCT(sbuf1);
3504 ZERO_STRUCT(sbuf2);
3506 /* No wildcards. */
3507 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3508 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3511 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3512 if (bad_path_oldname) {
3513 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3516 /* Quick check for "." and ".." */
3517 if (last_component_oldname[0] == '.') {
3518 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3519 return NT_STATUS_OBJECT_NAME_INVALID;
3523 /* source must already exist. */
3524 if (!VALID_STAT(sbuf1)) {
3525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3528 if (!check_name(oldname,conn)) {
3529 return NT_STATUS_ACCESS_DENIED;
3532 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3533 if (bad_path_newname) {
3534 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3537 /* Quick check for "." and ".." */
3538 if (last_component_newname[0] == '.') {
3539 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3540 return NT_STATUS_OBJECT_NAME_INVALID;
3544 /* Disallow if newname already exists. */
3545 if (VALID_STAT(sbuf2)) {
3546 return NT_STATUS_OBJECT_NAME_COLLISION;
3549 if (!check_name(newname,conn)) {
3550 return NT_STATUS_ACCESS_DENIED;
3553 /* No links from a directory. */
3554 if (S_ISDIR(sbuf1.st_mode)) {
3555 return NT_STATUS_FILE_IS_A_DIRECTORY;
3558 /* Ensure this is within the share. */
3559 if (!reduce_name(conn, oldname) != 0)
3560 return NT_STATUS_ACCESS_DENIED;
3562 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3564 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3565 status = map_nt_error_from_unix(errno);
3566 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3567 nt_errstr(status), newname, oldname));
3570 return status;
3573 /****************************************************************************
3574 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3575 ****************************************************************************/
3577 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3578 unsigned int tran_call,
3579 char **pparams, int total_params, char **ppdata, int total_data,
3580 unsigned int max_data_bytes)
3582 char *params = *pparams;
3583 char *pdata = *ppdata;
3584 uint16 info_level;
3585 int dosmode=0;
3586 SMB_OFF_T size=0;
3587 struct utimbuf tvs;
3588 SMB_STRUCT_STAT sbuf;
3589 pstring fname;
3590 int fd = -1;
3591 BOOL bad_path = False;
3592 files_struct *fsp = NULL;
3593 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3594 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3595 mode_t unixmode = 0;
3596 NTSTATUS status = NT_STATUS_OK;
3598 if (!params)
3599 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3601 ZERO_STRUCT(sbuf);
3602 ZERO_STRUCT(tvs);
3604 if (tran_call == TRANSACT2_SETFILEINFO) {
3605 if (total_params < 4) {
3606 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3609 fsp = file_fsp(params,0);
3610 info_level = SVAL(params,2);
3612 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3614 * This is actually a SETFILEINFO on a directory
3615 * handle (returned from an NT SMB). NT5.0 seems
3616 * to do this call. JRA.
3618 pstrcpy(fname, fsp->fsp_name);
3619 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3620 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3621 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3623 } else if (fsp && fsp->print_file) {
3625 * Doing a DELETE_ON_CLOSE should cancel a print job.
3627 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3628 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3630 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3632 SSVAL(params,0,0);
3633 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3634 return(-1);
3635 } else
3636 return (UNIXERROR(ERRDOS,ERRbadpath));
3637 } else {
3639 * Original code - this is an open file.
3641 CHECK_FSP(fsp,conn);
3643 pstrcpy(fname, fsp->fsp_name);
3644 fd = fsp->fh->fd;
3646 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3647 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3648 return(UNIXERROR(ERRDOS,ERRbadfid));
3651 } else {
3652 /* set path info */
3653 if (total_params < 6) {
3654 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3657 info_level = SVAL(params,0);
3658 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 return ERROR_NT(status);
3662 unix_convert(fname,conn,0,&bad_path,&sbuf);
3663 if (bad_path) {
3664 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3668 * For CIFS UNIX extensions the target name may not exist.
3671 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3672 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3673 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3676 if(!check_name(fname, conn)) {
3677 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3682 if (!CAN_WRITE(conn))
3683 return ERROR_DOS(ERRSRV,ERRaccess);
3685 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3686 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3688 if (VALID_STAT(sbuf))
3689 unixmode = sbuf.st_mode;
3691 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3692 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3694 /* Realloc the parameter size */
3695 params = SMB_REALLOC(*pparams,2);
3696 if(params == NULL) {
3697 return ERROR_NT(NT_STATUS_NO_MEMORY);
3699 *pparams = params;
3701 SSVAL(params,0,0);
3703 if (fsp && fsp->pending_modtime) {
3704 /* the pending modtime overrides the current modtime */
3705 sbuf.st_mtime = fsp->pending_modtime;
3708 size = get_file_size(sbuf);
3709 tvs.modtime = sbuf.st_mtime;
3710 tvs.actime = sbuf.st_atime;
3711 dosmode = dos_mode(conn,fname,&sbuf);
3712 unixmode = sbuf.st_mode;
3714 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3715 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3717 switch (info_level) {
3718 case SMB_INFO_STANDARD:
3720 if (total_data < 12) {
3721 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3724 /* access time */
3725 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3726 /* write time */
3727 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3728 break;
3731 case SMB_INFO_SET_EA:
3733 struct ea_list *ea_list = NULL;
3734 TALLOC_CTX *ctx = NULL;
3736 if (total_data < 10) {
3738 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3739 length. They seem to have no effect. Bug #3212. JRA */
3741 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3742 /* We're done. We only get EA info in this call. */
3743 SSVAL(params,0,0);
3744 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3745 return(-1);
3748 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3751 if (IVAL(pdata,0) > total_data) {
3752 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3753 IVAL(pdata,0), (unsigned int)total_data));
3754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3757 ctx = talloc_init("SMB_INFO_SET_EA");
3758 if (!ctx) {
3759 return ERROR_NT(NT_STATUS_NO_MEMORY);
3761 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3762 if (!ea_list) {
3763 talloc_destroy(ctx);
3764 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3766 status = set_ea(conn, fsp, fname, ea_list);
3767 talloc_destroy(ctx);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 return ERROR_NT(status);
3773 /* We're done. We only get EA info in this call. */
3774 SSVAL(params,0,0);
3775 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3776 return(-1);
3779 #if 0
3780 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3781 /* XXXX um, i don't think this is right.
3782 it's also not in the cifs6.txt spec.
3784 case SMB_INFO_QUERY_EAS_FROM_LIST:
3785 if (total_data < 28)
3786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3788 tvs.actime = make_unix_date2(pdata+8);
3789 tvs.modtime = make_unix_date2(pdata+12);
3790 size = IVAL(pdata,16);
3791 dosmode = IVAL(pdata,24);
3792 break;
3794 /* XXXX nor this. not in cifs6.txt, either. */
3795 case SMB_INFO_QUERY_ALL_EAS:
3796 if (total_data < 28)
3797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3799 tvs.actime = make_unix_date2(pdata+8);
3800 tvs.modtime = make_unix_date2(pdata+12);
3801 size = IVAL(pdata,16);
3802 dosmode = IVAL(pdata,24);
3803 break;
3804 #endif
3806 case SMB_SET_FILE_BASIC_INFO:
3807 case SMB_FILE_BASIC_INFORMATION:
3809 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3810 time_t write_time;
3811 time_t changed_time;
3813 if (total_data < 36) {
3814 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3817 /* Ignore create time at offset pdata. */
3819 /* access time */
3820 tvs.actime = interpret_long_date(pdata+8);
3822 write_time = interpret_long_date(pdata+16);
3823 changed_time = interpret_long_date(pdata+24);
3825 tvs.modtime = MIN(write_time, changed_time);
3827 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3828 tvs.modtime = write_time;
3830 /* Prefer a defined time to an undefined one. */
3831 if (null_mtime(tvs.modtime)) {
3832 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3835 /* attributes */
3836 dosmode = IVAL(pdata,32);
3837 break;
3840 case SMB_FILE_ALLOCATION_INFORMATION:
3841 case SMB_SET_FILE_ALLOCATION_INFO:
3843 int ret = -1;
3844 SMB_BIG_UINT allocation_size;
3846 if (total_data < 8) {
3847 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3850 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3851 #ifdef LARGE_SMB_OFF_T
3852 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3853 #else /* LARGE_SMB_OFF_T */
3854 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3855 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3856 #endif /* LARGE_SMB_OFF_T */
3857 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3858 fname, (double)allocation_size ));
3860 if (allocation_size) {
3861 allocation_size = smb_roundup(conn, allocation_size);
3864 if(allocation_size != get_file_size(sbuf)) {
3865 SMB_STRUCT_STAT new_sbuf;
3867 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3868 fname, (double)allocation_size ));
3870 if (fd == -1) {
3871 files_struct *new_fsp = NULL;
3873 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3874 FILE_WRITE_DATA,
3875 FILE_SHARE_READ|FILE_SHARE_WRITE,
3876 FILE_OPEN,
3878 FILE_ATTRIBUTE_NORMAL,
3879 INTERNAL_OPEN_ONLY,
3880 NULL);
3882 if (new_fsp == NULL) {
3883 return(UNIXERROR(ERRDOS,ERRbadpath));
3885 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3886 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3887 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3888 new_fsp->fnum, strerror(errno)));
3889 ret = -1;
3891 close_file(new_fsp,True);
3892 } else {
3893 ret = vfs_allocate_file_space(fsp, allocation_size);
3894 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3895 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3896 fsp->fnum, strerror(errno)));
3897 ret = -1;
3900 if (ret == -1)
3901 return ERROR_NT(NT_STATUS_DISK_FULL);
3903 /* Allocate can truncate size... */
3904 size = get_file_size(new_sbuf);
3907 break;
3910 case SMB_FILE_END_OF_FILE_INFORMATION:
3911 case SMB_SET_FILE_END_OF_FILE_INFO:
3913 if (total_data < 8) {
3914 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3917 size = IVAL(pdata,0);
3918 #ifdef LARGE_SMB_OFF_T
3919 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3920 #else /* LARGE_SMB_OFF_T */
3921 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3922 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3923 #endif /* LARGE_SMB_OFF_T */
3924 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3925 break;
3928 case SMB_FILE_DISPOSITION_INFORMATION:
3929 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3931 BOOL delete_on_close;
3933 if (total_data < 1) {
3934 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3937 delete_on_close = (CVAL(pdata,0) ? True : False);
3939 /* Just ignore this set on a path. */
3940 if (tran_call != TRANSACT2_SETFILEINFO)
3941 break;
3943 if (fsp == NULL)
3944 return(UNIXERROR(ERRDOS,ERRbadfid));
3946 status = can_set_delete_on_close(fsp, delete_on_close,
3947 dosmode);
3949 if (!NT_STATUS_IS_OK(status)) {
3950 return ERROR_NT(status);
3953 /* The set is across all open files on this dev/inode pair. */
3954 if (!set_delete_on_close(fsp, delete_on_close)) {
3955 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3958 SSVAL(params,0,0);
3959 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3960 return(-1);
3963 case SMB_FILE_POSITION_INFORMATION:
3965 SMB_BIG_UINT position_information;
3967 if (total_data < 8) {
3968 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3971 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3972 #ifdef LARGE_SMB_OFF_T
3973 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3974 #else /* LARGE_SMB_OFF_T */
3975 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3976 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3977 #endif /* LARGE_SMB_OFF_T */
3978 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3979 fname, (double)position_information ));
3980 if (fsp) {
3981 fsp->fh->position_information = position_information;
3984 /* We're done. We only get position info in this call. */
3985 SSVAL(params,0,0);
3986 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3987 return(-1);
3990 /* From tridge Samba4 :
3991 * MODE_INFORMATION in setfileinfo (I have no
3992 * idea what "mode information" on a file is - it takes a value of 0,
3993 * 2, 4 or 6. What could it be?).
3996 case SMB_FILE_MODE_INFORMATION:
3998 uint32 mode;
4000 if (total_data < 4) {
4001 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4003 mode = IVAL(pdata,0);
4004 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4005 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4008 /* We're done. We only get mode info in this call. */
4009 SSVAL(params,0,0);
4010 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4011 return(-1);
4015 * CIFS UNIX extensions.
4018 case SMB_SET_FILE_UNIX_BASIC:
4020 uint32 raw_unixmode;
4022 if (total_data < 100) {
4023 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4026 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4027 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4028 size=IVAL(pdata,0); /* first 8 Bytes are size */
4029 #ifdef LARGE_SMB_OFF_T
4030 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4031 #else /* LARGE_SMB_OFF_T */
4032 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4033 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4034 #endif /* LARGE_SMB_OFF_T */
4036 pdata+=24; /* ctime & st_blocks are not changed */
4037 tvs.actime = interpret_long_date(pdata); /* access_time */
4038 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4039 pdata+=16;
4040 set_owner = (uid_t)IVAL(pdata,0);
4041 pdata += 8;
4042 set_grp = (gid_t)IVAL(pdata,0);
4043 pdata += 8;
4044 raw_unixmode = IVAL(pdata,28);
4045 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4046 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4048 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4049 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4050 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4052 if (!VALID_STAT(sbuf)) {
4055 * The only valid use of this is to create character and block
4056 * devices, and named pipes. This is deprecated (IMHO) and
4057 * a new info level should be used for mknod. JRA.
4060 uint32 file_type = IVAL(pdata,0);
4061 #if defined(HAVE_MAKEDEV)
4062 uint32 dev_major = IVAL(pdata,4);
4063 uint32 dev_minor = IVAL(pdata,12);
4064 #endif
4066 uid_t myuid = geteuid();
4067 gid_t mygid = getegid();
4068 SMB_DEV_T dev = (SMB_DEV_T)0;
4070 if (tran_call == TRANSACT2_SETFILEINFO)
4071 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4073 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4074 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4077 #if defined(HAVE_MAKEDEV)
4078 dev = makedev(dev_major, dev_minor);
4079 #endif
4081 /* We can only create as the owner/group we are. */
4083 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4084 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4085 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4086 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4088 switch (file_type) {
4089 #if defined(S_IFIFO)
4090 case UNIX_TYPE_FIFO:
4091 unixmode |= S_IFIFO;
4092 break;
4093 #endif
4094 #if defined(S_IFSOCK)
4095 case UNIX_TYPE_SOCKET:
4096 unixmode |= S_IFSOCK;
4097 break;
4098 #endif
4099 #if defined(S_IFCHR)
4100 case UNIX_TYPE_CHARDEV:
4101 unixmode |= S_IFCHR;
4102 break;
4103 #endif
4104 #if defined(S_IFBLK)
4105 case UNIX_TYPE_BLKDEV:
4106 unixmode |= S_IFBLK;
4107 break;
4108 #endif
4109 default:
4110 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4113 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4114 0%o for file %s\n", (double)dev, unixmode, fname ));
4116 /* Ok - do the mknod. */
4117 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4118 return(UNIXERROR(ERRDOS,ERRnoaccess));
4120 inherit_access_acl(conn, fname, unixmode);
4122 SSVAL(params,0,0);
4123 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4124 return(-1);
4128 * Deal with the UNIX specific mode set.
4131 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4132 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4133 (unsigned int)unixmode, fname ));
4134 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4135 return(UNIXERROR(ERRDOS,ERRnoaccess));
4139 * Deal with the UNIX specific uid set.
4142 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4143 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4144 (unsigned int)set_owner, fname ));
4145 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4146 return(UNIXERROR(ERRDOS,ERRnoaccess));
4150 * Deal with the UNIX specific gid set.
4153 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4154 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4155 (unsigned int)set_owner, fname ));
4156 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4157 return(UNIXERROR(ERRDOS,ERRnoaccess));
4159 break;
4162 case SMB_SET_FILE_UNIX_LINK:
4164 pstring link_target;
4165 char *newname = fname;
4167 /* Set a symbolic link. */
4168 /* Don't allow this if follow links is false. */
4170 if (!lp_symlinks(SNUM(conn)))
4171 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4173 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4175 /* !widelinks forces the target path to be within the share. */
4176 /* This means we can interpret the target as a pathname. */
4177 if (!lp_widelinks(SNUM(conn))) {
4178 pstring rel_name;
4179 char *last_dirp = NULL;
4181 unix_format(link_target);
4182 if (*link_target == '/') {
4183 /* No absolute paths allowed. */
4184 return(UNIXERROR(ERRDOS,ERRnoaccess));
4186 pstrcpy(rel_name, newname);
4187 last_dirp = strrchr_m(rel_name, '/');
4188 if (last_dirp) {
4189 last_dirp[1] = '\0';
4190 } else {
4191 pstrcpy(rel_name, "./");
4193 pstrcat(rel_name, link_target);
4195 if (!check_name(rel_name, conn)) {
4196 return(UNIXERROR(ERRDOS,ERRnoaccess));
4200 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4201 fname, link_target ));
4203 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4204 return(UNIXERROR(ERRDOS,ERRnoaccess));
4205 SSVAL(params,0,0);
4206 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4207 return(-1);
4210 case SMB_SET_FILE_UNIX_HLINK:
4212 pstring oldname;
4213 char *newname = fname;
4215 /* Set a hard link. */
4216 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4217 if (!NT_STATUS_IS_OK(status)) {
4218 return ERROR_NT(status);
4221 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4222 fname, oldname));
4224 status = hardlink_internals(conn, oldname, newname);
4225 if (!NT_STATUS_IS_OK(status)) {
4226 return ERROR_NT(status);
4229 SSVAL(params,0,0);
4230 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4231 return(-1);
4234 case SMB_FILE_RENAME_INFORMATION:
4236 BOOL overwrite;
4237 uint32 root_fid;
4238 uint32 len;
4239 pstring newname;
4240 pstring base_name;
4241 char *p;
4243 if (total_data < 12) {
4244 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4247 overwrite = (CVAL(pdata,0) ? True : False);
4248 root_fid = IVAL(pdata,4);
4249 len = IVAL(pdata,8);
4250 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4251 if (!NT_STATUS_IS_OK(status)) {
4252 return ERROR_NT(status);
4255 /* Check the new name has no '/' characters. */
4256 if (strchr_m(newname, '/'))
4257 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4259 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4261 /* Create the base directory. */
4262 pstrcpy(base_name, fname);
4263 p = strrchr_m(base_name, '/');
4264 if (p)
4265 *p = '\0';
4266 /* Append the new name. */
4267 pstrcat(base_name, "/");
4268 pstrcat(base_name, newname);
4270 if (fsp) {
4271 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4272 fsp->fnum, fsp->fsp_name, base_name ));
4273 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4274 } else {
4275 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4276 fname, newname ));
4277 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4279 if (!NT_STATUS_IS_OK(status)) {
4280 return ERROR_NT(status);
4282 process_pending_change_notify_queue((time_t)0);
4283 SSVAL(params,0,0);
4284 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4285 return(-1);
4288 #if defined(HAVE_POSIX_ACLS)
4289 case SMB_SET_POSIX_ACL:
4291 uint16 posix_acl_version;
4292 uint16 num_file_acls;
4293 uint16 num_def_acls;
4294 BOOL valid_file_acls = True;
4295 BOOL valid_def_acls = True;
4297 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4298 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4300 posix_acl_version = SVAL(pdata,0);
4301 num_file_acls = SVAL(pdata,2);
4302 num_def_acls = SVAL(pdata,4);
4304 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4305 valid_file_acls = False;
4306 num_file_acls = 0;
4309 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4310 valid_def_acls = False;
4311 num_def_acls = 0;
4314 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4315 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4318 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4319 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4320 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4323 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4324 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4325 return(UNIXERROR(ERRDOS,ERRnoaccess));
4328 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4329 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4330 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4331 return(UNIXERROR(ERRDOS,ERRnoaccess));
4334 SSVAL(params,0,0);
4335 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4336 return(-1);
4338 #endif
4340 default:
4341 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4344 /* get some defaults (no modifications) if any info is zero or -1. */
4345 if (null_mtime(tvs.actime)) {
4346 tvs.actime = sbuf.st_atime;
4349 if (null_mtime(tvs.modtime)) {
4350 tvs.modtime = sbuf.st_mtime;
4353 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4354 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4355 DEBUG(6,("size: %.0f ", (double)size));
4357 if (dosmode) {
4358 if (S_ISDIR(sbuf.st_mode))
4359 dosmode |= aDIR;
4360 else
4361 dosmode &= ~aDIR;
4364 DEBUG(6,("dosmode: %x\n" , dosmode));
4366 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4367 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4368 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4369 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4372 * Only do this test if we are not explicitly
4373 * changing the size of a file.
4375 if (!size)
4376 size = get_file_size(sbuf);
4380 * Try and set the times, size and mode of this file -
4381 * if they are different from the current values
4384 /* check the mode isn't different, before changing it */
4385 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4387 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4389 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4390 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4391 return(UNIXERROR(ERRDOS,ERRnoaccess));
4395 /* Now the size. */
4396 if (size != get_file_size(sbuf)) {
4398 int ret;
4400 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4401 fname, (double)size ));
4403 if (fd == -1) {
4404 files_struct *new_fsp = NULL;
4406 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4407 FILE_WRITE_DATA,
4408 FILE_SHARE_READ|FILE_SHARE_WRITE,
4409 FILE_OPEN,
4411 FILE_ATTRIBUTE_NORMAL,
4412 INTERNAL_OPEN_ONLY,
4413 NULL);
4415 if (new_fsp == NULL) {
4416 return(UNIXERROR(ERRDOS,ERRbadpath));
4418 ret = vfs_set_filelen(new_fsp, size);
4419 close_file(new_fsp,True);
4420 } else {
4421 ret = vfs_set_filelen(fsp, size);
4424 if (ret == -1) {
4425 return (UNIXERROR(ERRHRD,ERRdiskfull));
4430 * Finally the times.
4432 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4433 if(fsp != NULL) {
4435 * This was a setfileinfo on an open file.
4436 * NT does this a lot. We also need to
4437 * set the time here, as it can be read by
4438 * FindFirst/FindNext and with the patch for bug #2045
4439 * in smbd/fileio.c it ensures that this timestamp is
4440 * kept sticky even after a write. We save the request
4441 * away and will set it on file close and after a write. JRA.
4444 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4445 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4446 fsp_set_pending_modtime(fsp, tvs.modtime);
4450 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4452 if(file_utime(conn, fname, &tvs)!=0) {
4453 return(UNIXERROR(ERRDOS,ERRnoaccess));
4457 SSVAL(params,0,0);
4458 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4460 return(-1);
4463 /****************************************************************************
4464 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4465 ****************************************************************************/
4467 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4468 char **pparams, int total_params, char **ppdata, int total_data,
4469 unsigned int max_data_bytes)
4471 char *params = *pparams;
4472 char *pdata = *ppdata;
4473 pstring directory;
4474 int ret = -1;
4475 SMB_STRUCT_STAT sbuf;
4476 BOOL bad_path = False;
4477 NTSTATUS status = NT_STATUS_OK;
4478 TALLOC_CTX *ctx = NULL;
4479 struct ea_list *ea_list = NULL;
4481 if (!CAN_WRITE(conn))
4482 return ERROR_DOS(ERRSRV,ERRaccess);
4484 if (total_params < 4) {
4485 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4488 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
4489 if (!NT_STATUS_IS_OK(status)) {
4490 return ERROR_NT(status);
4493 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4495 unix_convert(directory,conn,0,&bad_path,&sbuf);
4496 if (bad_path) {
4497 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4500 /* Any data in this call is an EA list. */
4501 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4502 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4506 * OS/2 workplace shell seems to send SET_EA requests of "null"
4507 * length (4 bytes containing IVAL 4).
4508 * They seem to have no effect. Bug #3212. JRA.
4511 if (total_data != 4) {
4512 if (total_data < 10) {
4513 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4516 if (IVAL(pdata,0) > total_data) {
4517 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4518 IVAL(pdata,0), (unsigned int)total_data));
4519 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4522 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4523 if (!ctx) {
4524 return ERROR_NT(NT_STATUS_NO_MEMORY);
4526 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4527 if (!ea_list) {
4528 talloc_destroy(ctx);
4529 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4531 } else if (IVAL(pdata,0) != 4) {
4532 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4535 if (check_name(directory,conn)) {
4536 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4539 if(ret < 0) {
4540 talloc_destroy(ctx);
4541 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4542 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4545 /* Try and set any given EA. */
4546 if (total_data) {
4547 status = set_ea(conn, NULL, directory, ea_list);
4548 talloc_destroy(ctx);
4549 if (!NT_STATUS_IS_OK(status)) {
4550 return ERROR_NT(status);
4554 /* Realloc the parameter and data sizes */
4555 params = SMB_REALLOC(*pparams,2);
4556 if(params == NULL) {
4557 return ERROR_NT(NT_STATUS_NO_MEMORY);
4559 *pparams = params;
4561 SSVAL(params,0,0);
4563 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4565 return(-1);
4568 /****************************************************************************
4569 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4570 We don't actually do this - we just send a null response.
4571 ****************************************************************************/
4573 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4574 char **pparams, int total_params, char **ppdata, int total_data,
4575 unsigned int max_data_bytes)
4577 static uint16 fnf_handle = 257;
4578 char *params = *pparams;
4579 uint16 info_level;
4581 if (total_params < 6) {
4582 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4585 info_level = SVAL(params,4);
4586 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4588 switch (info_level) {
4589 case 1:
4590 case 2:
4591 break;
4592 default:
4593 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4596 /* Realloc the parameter and data sizes */
4597 params = SMB_REALLOC(*pparams,6);
4598 if(params == NULL) {
4599 return ERROR_NT(NT_STATUS_NO_MEMORY);
4601 *pparams = params;
4603 SSVAL(params,0,fnf_handle);
4604 SSVAL(params,2,0); /* No changes */
4605 SSVAL(params,4,0); /* No EA errors */
4607 fnf_handle++;
4609 if(fnf_handle == 0)
4610 fnf_handle = 257;
4612 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4614 return(-1);
4617 /****************************************************************************
4618 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4619 changes). Currently this does nothing.
4620 ****************************************************************************/
4622 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4623 char **pparams, int total_params, char **ppdata, int total_data,
4624 unsigned int max_data_bytes)
4626 char *params = *pparams;
4628 DEBUG(3,("call_trans2findnotifynext\n"));
4630 /* Realloc the parameter and data sizes */
4631 params = SMB_REALLOC(*pparams,4);
4632 if(params == NULL) {
4633 return ERROR_NT(NT_STATUS_NO_MEMORY);
4635 *pparams = params;
4637 SSVAL(params,0,0); /* No changes */
4638 SSVAL(params,2,0); /* No EA errors */
4640 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4642 return(-1);
4645 /****************************************************************************
4646 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4647 ****************************************************************************/
4649 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4650 char **pparams, int total_params, char **ppdata, int total_data,
4651 unsigned int max_data_bytes)
4653 char *params = *pparams;
4654 pstring pathname;
4655 int reply_size = 0;
4656 int max_referral_level;
4658 DEBUG(10,("call_trans2getdfsreferral\n"));
4660 if (total_params < 2) {
4661 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4664 max_referral_level = SVAL(params,0);
4666 if(!lp_host_msdfs())
4667 return ERROR_DOS(ERRDOS,ERRbadfunc);
4669 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4670 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4671 return UNIXERROR(ERRDOS,ERRbadfile);
4673 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4674 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4676 return(-1);
4679 #define LMCAT_SPL 0x53
4680 #define LMFUNC_GETJOBID 0x60
4682 /****************************************************************************
4683 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4684 ****************************************************************************/
4686 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4687 char **pparams, int total_params, char **ppdata, int total_data,
4688 unsigned int max_data_bytes)
4690 char *pdata = *ppdata;
4691 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4693 /* check for an invalid fid before proceeding */
4695 if (!fsp)
4696 return(ERROR_DOS(ERRDOS,ERRbadfid));
4698 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4699 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4700 pdata = SMB_REALLOC(*ppdata, 32);
4701 if(pdata == NULL) {
4702 return ERROR_NT(NT_STATUS_NO_MEMORY);
4704 *ppdata = pdata;
4706 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4707 CAN ACCEPT THIS IN UNICODE. JRA. */
4709 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4710 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4711 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4712 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4713 return(-1);
4714 } else {
4715 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4716 return ERROR_DOS(ERRSRV,ERRerror);
4720 /****************************************************************************
4721 Reply to a SMBfindclose (stop trans2 directory search).
4722 ****************************************************************************/
4724 int reply_findclose(connection_struct *conn,
4725 char *inbuf,char *outbuf,int length,int bufsize)
4727 int outsize = 0;
4728 int dptr_num=SVALS(inbuf,smb_vwv0);
4729 START_PROFILE(SMBfindclose);
4731 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4733 dptr_close(&dptr_num);
4735 outsize = set_message(outbuf,0,0,True);
4737 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4739 END_PROFILE(SMBfindclose);
4740 return(outsize);
4743 /****************************************************************************
4744 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4745 ****************************************************************************/
4747 int reply_findnclose(connection_struct *conn,
4748 char *inbuf,char *outbuf,int length,int bufsize)
4750 int outsize = 0;
4751 int dptr_num= -1;
4752 START_PROFILE(SMBfindnclose);
4754 dptr_num = SVAL(inbuf,smb_vwv0);
4756 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4758 /* We never give out valid handles for a
4759 findnotifyfirst - so any dptr_num is ok here.
4760 Just ignore it. */
4762 outsize = set_message(outbuf,0,0,True);
4764 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4766 END_PROFILE(SMBfindnclose);
4767 return(outsize);
4770 /****************************************************************************
4771 Reply to a SMBtranss2 - just ignore it!
4772 ****************************************************************************/
4774 int reply_transs2(connection_struct *conn,
4775 char *inbuf,char *outbuf,int length,int bufsize)
4777 START_PROFILE(SMBtranss2);
4778 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4779 END_PROFILE(SMBtranss2);
4780 return(-1);
4783 /****************************************************************************
4784 Reply to a SMBtrans2.
4785 ****************************************************************************/
4787 int reply_trans2(connection_struct *conn,
4788 char *inbuf,char *outbuf,int length,int bufsize)
4790 int outsize = 0;
4791 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4792 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4793 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4794 #if 0
4795 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4796 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4797 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4798 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4799 int32 timeout = IVALS(inbuf,smb_timeout);
4800 #endif
4801 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4802 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4803 char *params = NULL, *data = NULL;
4804 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4805 START_PROFILE(SMBtrans2);
4807 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4808 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4809 END_PROFILE(SMBtrans2);
4810 return ERROR_DOS(ERRSRV,ERRaccess);
4813 outsize = set_message(outbuf,0,0,True);
4815 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4816 is so as a sanity check */
4817 if (suwcnt != 1) {
4819 * Need to have rc=0 for ioctl to get job id for OS/2.
4820 * Network printing will fail if function is not successful.
4821 * Similar function in reply.c will be used if protocol
4822 * is LANMAN1.0 instead of LM1.2X002.
4823 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4824 * outbuf doesn't have to be set(only job id is used).
4826 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4827 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4828 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4829 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4830 } else {
4831 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4832 DEBUG(2,("Transaction is %d\n",tran_call));
4833 END_PROFILE(SMBtrans2);
4834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4838 /* Allocate the space for the maximum needed parameters and data */
4839 if (total_params > 0)
4840 params = (char *)SMB_MALLOC(total_params);
4841 if (total_data > 0)
4842 data = (char *)SMB_MALLOC(total_data);
4844 if ((total_params && !params) || (total_data && !data)) {
4845 DEBUG(2,("Out of memory in reply_trans2\n"));
4846 SAFE_FREE(params);
4847 SAFE_FREE(data);
4848 END_PROFILE(SMBtrans2);
4849 return ERROR_NT(NT_STATUS_NO_MEMORY);
4852 /* Copy the param and data bytes sent with this request into
4853 the params buffer */
4854 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4855 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4857 if (num_params > total_params || num_data > total_data)
4858 exit_server("invalid params in reply_trans2");
4860 if(params) {
4861 unsigned int psoff = SVAL(inbuf, smb_psoff);
4862 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4863 goto bad_param;
4864 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4865 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4866 goto bad_param;
4867 memcpy( params, smb_base(inbuf) + psoff, num_params);
4869 if(data) {
4870 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4871 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4872 goto bad_param;
4873 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4874 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4875 goto bad_param;
4876 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4879 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4881 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4882 /* We need to send an interim response then receive the rest
4883 of the parameter/data bytes */
4884 outsize = set_message(outbuf,0,0,True);
4885 srv_signing_trans_stop();
4886 show_msg(outbuf);
4887 if (!send_smb(smbd_server_fd(),outbuf))
4888 exit_server("reply_trans2: send_smb failed.");
4890 while (num_data_sofar < total_data ||
4891 num_params_sofar < total_params) {
4892 BOOL ret;
4893 unsigned int param_disp;
4894 unsigned int param_off;
4895 unsigned int data_disp;
4896 unsigned int data_off;
4898 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4900 /* We need to re-calcuate the new length after we've read the secondary packet. */
4901 length = smb_len(inbuf) + 4;
4904 * The sequence number for the trans reply is always
4905 * based on the last secondary received.
4908 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4910 if ((ret &&
4911 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4912 outsize = set_message(outbuf,0,0,True);
4913 if(ret)
4914 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4915 else
4916 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4917 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4918 goto bad_param;
4921 /* Revise total_params and total_data in case
4922 they have changed downwards */
4923 if (SVAL(inbuf, smb_tpscnt) < total_params)
4924 total_params = SVAL(inbuf, smb_tpscnt);
4925 if (SVAL(inbuf, smb_tdscnt) < total_data)
4926 total_data = SVAL(inbuf, smb_tdscnt);
4928 num_params = SVAL(inbuf,smb_spscnt);
4929 param_off = SVAL(inbuf, smb_spsoff);
4930 param_disp = SVAL(inbuf, smb_spsdisp);
4931 num_params_sofar += num_params;
4933 num_data = SVAL(inbuf, smb_sdscnt);
4934 data_off = SVAL(inbuf, smb_sdsoff);
4935 data_disp = SVAL(inbuf, smb_sdsdisp);
4936 num_data_sofar += num_data;
4938 if (num_params_sofar > total_params || num_data_sofar > total_data)
4939 goto bad_param;
4941 if (num_params) {
4942 if (param_disp + num_params > total_params)
4943 goto bad_param;
4944 if ((param_disp + num_params < param_disp) ||
4945 (param_disp + num_params < num_params))
4946 goto bad_param;
4947 if (param_disp > total_params)
4948 goto bad_param;
4949 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4950 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4951 goto bad_param;
4952 if (params + param_disp < params)
4953 goto bad_param;
4955 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4957 if (num_data) {
4958 if (data_disp + num_data > total_data)
4959 goto bad_param;
4960 if ((data_disp + num_data < data_disp) ||
4961 (data_disp + num_data < num_data))
4962 goto bad_param;
4963 if (data_disp > total_data)
4964 goto bad_param;
4965 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4966 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4967 goto bad_param;
4968 if (data + data_disp < data)
4969 goto bad_param;
4971 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4976 if (Protocol >= PROTOCOL_NT1) {
4977 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4980 /* Now we must call the relevant TRANS2 function */
4981 switch(tran_call) {
4982 case TRANSACT2_OPEN:
4983 START_PROFILE_NESTED(Trans2_open);
4984 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4985 &params, total_params, &data, total_data, max_data_bytes);
4986 END_PROFILE_NESTED(Trans2_open);
4987 break;
4989 case TRANSACT2_FINDFIRST:
4990 START_PROFILE_NESTED(Trans2_findfirst);
4991 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4992 &params, total_params, &data, total_data, max_data_bytes);
4993 END_PROFILE_NESTED(Trans2_findfirst);
4994 break;
4996 case TRANSACT2_FINDNEXT:
4997 START_PROFILE_NESTED(Trans2_findnext);
4998 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4999 &params, total_params, &data, total_data, max_data_bytes);
5000 END_PROFILE_NESTED(Trans2_findnext);
5001 break;
5003 case TRANSACT2_QFSINFO:
5004 START_PROFILE_NESTED(Trans2_qfsinfo);
5005 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
5006 &params, total_params, &data, total_data, max_data_bytes);
5007 END_PROFILE_NESTED(Trans2_qfsinfo);
5008 break;
5010 case TRANSACT2_SETFSINFO:
5011 START_PROFILE_NESTED(Trans2_setfsinfo);
5012 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5013 &params, total_params, &data, total_data, max_data_bytes);
5014 END_PROFILE_NESTED(Trans2_setfsinfo);
5015 break;
5017 case TRANSACT2_QPATHINFO:
5018 case TRANSACT2_QFILEINFO:
5019 START_PROFILE_NESTED(Trans2_qpathinfo);
5020 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5021 &params, total_params, &data, total_data, max_data_bytes);
5022 END_PROFILE_NESTED(Trans2_qpathinfo);
5023 break;
5024 case TRANSACT2_SETPATHINFO:
5025 case TRANSACT2_SETFILEINFO:
5026 START_PROFILE_NESTED(Trans2_setpathinfo);
5027 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5028 &params, total_params, &data, total_data, max_data_bytes);
5029 END_PROFILE_NESTED(Trans2_setpathinfo);
5030 break;
5032 case TRANSACT2_FINDNOTIFYFIRST:
5033 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5034 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5035 &params, total_params, &data, total_data, max_data_bytes);
5036 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5037 break;
5039 case TRANSACT2_FINDNOTIFYNEXT:
5040 START_PROFILE_NESTED(Trans2_findnotifynext);
5041 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5042 &params, total_params, &data, total_data, max_data_bytes);
5043 END_PROFILE_NESTED(Trans2_findnotifynext);
5044 break;
5045 case TRANSACT2_MKDIR:
5046 START_PROFILE_NESTED(Trans2_mkdir);
5047 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5048 &params, total_params, &data, total_data, max_data_bytes);
5049 END_PROFILE_NESTED(Trans2_mkdir);
5050 break;
5052 case TRANSACT2_GET_DFS_REFERRAL:
5053 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5054 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5055 &params, total_params, &data, total_data, max_data_bytes);
5056 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5057 break;
5058 case TRANSACT2_IOCTL:
5059 START_PROFILE_NESTED(Trans2_ioctl);
5060 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5061 &params, total_params, &data, total_data, max_data_bytes);
5062 END_PROFILE_NESTED(Trans2_ioctl);
5063 break;
5064 default:
5065 /* Error in request */
5066 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5067 SAFE_FREE(params);
5068 SAFE_FREE(data);
5069 END_PROFILE(SMBtrans2);
5070 srv_signing_trans_stop();
5071 return ERROR_DOS(ERRSRV,ERRerror);
5074 /* As we do not know how many data packets will need to be
5075 returned here the various call_trans2xxxx calls
5076 must send their own. Thus a call_trans2xxx routine only
5077 returns a value other than -1 when it wants to send
5078 an error packet.
5081 srv_signing_trans_stop();
5083 SAFE_FREE(params);
5084 SAFE_FREE(data);
5085 END_PROFILE(SMBtrans2);
5086 return outsize; /* If a correct response was needed the
5087 call_trans2xxx calls have already sent
5088 it. If outsize != -1 then it is returning */
5090 bad_param:
5092 srv_signing_trans_stop();
5093 SAFE_FREE(params);
5094 SAFE_FREE(data);
5095 END_PROFILE(SMBtrans2);
5096 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);