spoolss: use nstring_array in spoolss_EnumPrinterKey.
[Samba.git] / source3 / smbd / trans2.c
blobee1dda98b22c3ca3d982e60ddc71dadd49921447
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
35 char *pdata,
36 files_struct *fsp,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
40 char *pdata,
41 files_struct *fsp,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
58 return val;
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name)
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
74 NULL
77 int i;
79 for (i = 0; prohibited_ea_names[i]; i++) {
80 if (strequal( prohibited_ea_names[i], unix_ea_name))
81 return true;
83 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
85 return true;
87 return false;
90 /****************************************************************************
91 Get one EA value. Fill in a struct ea_struct.
92 ****************************************************************************/
94 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
95 files_struct *fsp, const char *fname,
96 const char *ea_name, struct ea_struct *pea)
98 /* Get the value of this xattr. Max size is 64k. */
99 size_t attr_size = 256;
100 char *val = NULL;
101 ssize_t sizeret;
103 again:
105 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
106 if (!val) {
107 return NT_STATUS_NO_MEMORY;
110 if (fsp && fsp->fh->fd != -1) {
111 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
112 } else {
113 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
116 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
117 attr_size = 65536;
118 goto again;
121 if (sizeret == -1) {
122 return map_nt_error_from_unix(errno);
125 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
126 dump_data(10, (uint8 *)val, sizeret);
128 pea->flags = 0;
129 if (strnequal(ea_name, "user.", 5)) {
130 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
131 } else {
132 pea->name = talloc_strdup(mem_ctx, ea_name);
134 if (pea->name == NULL) {
135 TALLOC_FREE(val);
136 return NT_STATUS_NO_MEMORY;
138 pea->value.data = (unsigned char *)val;
139 pea->value.length = (size_t)sizeret;
140 return NT_STATUS_OK;
143 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
144 files_struct *fsp, const char *fname,
145 char ***pnames, size_t *pnum_names)
147 /* Get a list of all xattrs. Max namesize is 64k. */
148 size_t ea_namelist_size = 1024;
149 char *ea_namelist = NULL;
151 char *p;
152 char **names, **tmp;
153 size_t num_names;
154 ssize_t sizeret = -1;
156 if (!lp_ea_support(SNUM(conn))) {
157 *pnames = NULL;
158 *pnum_names = 0;
159 return NT_STATUS_OK;
163 * TALLOC the result early to get the talloc hierarchy right.
166 names = TALLOC_ARRAY(mem_ctx, char *, 1);
167 if (names == NULL) {
168 DEBUG(0, ("talloc failed\n"));
169 return NT_STATUS_NO_MEMORY;
172 while (ea_namelist_size <= 65536) {
174 ea_namelist = TALLOC_REALLOC_ARRAY(
175 names, ea_namelist, char, ea_namelist_size);
176 if (ea_namelist == NULL) {
177 DEBUG(0, ("talloc failed\n"));
178 TALLOC_FREE(names);
179 return NT_STATUS_NO_MEMORY;
182 if (fsp && fsp->fh->fd != -1) {
183 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
184 ea_namelist_size);
185 } else {
186 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
187 ea_namelist_size);
190 if ((sizeret == -1) && (errno == ERANGE)) {
191 ea_namelist_size *= 2;
193 else {
194 break;
198 if (sizeret == -1) {
199 TALLOC_FREE(names);
200 return map_nt_error_from_unix(errno);
203 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
204 (unsigned int)sizeret));
206 if (sizeret == 0) {
207 TALLOC_FREE(names);
208 *pnames = NULL;
209 *pnum_names = 0;
210 return NT_STATUS_OK;
214 * Ensure the result is 0-terminated
217 if (ea_namelist[sizeret-1] != '\0') {
218 TALLOC_FREE(names);
219 return NT_STATUS_INTERNAL_ERROR;
223 * count the names
225 num_names = 0;
227 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
228 num_names += 1;
231 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
232 if (tmp == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 names = tmp;
239 num_names = 0;
241 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
242 names[num_names++] = p;
245 *pnames = names;
246 *pnum_names = num_names;
247 return NT_STATUS_OK;
250 /****************************************************************************
251 Return a linked list of the total EA's. Plus the total size
252 ****************************************************************************/
254 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
255 const char *fname, size_t *pea_total_len)
257 /* Get a list of all xattrs. Max namesize is 64k. */
258 size_t i, num_names;
259 char **names;
260 struct ea_list *ea_list_head = NULL;
261 NTSTATUS status;
263 *pea_total_len = 0;
265 if (!lp_ea_support(SNUM(conn))) {
266 return NULL;
269 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
270 &names, &num_names);
272 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
273 return NULL;
276 for (i=0; i<num_names; i++) {
277 struct ea_list *listp;
278 fstring dos_ea_name;
280 if (strnequal(names[i], "system.", 7)
281 || samba_private_attr_name(names[i]))
282 continue;
284 listp = TALLOC_P(mem_ctx, struct ea_list);
285 if (listp == NULL) {
286 return NULL;
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
290 fname, names[i],
291 &listp->ea))) {
292 return NULL;
295 push_ascii_fstring(dos_ea_name, listp->ea.name);
297 *pea_total_len +=
298 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
300 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
301 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
302 (unsigned int)listp->ea.value.length));
304 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
308 /* Add on 4 for total length. */
309 if (*pea_total_len) {
310 *pea_total_len += 4;
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len));
316 return ea_list_head;
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
321 that was filled.
322 ****************************************************************************/
324 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
325 connection_struct *conn, struct ea_list *ea_list)
327 unsigned int ret_data_size = 4;
328 char *p = pdata;
330 SMB_ASSERT(total_data_size >= 4);
332 if (!lp_ea_support(SNUM(conn))) {
333 SIVAL(pdata,4,0);
334 return 4;
337 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
338 size_t dos_namelen;
339 fstring dos_ea_name;
340 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
341 dos_namelen = strlen(dos_ea_name);
342 if (dos_namelen > 255 || dos_namelen == 0) {
343 break;
345 if (ea_list->ea.value.length > 65535) {
346 break;
348 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
349 break;
352 /* We know we have room. */
353 SCVAL(p,0,ea_list->ea.flags);
354 SCVAL(p,1,dos_namelen);
355 SSVAL(p,2,ea_list->ea.value.length);
356 fstrcpy(p+4, dos_ea_name);
357 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
359 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
360 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
363 ret_data_size = PTR_DIFF(p, pdata);
364 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
365 SIVAL(pdata,0,ret_data_size);
366 return ret_data_size;
369 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
371 size_t total_ea_len = 0;
372 TALLOC_CTX *mem_ctx = NULL;
374 if (!lp_ea_support(SNUM(conn))) {
375 return 0;
377 mem_ctx = talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
379 return total_ea_len;
382 /****************************************************************************
383 Ensure the EA name is case insensitive by matching any existing EA name.
384 ****************************************************************************/
386 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
388 size_t total_ea_len;
389 TALLOC_CTX *mem_ctx = talloc_tos();
390 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
392 for (; ea_list; ea_list = ea_list->next) {
393 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
394 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
395 &unix_ea_name[5], ea_list->ea.name));
396 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
397 break;
402 /****************************************************************************
403 Set or delete an extended attribute.
404 ****************************************************************************/
406 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
408 if (!lp_ea_support(SNUM(conn))) {
409 return NT_STATUS_EAS_NOT_SUPPORTED;
412 for (;ea_list; ea_list = ea_list->next) {
413 int ret;
414 fstring unix_ea_name;
416 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
417 fstrcat(unix_ea_name, ea_list->ea.name);
419 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
421 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
423 if (samba_private_attr_name(unix_ea_name)) {
424 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
425 return NT_STATUS_ACCESS_DENIED;
428 if (ea_list->ea.value.length == 0) {
429 /* Remove the attribute. */
430 if (fsp && (fsp->fh->fd != -1)) {
431 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
432 unix_ea_name, fsp->fsp_name));
433 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
434 } else {
435 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
436 unix_ea_name, fname));
437 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
439 #ifdef ENOATTR
440 /* Removing a non existent attribute always succeeds. */
441 if (ret == -1 && errno == ENOATTR) {
442 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
443 unix_ea_name));
444 ret = 0;
446 #endif
447 } else {
448 if (fsp && (fsp->fh->fd != -1)) {
449 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
450 unix_ea_name, fsp->fsp_name));
451 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
452 ea_list->ea.value.data, ea_list->ea.value.length, 0);
453 } else {
454 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
455 unix_ea_name, fname));
456 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
457 ea_list->ea.value.data, ea_list->ea.value.length, 0);
461 if (ret == -1) {
462 #ifdef ENOTSUP
463 if (errno == ENOTSUP) {
464 return NT_STATUS_EAS_NOT_SUPPORTED;
466 #endif
467 return map_nt_error_from_unix(errno);
471 return NT_STATUS_OK;
473 /****************************************************************************
474 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
475 ****************************************************************************/
477 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
479 struct ea_list *ea_list_head = NULL;
480 size_t converted_size, offset = 0;
482 while (offset + 2 < data_size) {
483 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
484 unsigned int namelen = CVAL(pdata,offset);
486 offset++; /* Go past the namelen byte. */
488 /* integer wrap paranioa. */
489 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
490 (offset > data_size) || (namelen > data_size) ||
491 (offset + namelen >= data_size)) {
492 break;
494 /* Ensure the name is null terminated. */
495 if (pdata[offset + namelen] != '\0') {
496 return NULL;
498 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
499 &converted_size)) {
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno)));
503 if (!eal->ea.name) {
504 return NULL;
507 offset += (namelen + 1); /* Go past the name + terminating zero. */
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
512 return ea_list_head;
515 /****************************************************************************
516 Read one EA list entry from the buffer.
517 ****************************************************************************/
519 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
521 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
522 uint16 val_len;
523 unsigned int namelen;
524 size_t converted_size;
526 if (!eal) {
527 return NULL;
530 if (data_size < 6) {
531 return NULL;
534 eal->ea.flags = CVAL(pdata,0);
535 namelen = CVAL(pdata,1);
536 val_len = SVAL(pdata,2);
538 if (4 + namelen + 1 + val_len > data_size) {
539 return NULL;
542 /* Ensure the name is null terminated. */
543 if (pdata[namelen + 4] != '\0') {
544 return NULL;
546 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
547 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
548 strerror(errno)));
550 if (!eal->ea.name) {
551 return NULL;
554 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
555 if (!eal->ea.value.data) {
556 return NULL;
559 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
561 /* Ensure we're null terminated just in case we print the value. */
562 eal->ea.value.data[val_len] = '\0';
563 /* But don't count the null. */
564 eal->ea.value.length--;
566 if (pbytes_used) {
567 *pbytes_used = 4 + namelen + 1 + val_len;
570 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
571 dump_data(10, eal->ea.value.data, eal->ea.value.length);
573 return eal;
576 /****************************************************************************
577 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
578 ****************************************************************************/
580 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
582 struct ea_list *ea_list_head = NULL;
583 size_t offset = 0;
584 size_t bytes_used = 0;
586 while (offset < data_size) {
587 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
589 if (!eal) {
590 return NULL;
593 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
594 offset += bytes_used;
597 return ea_list_head;
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
604 static size_t ea_list_size(struct ea_list *ealist)
606 fstring dos_ea_name;
607 struct ea_list *listp;
608 size_t ret = 0;
610 for (listp = ealist; listp; listp = listp->next) {
611 push_ascii_fstring(dos_ea_name, listp->ea.name);
612 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
614 /* Add on 4 for total length. */
615 if (ret) {
616 ret += 4;
619 return ret;
622 /****************************************************************************
623 Return a union of EA's from a file list and a list of names.
624 The TALLOC context for the two lists *MUST* be identical as we steal
625 memory from one list to add to another. JRA.
626 ****************************************************************************/
628 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
630 struct ea_list *nlistp, *flistp;
632 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
633 for (flistp = file_list; flistp; flistp = flistp->next) {
634 if (strequal(nlistp->ea.name, flistp->ea.name)) {
635 break;
639 if (flistp) {
640 /* Copy the data from this entry. */
641 nlistp->ea.flags = flistp->ea.flags;
642 nlistp->ea.value = flistp->ea.value;
643 } else {
644 /* Null entry. */
645 nlistp->ea.flags = 0;
646 ZERO_STRUCT(nlistp->ea.value);
650 *total_ea_len = ea_list_size(name_list);
651 return name_list;
654 /****************************************************************************
655 Send the required number of replies back.
656 We assume all fields other than the data fields are
657 set correctly for the type of call.
658 HACK ! Always assumes smb_setup field is zero.
659 ****************************************************************************/
661 void send_trans2_replies(connection_struct *conn,
662 struct smb_request *req,
663 const char *params,
664 int paramsize,
665 const char *pdata,
666 int datasize,
667 int max_data_bytes)
669 /* As we are using a protocol > LANMAN1 then the max_send
670 variable must have been set in the sessetupX call.
671 This takes precedence over the max_xmit field in the
672 global struct. These different max_xmit variables should
673 be merged as this is now too confusing */
675 int data_to_send = datasize;
676 int params_to_send = paramsize;
677 int useable_space;
678 const char *pp = params;
679 const char *pd = pdata;
680 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
681 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
682 int data_alignment_offset = 0;
683 bool overflow = False;
685 /* Modify the data_to_send and datasize and set the error if
686 we're trying to send more than max_data_bytes. We still send
687 the part of the packet(s) that fit. Strange, but needed
688 for OS/2. */
690 if (max_data_bytes > 0 && datasize > max_data_bytes) {
691 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
692 max_data_bytes, datasize ));
693 datasize = data_to_send = max_data_bytes;
694 overflow = True;
697 /* If there genuinely are no parameters or data to send just send the empty packet */
699 if(params_to_send == 0 && data_to_send == 0) {
700 reply_outbuf(req, 10, 0);
701 show_msg((char *)req->outbuf);
702 return;
705 /* When sending params and data ensure that both are nicely aligned */
706 /* Only do this alignment when there is also data to send - else
707 can cause NT redirector problems. */
709 if (((params_to_send % 4) != 0) && (data_to_send != 0))
710 data_alignment_offset = 4 - (params_to_send % 4);
712 /* Space is bufsize minus Netbios over TCP header minus SMB header */
713 /* The alignment_offset is to align the param bytes on an even byte
714 boundary. NT 4.0 Beta needs this to work correctly. */
716 useable_space = max_send - (smb_size
717 + 2 * 10 /* wct */
718 + alignment_offset
719 + data_alignment_offset);
721 if (useable_space < 0) {
722 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
723 "= %d!!!", useable_space));
724 exit_server_cleanly("send_trans2_replies: Not enough space");
727 while (params_to_send || data_to_send) {
728 /* Calculate whether we will totally or partially fill this packet */
730 total_sent_thistime = params_to_send + data_to_send;
732 /* We can never send more than useable_space */
734 * Note that 'useable_space' does not include the alignment offsets,
735 * but we must include the alignment offsets in the calculation of
736 * the length of the data we send over the wire, as the alignment offsets
737 * are sent here. Fix from Marc_Jacobsen@hp.com.
740 total_sent_thistime = MIN(total_sent_thistime, useable_space);
742 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
743 + data_alignment_offset);
746 * We might have SMBtrans2s in req which was transferred to
747 * the outbuf, fix that.
749 SCVAL(req->outbuf, smb_com, SMBtrans2);
751 /* Set total params and data to be sent */
752 SSVAL(req->outbuf,smb_tprcnt,paramsize);
753 SSVAL(req->outbuf,smb_tdrcnt,datasize);
755 /* Calculate how many parameters and data we can fit into
756 * this packet. Parameters get precedence
759 params_sent_thistime = MIN(params_to_send,useable_space);
760 data_sent_thistime = useable_space - params_sent_thistime;
761 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
763 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
765 /* smb_proff is the offset from the start of the SMB header to the
766 parameter bytes, however the first 4 bytes of outbuf are
767 the Netbios over TCP header. Thus use smb_base() to subtract
768 them from the calculation */
770 SSVAL(req->outbuf,smb_proff,
771 ((smb_buf(req->outbuf)+alignment_offset)
772 - smb_base(req->outbuf)));
774 if(params_sent_thistime == 0)
775 SSVAL(req->outbuf,smb_prdisp,0);
776 else
777 /* Absolute displacement of param bytes sent in this packet */
778 SSVAL(req->outbuf,smb_prdisp,pp - params);
780 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
781 if(data_sent_thistime == 0) {
782 SSVAL(req->outbuf,smb_droff,0);
783 SSVAL(req->outbuf,smb_drdisp, 0);
784 } else {
785 /* The offset of the data bytes is the offset of the
786 parameter bytes plus the number of parameters being sent this time */
787 SSVAL(req->outbuf, smb_droff,
788 ((smb_buf(req->outbuf)+alignment_offset)
789 - smb_base(req->outbuf))
790 + params_sent_thistime + data_alignment_offset);
791 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
794 /* Initialize the padding for alignment */
796 if (alignment_offset != 0) {
797 memset(smb_buf(req->outbuf), 0, alignment_offset);
800 /* Copy the param bytes into the packet */
802 if(params_sent_thistime) {
803 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
804 params_sent_thistime);
807 /* Copy in the data bytes */
808 if(data_sent_thistime) {
809 if (data_alignment_offset != 0) {
810 memset((smb_buf(req->outbuf)+alignment_offset+
811 params_sent_thistime), 0,
812 data_alignment_offset);
814 memcpy(smb_buf(req->outbuf)+alignment_offset
815 +params_sent_thistime+data_alignment_offset,
816 pd,data_sent_thistime);
819 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
820 params_sent_thistime, data_sent_thistime, useable_space));
821 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
822 params_to_send, data_to_send, paramsize, datasize));
824 if (overflow) {
825 error_packet_set((char *)req->outbuf,
826 ERRDOS,ERRbufferoverflow,
827 STATUS_BUFFER_OVERFLOW,
828 __LINE__,__FILE__);
831 /* Send the packet */
832 show_msg((char *)req->outbuf);
833 if (!srv_send_smb(smbd_server_fd(),
834 (char *)req->outbuf,
835 IS_CONN_ENCRYPTED(conn),
836 &req->pcd))
837 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
839 TALLOC_FREE(req->outbuf);
841 pp += params_sent_thistime;
842 pd += data_sent_thistime;
844 params_to_send -= params_sent_thistime;
845 data_to_send -= data_sent_thistime;
847 /* Sanity check */
848 if(params_to_send < 0 || data_to_send < 0) {
849 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
850 params_to_send, data_to_send));
851 return;
855 return;
858 /****************************************************************************
859 Reply to a TRANSACT2_OPEN.
860 ****************************************************************************/
862 static void call_trans2open(connection_struct *conn,
863 struct smb_request *req,
864 char **pparams, int total_params,
865 char **ppdata, int total_data,
866 unsigned int max_data_bytes)
868 char *params = *pparams;
869 char *pdata = *ppdata;
870 int deny_mode;
871 int32 open_attr;
872 bool oplock_request;
873 #if 0
874 bool return_additional_info;
875 int16 open_sattr;
876 time_t open_time;
877 #endif
878 int open_ofun;
879 uint32 open_size;
880 char *pname;
881 char *fname = NULL;
882 SMB_OFF_T size=0;
883 int fattr=0,mtime=0;
884 SMB_INO_T inode = 0;
885 SMB_STRUCT_STAT sbuf;
886 int smb_action = 0;
887 files_struct *fsp;
888 struct ea_list *ea_list = NULL;
889 uint16 flags = 0;
890 NTSTATUS status;
891 uint32 access_mask;
892 uint32 share_mode;
893 uint32 create_disposition;
894 uint32 create_options = 0;
895 TALLOC_CTX *ctx = talloc_tos();
898 * Ensure we have enough parameters to perform the operation.
901 if (total_params < 29) {
902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
903 return;
906 flags = SVAL(params, 0);
907 deny_mode = SVAL(params, 2);
908 open_attr = SVAL(params,6);
909 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
910 if (oplock_request) {
911 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
914 #if 0
915 return_additional_info = BITSETW(params,0);
916 open_sattr = SVAL(params, 4);
917 open_time = make_unix_date3(params+8);
918 #endif
919 open_ofun = SVAL(params,12);
920 open_size = IVAL(params,14);
921 pname = &params[28];
923 if (IS_IPC(conn)) {
924 reply_doserror(req, ERRSRV, ERRaccess);
925 return;
928 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
929 total_params - 28, STR_TERMINATE,
930 &status);
931 if (!NT_STATUS_IS_OK(status)) {
932 reply_nterror(req, status);
933 return;
936 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
937 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
938 (unsigned int)open_ofun, open_size));
940 if (open_ofun == 0) {
941 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
942 return;
945 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
946 &access_mask,
947 &share_mode,
948 &create_disposition,
949 &create_options)) {
950 reply_doserror(req, ERRDOS, ERRbadaccess);
951 return;
954 /* Any data in this call is an EA list. */
955 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
956 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
957 return;
960 if (total_data != 4) {
961 if (total_data < 10) {
962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
963 return;
966 if (IVAL(pdata,0) > total_data) {
967 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
968 IVAL(pdata,0), (unsigned int)total_data));
969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
970 return;
973 ea_list = read_ea_list(talloc_tos(), pdata + 4,
974 total_data - 4);
975 if (!ea_list) {
976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
977 return;
979 } else if (IVAL(pdata,0) != 4) {
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981 return;
984 status = SMB_VFS_CREATE_FILE(
985 conn, /* conn */
986 req, /* req */
987 0, /* root_dir_fid */
988 fname, /* fname */
989 CFF_DOS_PATH, /* create_file_flags */
990 access_mask, /* access_mask */
991 share_mode, /* share_access */
992 create_disposition, /* create_disposition*/
993 create_options, /* create_options */
994 open_attr, /* file_attributes */
995 oplock_request, /* oplock_request */
996 open_size, /* allocation_size */
997 NULL, /* sd */
998 ea_list, /* ea_list */
999 &fsp, /* result */
1000 &smb_action, /* pinfo */
1001 &sbuf); /* psbuf */
1003 if (!NT_STATUS_IS_OK(status)) {
1004 if (open_was_deferred(req->mid)) {
1005 /* We have re-scheduled this call. */
1006 return;
1008 reply_openerror(req, status);
1009 return;
1012 size = get_file_size_stat(&sbuf);
1013 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1014 mtime = sbuf.st_mtime;
1015 inode = sbuf.st_ino;
1016 if (fattr & aDIR) {
1017 close_file(req, fsp, ERROR_CLOSE);
1018 reply_doserror(req, ERRDOS,ERRnoaccess);
1019 return;
1022 /* Realloc the size of parameters and data we will return */
1023 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1024 if(*pparams == NULL ) {
1025 reply_nterror(req, NT_STATUS_NO_MEMORY);
1026 return;
1028 params = *pparams;
1030 SSVAL(params,0,fsp->fnum);
1031 SSVAL(params,2,fattr);
1032 srv_put_dos_date2(params,4, mtime);
1033 SIVAL(params,8, (uint32)size);
1034 SSVAL(params,12,deny_mode);
1035 SSVAL(params,14,0); /* open_type - file or directory. */
1036 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1038 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1039 smb_action |= EXTENDED_OPLOCK_GRANTED;
1042 SSVAL(params,18,smb_action);
1045 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1047 SIVAL(params,20,inode);
1048 SSVAL(params,24,0); /* Padding. */
1049 if (flags & 8) {
1050 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1051 SIVAL(params, 26, ea_size);
1052 } else {
1053 SIVAL(params, 26, 0);
1056 /* Send the required number of replies */
1057 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1060 /*********************************************************
1061 Routine to check if a given string matches exactly.
1062 as a special case a mask of "." does NOT match. That
1063 is required for correct wildcard semantics
1064 Case can be significant or not.
1065 **********************************************************/
1067 static bool exact_match(connection_struct *conn,
1068 const char *str,
1069 const char *mask)
1071 if (mask[0] == '.' && mask[1] == 0)
1072 return False;
1073 if (dptr_has_wild(conn->dirptr)) {
1074 return False;
1076 if (conn->case_sensitive)
1077 return strcmp(str,mask)==0;
1078 else
1079 return StrCaseCmp(str,mask) == 0;
1082 /****************************************************************************
1083 Return the filetype for UNIX extensions.
1084 ****************************************************************************/
1086 static uint32 unix_filetype(mode_t mode)
1088 if(S_ISREG(mode))
1089 return UNIX_TYPE_FILE;
1090 else if(S_ISDIR(mode))
1091 return UNIX_TYPE_DIR;
1092 #ifdef S_ISLNK
1093 else if(S_ISLNK(mode))
1094 return UNIX_TYPE_SYMLINK;
1095 #endif
1096 #ifdef S_ISCHR
1097 else if(S_ISCHR(mode))
1098 return UNIX_TYPE_CHARDEV;
1099 #endif
1100 #ifdef S_ISBLK
1101 else if(S_ISBLK(mode))
1102 return UNIX_TYPE_BLKDEV;
1103 #endif
1104 #ifdef S_ISFIFO
1105 else if(S_ISFIFO(mode))
1106 return UNIX_TYPE_FIFO;
1107 #endif
1108 #ifdef S_ISSOCK
1109 else if(S_ISSOCK(mode))
1110 return UNIX_TYPE_SOCKET;
1111 #endif
1113 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1114 return UNIX_TYPE_UNKNOWN;
1117 /****************************************************************************
1118 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1119 ****************************************************************************/
1121 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1123 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1124 SMB_STRUCT_STAT *psbuf,
1125 uint32 perms,
1126 enum perm_type ptype,
1127 mode_t *ret_perms)
1129 mode_t ret = 0;
1131 if (perms == SMB_MODE_NO_CHANGE) {
1132 if (!VALID_STAT(*psbuf)) {
1133 return NT_STATUS_INVALID_PARAMETER;
1134 } else {
1135 *ret_perms = psbuf->st_mode;
1136 return NT_STATUS_OK;
1140 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1141 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1142 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1143 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1144 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1145 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1146 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1147 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1148 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1149 #ifdef S_ISVTX
1150 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1151 #endif
1152 #ifdef S_ISGID
1153 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1154 #endif
1155 #ifdef S_ISUID
1156 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1157 #endif
1159 switch (ptype) {
1160 case PERM_NEW_FILE:
1161 /* Apply mode mask */
1162 ret &= lp_create_mask(SNUM(conn));
1163 /* Add in force bits */
1164 ret |= lp_force_create_mode(SNUM(conn));
1165 break;
1166 case PERM_NEW_DIR:
1167 ret &= lp_dir_mask(SNUM(conn));
1168 /* Add in force bits */
1169 ret |= lp_force_dir_mode(SNUM(conn));
1170 break;
1171 case PERM_EXISTING_FILE:
1172 /* Apply mode mask */
1173 ret &= lp_security_mask(SNUM(conn));
1174 /* Add in force bits */
1175 ret |= lp_force_security_mode(SNUM(conn));
1176 break;
1177 case PERM_EXISTING_DIR:
1178 /* Apply mode mask */
1179 ret &= lp_dir_security_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_dir_security_mode(SNUM(conn));
1182 break;
1185 *ret_perms = ret;
1186 return NT_STATUS_OK;
1189 /****************************************************************************
1190 Needed to show the msdfs symlinks as directories. Modifies psbuf
1191 to be a directory if it's a msdfs link.
1192 ****************************************************************************/
1194 static bool check_msdfs_link(connection_struct *conn,
1195 const char *pathname,
1196 SMB_STRUCT_STAT *psbuf)
1198 int saved_errno = errno;
1199 if(lp_host_msdfs() &&
1200 lp_msdfs_root(SNUM(conn)) &&
1201 is_msdfs_link(conn, pathname, psbuf)) {
1203 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1204 "as a directory\n",
1205 pathname));
1206 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1207 errno = saved_errno;
1208 return true;
1210 errno = saved_errno;
1211 return false;
1215 /****************************************************************************
1216 Get a level dependent lanman2 dir entry.
1217 ****************************************************************************/
1219 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1220 connection_struct *conn,
1221 uint16 flags2,
1222 const char *path_mask,
1223 uint32 dirtype,
1224 int info_level,
1225 int requires_resume_key,
1226 bool dont_descend,
1227 bool ask_sharemode,
1228 char **ppdata,
1229 char *base_data,
1230 char *end_data,
1231 int space_remaining,
1232 bool *out_of_space,
1233 bool *got_exact_match,
1234 int *last_entry_off,
1235 struct ea_list *name_list)
1237 const char *dname;
1238 bool found = False;
1239 SMB_STRUCT_STAT sbuf;
1240 const char *mask = NULL;
1241 char *pathreal = NULL;
1242 const char *fname = NULL;
1243 char *p, *q, *pdata = *ppdata;
1244 uint32 reskey=0;
1245 long prev_dirpos=0;
1246 uint32 mode=0;
1247 SMB_OFF_T file_size = 0;
1248 uint64_t allocation_size = 0;
1249 uint32 len;
1250 struct timespec mdate_ts, adate_ts, create_date_ts;
1251 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1252 char *nameptr;
1253 char *last_entry_ptr;
1254 bool was_8_3;
1255 uint32 nt_extmode; /* Used for NT connections instead of mode */
1256 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1257 bool check_mangled_names = lp_manglednames(conn->params);
1258 char mangled_name[13]; /* mangled 8.3 name. */
1260 *out_of_space = False;
1261 *got_exact_match = False;
1263 ZERO_STRUCT(mdate_ts);
1264 ZERO_STRUCT(adate_ts);
1265 ZERO_STRUCT(create_date_ts);
1267 if (!conn->dirptr) {
1268 return(False);
1271 p = strrchr_m(path_mask,'/');
1272 if(p != NULL) {
1273 if(p[1] == '\0') {
1274 mask = talloc_strdup(ctx,"*.*");
1275 } else {
1276 mask = p+1;
1278 } else {
1279 mask = path_mask;
1282 while (!found) {
1283 bool got_match;
1284 bool ms_dfs_link = False;
1286 /* Needed if we run out of space */
1287 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1288 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1291 * Due to bugs in NT client redirectors we are not using
1292 * resume keys any more - set them to zero.
1293 * Check out the related comments in findfirst/findnext.
1294 * JRA.
1297 reskey = 0;
1299 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1300 (long)conn->dirptr,curr_dirpos));
1302 if (!dname) {
1303 return(False);
1307 * fname may get mangled, dname is never mangled.
1308 * Whenever we're accessing the filesystem we use
1309 * pathreal which is composed from dname.
1312 pathreal = NULL;
1313 fname = dname;
1315 /* Mangle fname if it's an illegal name. */
1316 if (mangle_must_mangle(dname,conn->params)) {
1317 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1318 continue; /* Error - couldn't mangle. */
1320 fname = mangled_name;
1323 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1324 got_match = mask_match(fname, mask, conn->case_sensitive);
1327 if(!got_match && check_mangled_names &&
1328 !mangle_is_8_3(fname, False, conn->params)) {
1330 * It turns out that NT matches wildcards against
1331 * both long *and* short names. This may explain some
1332 * of the wildcard wierdness from old DOS clients
1333 * that some people have been seeing.... JRA.
1335 /* Force the mangling into 8.3. */
1336 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1337 continue; /* Error - couldn't mangle. */
1340 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1341 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1345 if (got_match) {
1346 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1348 if (dont_descend && !isdots) {
1349 continue;
1352 if (needslash) {
1353 pathreal = NULL;
1354 pathreal = talloc_asprintf(ctx,
1355 "%s/%s",
1356 conn->dirpath,
1357 dname);
1358 } else {
1359 pathreal = talloc_asprintf(ctx,
1360 "%s%s",
1361 conn->dirpath,
1362 dname);
1365 if (!pathreal) {
1366 return False;
1369 if (INFO_LEVEL_IS_UNIX(info_level)) {
1370 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1371 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1372 pathreal,strerror(errno)));
1373 TALLOC_FREE(pathreal);
1374 continue;
1376 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1377 /* Needed to show the msdfs symlinks as
1378 * directories */
1380 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1381 if (!ms_dfs_link) {
1382 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1383 pathreal,strerror(errno)));
1384 TALLOC_FREE(pathreal);
1385 continue;
1389 if (ms_dfs_link) {
1390 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1391 } else {
1392 mode = dos_mode(conn,pathreal,&sbuf);
1395 if (!dir_check_ftype(conn,mode,dirtype)) {
1396 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1397 TALLOC_FREE(pathreal);
1398 continue;
1401 if (!(mode & aDIR)) {
1402 file_size = get_file_size_stat(&sbuf);
1404 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1406 mdate_ts = get_mtimespec(&sbuf);
1407 adate_ts = get_atimespec(&sbuf);
1408 create_date_ts = get_create_timespec(&sbuf,
1409 lp_fake_dir_create_times(SNUM(conn)));
1411 if (ask_sharemode) {
1412 struct timespec write_time_ts;
1413 struct file_id fileid;
1415 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1416 get_file_infos(fileid, NULL, &write_time_ts);
1417 if (!null_timespec(write_time_ts)) {
1418 mdate_ts = write_time_ts;
1422 if (lp_dos_filetime_resolution(SNUM(conn))) {
1423 dos_filetime_timespec(&create_date_ts);
1424 dos_filetime_timespec(&mdate_ts);
1425 dos_filetime_timespec(&adate_ts);
1428 create_date = convert_timespec_to_time_t(create_date_ts);
1429 mdate = convert_timespec_to_time_t(mdate_ts);
1430 adate = convert_timespec_to_time_t(adate_ts);
1432 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1433 pathreal,fname));
1435 found = True;
1437 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1441 p = pdata;
1442 last_entry_ptr = p;
1444 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1446 switch (info_level) {
1447 case SMB_FIND_INFO_STANDARD:
1448 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1449 if(requires_resume_key) {
1450 SIVAL(p,0,reskey);
1451 p += 4;
1453 srv_put_dos_date2(p,0,create_date);
1454 srv_put_dos_date2(p,4,adate);
1455 srv_put_dos_date2(p,8,mdate);
1456 SIVAL(p,12,(uint32)file_size);
1457 SIVAL(p,16,(uint32)allocation_size);
1458 SSVAL(p,20,mode);
1459 p += 23;
1460 nameptr = p;
1461 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1462 p += ucs2_align(base_data, p, 0);
1464 len = srvstr_push(base_data, flags2, p,
1465 fname, PTR_DIFF(end_data, p),
1466 STR_TERMINATE);
1467 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1468 if (len > 2) {
1469 SCVAL(nameptr, -1, len - 2);
1470 } else {
1471 SCVAL(nameptr, -1, 0);
1473 } else {
1474 if (len > 1) {
1475 SCVAL(nameptr, -1, len - 1);
1476 } else {
1477 SCVAL(nameptr, -1, 0);
1480 p += len;
1481 break;
1483 case SMB_FIND_EA_SIZE:
1484 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1485 if(requires_resume_key) {
1486 SIVAL(p,0,reskey);
1487 p += 4;
1489 srv_put_dos_date2(p,0,create_date);
1490 srv_put_dos_date2(p,4,adate);
1491 srv_put_dos_date2(p,8,mdate);
1492 SIVAL(p,12,(uint32)file_size);
1493 SIVAL(p,16,(uint32)allocation_size);
1494 SSVAL(p,20,mode);
1496 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1497 SIVAL(p,22,ea_size); /* Extended attributes */
1499 p += 27;
1500 nameptr = p - 1;
1501 len = srvstr_push(base_data, flags2,
1502 p, fname, PTR_DIFF(end_data, p),
1503 STR_TERMINATE | STR_NOALIGN);
1504 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1505 if (len > 2) {
1506 len -= 2;
1507 } else {
1508 len = 0;
1510 } else {
1511 if (len > 1) {
1512 len -= 1;
1513 } else {
1514 len = 0;
1517 SCVAL(nameptr,0,len);
1518 p += len;
1519 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1520 break;
1522 case SMB_FIND_EA_LIST:
1524 struct ea_list *file_list = NULL;
1525 size_t ea_len = 0;
1527 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1528 if (!name_list) {
1529 return False;
1531 if(requires_resume_key) {
1532 SIVAL(p,0,reskey);
1533 p += 4;
1535 srv_put_dos_date2(p,0,create_date);
1536 srv_put_dos_date2(p,4,adate);
1537 srv_put_dos_date2(p,8,mdate);
1538 SIVAL(p,12,(uint32)file_size);
1539 SIVAL(p,16,(uint32)allocation_size);
1540 SSVAL(p,20,mode);
1541 p += 22; /* p now points to the EA area. */
1543 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1544 name_list = ea_list_union(name_list, file_list, &ea_len);
1546 /* We need to determine if this entry will fit in the space available. */
1547 /* Max string size is 255 bytes. */
1548 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1549 /* Move the dirptr back to prev_dirpos */
1550 dptr_SeekDir(conn->dirptr, prev_dirpos);
1551 *out_of_space = True;
1552 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1553 return False; /* Not finished - just out of space */
1556 /* Push the ea_data followed by the name. */
1557 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1558 nameptr = p;
1559 len = srvstr_push(base_data, flags2,
1560 p + 1, fname, PTR_DIFF(end_data, p+1),
1561 STR_TERMINATE | STR_NOALIGN);
1562 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1563 if (len > 2) {
1564 len -= 2;
1565 } else {
1566 len = 0;
1568 } else {
1569 if (len > 1) {
1570 len -= 1;
1571 } else {
1572 len = 0;
1575 SCVAL(nameptr,0,len);
1576 p += len + 1;
1577 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1578 break;
1581 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1582 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1583 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1584 p += 4;
1585 SIVAL(p,0,reskey); p += 4;
1586 put_long_date_timespec(p,create_date_ts); p += 8;
1587 put_long_date_timespec(p,adate_ts); p += 8;
1588 put_long_date_timespec(p,mdate_ts); p += 8;
1589 put_long_date_timespec(p,mdate_ts); p += 8;
1590 SOFF_T(p,0,file_size); p += 8;
1591 SOFF_T(p,0,allocation_size); p += 8;
1592 SIVAL(p,0,nt_extmode); p += 4;
1593 q = p; p += 4; /* q is placeholder for name length. */
1595 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1596 SIVAL(p,0,ea_size); /* Extended attributes */
1597 p += 4;
1599 /* Clear the short name buffer. This is
1600 * IMPORTANT as not doing so will trigger
1601 * a Win2k client bug. JRA.
1603 if (!was_8_3 && check_mangled_names) {
1604 if (!name_to_8_3(fname,mangled_name,True,
1605 conn->params)) {
1606 /* Error - mangle failed ! */
1607 memset(mangled_name,'\0',12);
1609 mangled_name[12] = 0;
1610 len = srvstr_push(base_data, flags2,
1611 p+2, mangled_name, 24,
1612 STR_UPPER|STR_UNICODE);
1613 if (len < 24) {
1614 memset(p + 2 + len,'\0',24 - len);
1616 SSVAL(p, 0, len);
1617 } else {
1618 memset(p,'\0',26);
1620 p += 2 + 24;
1621 len = srvstr_push(base_data, flags2, p,
1622 fname, PTR_DIFF(end_data, p),
1623 STR_TERMINATE_ASCII);
1624 SIVAL(q,0,len);
1625 p += len;
1626 SIVAL(p,0,0); /* Ensure any padding is null. */
1627 len = PTR_DIFF(p, pdata);
1628 len = (len + 3) & ~3;
1629 SIVAL(pdata,0,len);
1630 p = pdata + len;
1631 break;
1633 case SMB_FIND_FILE_DIRECTORY_INFO:
1634 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1635 p += 4;
1636 SIVAL(p,0,reskey); p += 4;
1637 put_long_date_timespec(p,create_date_ts); p += 8;
1638 put_long_date_timespec(p,adate_ts); p += 8;
1639 put_long_date_timespec(p,mdate_ts); p += 8;
1640 put_long_date_timespec(p,mdate_ts); p += 8;
1641 SOFF_T(p,0,file_size); p += 8;
1642 SOFF_T(p,0,allocation_size); p += 8;
1643 SIVAL(p,0,nt_extmode); p += 4;
1644 len = srvstr_push(base_data, flags2,
1645 p + 4, fname, PTR_DIFF(end_data, p+4),
1646 STR_TERMINATE_ASCII);
1647 SIVAL(p,0,len);
1648 p += 4 + len;
1649 SIVAL(p,0,0); /* Ensure any padding is null. */
1650 len = PTR_DIFF(p, pdata);
1651 len = (len + 3) & ~3;
1652 SIVAL(pdata,0,len);
1653 p = pdata + len;
1654 break;
1656 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1657 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1658 p += 4;
1659 SIVAL(p,0,reskey); p += 4;
1660 put_long_date_timespec(p,create_date_ts); p += 8;
1661 put_long_date_timespec(p,adate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 put_long_date_timespec(p,mdate_ts); p += 8;
1664 SOFF_T(p,0,file_size); p += 8;
1665 SOFF_T(p,0,allocation_size); p += 8;
1666 SIVAL(p,0,nt_extmode); p += 4;
1667 q = p; p += 4; /* q is placeholder for name length. */
1669 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1670 SIVAL(p,0,ea_size); /* Extended attributes */
1671 p +=4;
1673 len = srvstr_push(base_data, flags2, p,
1674 fname, PTR_DIFF(end_data, p),
1675 STR_TERMINATE_ASCII);
1676 SIVAL(q, 0, len);
1677 p += len;
1679 SIVAL(p,0,0); /* Ensure any padding is null. */
1680 len = PTR_DIFF(p, pdata);
1681 len = (len + 3) & ~3;
1682 SIVAL(pdata,0,len);
1683 p = pdata + len;
1684 break;
1686 case SMB_FIND_FILE_NAMES_INFO:
1687 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1688 p += 4;
1689 SIVAL(p,0,reskey); p += 4;
1690 p += 4;
1691 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1692 acl on a dir (tridge) */
1693 len = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1695 STR_TERMINATE_ASCII);
1696 SIVAL(p, -4, len);
1697 p += len;
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1699 len = PTR_DIFF(p, pdata);
1700 len = (len + 3) & ~3;
1701 SIVAL(pdata,0,len);
1702 p = pdata + len;
1703 break;
1705 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1706 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1707 p += 4;
1708 SIVAL(p,0,reskey); p += 4;
1709 put_long_date_timespec(p,create_date_ts); p += 8;
1710 put_long_date_timespec(p,adate_ts); p += 8;
1711 put_long_date_timespec(p,mdate_ts); p += 8;
1712 put_long_date_timespec(p,mdate_ts); p += 8;
1713 SOFF_T(p,0,file_size); p += 8;
1714 SOFF_T(p,0,allocation_size); p += 8;
1715 SIVAL(p,0,nt_extmode); p += 4;
1716 q = p; p += 4; /* q is placeholder for name length. */
1718 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1719 SIVAL(p,0,ea_size); /* Extended attributes */
1720 p +=4;
1722 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1723 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1724 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1725 len = srvstr_push(base_data, flags2, p,
1726 fname, PTR_DIFF(end_data, p),
1727 STR_TERMINATE_ASCII);
1728 SIVAL(q, 0, len);
1729 p += len;
1730 SIVAL(p,0,0); /* Ensure any padding is null. */
1731 len = PTR_DIFF(p, pdata);
1732 len = (len + 3) & ~3;
1733 SIVAL(pdata,0,len);
1734 p = pdata + len;
1735 break;
1737 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1738 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1739 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1740 p += 4;
1741 SIVAL(p,0,reskey); p += 4;
1742 put_long_date_timespec(p,create_date_ts); p += 8;
1743 put_long_date_timespec(p,adate_ts); p += 8;
1744 put_long_date_timespec(p,mdate_ts); p += 8;
1745 put_long_date_timespec(p,mdate_ts); p += 8;
1746 SOFF_T(p,0,file_size); p += 8;
1747 SOFF_T(p,0,allocation_size); p += 8;
1748 SIVAL(p,0,nt_extmode); p += 4;
1749 q = p; p += 4; /* q is placeholder for name length */
1751 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1752 SIVAL(p,0,ea_size); /* Extended attributes */
1753 p +=4;
1755 /* Clear the short name buffer. This is
1756 * IMPORTANT as not doing so will trigger
1757 * a Win2k client bug. JRA.
1759 if (!was_8_3 && check_mangled_names) {
1760 if (!name_to_8_3(fname,mangled_name,True,
1761 conn->params)) {
1762 /* Error - mangle failed ! */
1763 memset(mangled_name,'\0',12);
1765 mangled_name[12] = 0;
1766 len = srvstr_push(base_data, flags2,
1767 p+2, mangled_name, 24,
1768 STR_UPPER|STR_UNICODE);
1769 SSVAL(p, 0, len);
1770 if (len < 24) {
1771 memset(p + 2 + len,'\0',24 - len);
1773 SSVAL(p, 0, len);
1774 } else {
1775 memset(p,'\0',26);
1777 p += 26;
1778 SSVAL(p,0,0); p += 2; /* Reserved ? */
1779 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1780 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1781 len = srvstr_push(base_data, flags2, p,
1782 fname, PTR_DIFF(end_data, p),
1783 STR_TERMINATE_ASCII);
1784 SIVAL(q,0,len);
1785 p += len;
1786 SIVAL(p,0,0); /* Ensure any padding is null. */
1787 len = PTR_DIFF(p, pdata);
1788 len = (len + 3) & ~3;
1789 SIVAL(pdata,0,len);
1790 p = pdata + len;
1791 break;
1793 /* CIFS UNIX Extension. */
1795 case SMB_FIND_FILE_UNIX:
1796 case SMB_FIND_FILE_UNIX_INFO2:
1797 p+= 4;
1798 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1800 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1802 if (info_level == SMB_FIND_FILE_UNIX) {
1803 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1804 p = store_file_unix_basic(conn, p,
1805 NULL, &sbuf);
1806 len = srvstr_push(base_data, flags2, p,
1807 fname, PTR_DIFF(end_data, p),
1808 STR_TERMINATE);
1809 } else {
1810 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1811 p = store_file_unix_basic_info2(conn, p,
1812 NULL, &sbuf);
1813 nameptr = p;
1814 p += 4;
1815 len = srvstr_push(base_data, flags2, p, fname,
1816 PTR_DIFF(end_data, p), 0);
1817 SIVAL(nameptr, 0, len);
1820 p += len;
1821 SIVAL(p,0,0); /* Ensure any padding is null. */
1823 len = PTR_DIFF(p, pdata);
1824 len = (len + 3) & ~3;
1825 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1826 p = pdata + len;
1827 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1829 break;
1831 default:
1832 return(False);
1836 if (PTR_DIFF(p,pdata) > space_remaining) {
1837 /* Move the dirptr back to prev_dirpos */
1838 dptr_SeekDir(conn->dirptr, prev_dirpos);
1839 *out_of_space = True;
1840 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1841 return False; /* Not finished - just out of space */
1844 /* Setup the last entry pointer, as an offset from base_data */
1845 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1846 /* Advance the data pointer to the next slot */
1847 *ppdata = p;
1849 return(found);
1852 /****************************************************************************
1853 Reply to a TRANS2_FINDFIRST.
1854 ****************************************************************************/
1856 static void call_trans2findfirst(connection_struct *conn,
1857 struct smb_request *req,
1858 char **pparams, int total_params,
1859 char **ppdata, int total_data,
1860 unsigned int max_data_bytes)
1862 /* We must be careful here that we don't return more than the
1863 allowed number of data bytes. If this means returning fewer than
1864 maxentries then so be it. We assume that the redirector has
1865 enough room for the fixed number of parameter bytes it has
1866 requested. */
1867 char *params = *pparams;
1868 char *pdata = *ppdata;
1869 char *data_end;
1870 uint32 dirtype;
1871 int maxentries;
1872 uint16 findfirst_flags;
1873 bool close_after_first;
1874 bool close_if_end;
1875 bool requires_resume_key;
1876 int info_level;
1877 char *directory = NULL;
1878 char *mask = NULL;
1879 char *p;
1880 int last_entry_off=0;
1881 int dptr_num = -1;
1882 int numentries = 0;
1883 int i;
1884 bool finished = False;
1885 bool dont_descend = False;
1886 bool out_of_space = False;
1887 int space_remaining;
1888 bool mask_contains_wcard = False;
1889 SMB_STRUCT_STAT sbuf;
1890 struct ea_list *ea_list = NULL;
1891 NTSTATUS ntstatus = NT_STATUS_OK;
1892 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1893 TALLOC_CTX *ctx = talloc_tos();
1895 if (total_params < 13) {
1896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1897 return;
1900 dirtype = SVAL(params,0);
1901 maxentries = SVAL(params,2);
1902 findfirst_flags = SVAL(params,4);
1903 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1904 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1905 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1906 info_level = SVAL(params,6);
1908 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1909 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1910 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1911 info_level, max_data_bytes));
1913 if (!maxentries) {
1914 /* W2K3 seems to treat zero as 1. */
1915 maxentries = 1;
1918 switch (info_level) {
1919 case SMB_FIND_INFO_STANDARD:
1920 case SMB_FIND_EA_SIZE:
1921 case SMB_FIND_EA_LIST:
1922 case SMB_FIND_FILE_DIRECTORY_INFO:
1923 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1924 case SMB_FIND_FILE_NAMES_INFO:
1925 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1926 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1927 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1928 break;
1929 case SMB_FIND_FILE_UNIX:
1930 case SMB_FIND_FILE_UNIX_INFO2:
1931 /* Always use filesystem for UNIX mtime query. */
1932 ask_sharemode = false;
1933 if (!lp_unix_extensions()) {
1934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1935 return;
1937 break;
1938 default:
1939 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1940 return;
1943 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1944 params+12, total_params - 12,
1945 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1946 if (!NT_STATUS_IS_OK(ntstatus)) {
1947 reply_nterror(req, ntstatus);
1948 return;
1951 ntstatus = resolve_dfspath_wcard(ctx, conn,
1952 req->flags2 & FLAGS2_DFS_PATHNAMES,
1953 directory,
1954 &directory,
1955 &mask_contains_wcard);
1956 if (!NT_STATUS_IS_OK(ntstatus)) {
1957 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1958 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1959 ERRSRV, ERRbadpath);
1960 return;
1962 reply_nterror(req, ntstatus);
1963 return;
1966 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1967 if (!NT_STATUS_IS_OK(ntstatus)) {
1968 reply_nterror(req, ntstatus);
1969 return;
1972 ntstatus = check_name(conn, directory);
1973 if (!NT_STATUS_IS_OK(ntstatus)) {
1974 reply_nterror(req, ntstatus);
1975 return;
1978 p = strrchr_m(directory,'/');
1979 if(p == NULL) {
1980 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1981 if((directory[0] == '.') && (directory[1] == '\0')) {
1982 mask = talloc_strdup(ctx,"*");
1983 if (!mask) {
1984 reply_nterror(req, NT_STATUS_NO_MEMORY);
1985 return;
1987 mask_contains_wcard = True;
1989 directory = talloc_strdup(talloc_tos(), "./");
1990 if (!directory) {
1991 reply_nterror(req, NT_STATUS_NO_MEMORY);
1992 return;
1994 } else {
1995 *p = 0;
1998 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2000 if (info_level == SMB_FIND_EA_LIST) {
2001 uint32 ea_size;
2003 if (total_data < 4) {
2004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2005 return;
2008 ea_size = IVAL(pdata,0);
2009 if (ea_size != total_data) {
2010 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2011 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2013 return;
2016 if (!lp_ea_support(SNUM(conn))) {
2017 reply_doserror(req, ERRDOS, ERReasnotsupported);
2018 return;
2021 /* Pull out the list of names. */
2022 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2023 if (!ea_list) {
2024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2025 return;
2029 *ppdata = (char *)SMB_REALLOC(
2030 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2031 if(*ppdata == NULL ) {
2032 reply_nterror(req, NT_STATUS_NO_MEMORY);
2033 return;
2035 pdata = *ppdata;
2036 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2038 /* Realloc the params space */
2039 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2040 if (*pparams == NULL) {
2041 reply_nterror(req, NT_STATUS_NO_MEMORY);
2042 return;
2044 params = *pparams;
2046 /* Save the wildcard match and attribs we are using on this directory -
2047 needed as lanman2 assumes these are being saved between calls */
2049 ntstatus = dptr_create(conn,
2050 directory,
2051 False,
2052 True,
2053 req->smbpid,
2054 mask,
2055 mask_contains_wcard,
2056 dirtype,
2057 &conn->dirptr);
2059 if (!NT_STATUS_IS_OK(ntstatus)) {
2060 reply_nterror(req, ntstatus);
2061 return;
2064 dptr_num = dptr_dnum(conn->dirptr);
2065 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2067 /* Initialize per TRANS2_FIND_FIRST operation data */
2068 dptr_init_search_op(conn->dirptr);
2070 /* We don't need to check for VOL here as this is returned by
2071 a different TRANS2 call. */
2073 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2074 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2075 dont_descend = True;
2077 p = pdata;
2078 space_remaining = max_data_bytes;
2079 out_of_space = False;
2081 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2082 bool got_exact_match = False;
2084 /* this is a heuristic to avoid seeking the dirptr except when
2085 absolutely necessary. It allows for a filename of about 40 chars */
2086 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2087 out_of_space = True;
2088 finished = False;
2089 } else {
2090 finished = !get_lanman2_dir_entry(ctx,
2091 conn,
2092 req->flags2,
2093 mask,dirtype,info_level,
2094 requires_resume_key,dont_descend,
2095 ask_sharemode,
2096 &p,pdata,data_end,
2097 space_remaining, &out_of_space,
2098 &got_exact_match,
2099 &last_entry_off, ea_list);
2102 if (finished && out_of_space)
2103 finished = False;
2105 if (!finished && !out_of_space)
2106 numentries++;
2109 * As an optimisation if we know we aren't looking
2110 * for a wildcard name (ie. the name matches the wildcard exactly)
2111 * then we can finish on any (first) match.
2112 * This speeds up large directory searches. JRA.
2115 if(got_exact_match)
2116 finished = True;
2118 /* Ensure space_remaining never goes -ve. */
2119 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2120 space_remaining = 0;
2121 out_of_space = true;
2122 } else {
2123 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2127 /* Check if we can close the dirptr */
2128 if(close_after_first || (finished && close_if_end)) {
2129 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2130 dptr_close(&dptr_num);
2134 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2135 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2136 * the protocol level is less than NT1. Tested with smbclient. JRA.
2137 * This should fix the OS/2 client bug #2335.
2140 if(numentries == 0) {
2141 dptr_close(&dptr_num);
2142 if (Protocol < PROTOCOL_NT1) {
2143 reply_doserror(req, ERRDOS, ERRnofiles);
2144 return;
2145 } else {
2146 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2147 ERRDOS, ERRbadfile);
2148 return;
2152 /* At this point pdata points to numentries directory entries. */
2154 /* Set up the return parameter block */
2155 SSVAL(params,0,dptr_num);
2156 SSVAL(params,2,numentries);
2157 SSVAL(params,4,finished);
2158 SSVAL(params,6,0); /* Never an EA error */
2159 SSVAL(params,8,last_entry_off);
2161 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2162 max_data_bytes);
2164 if ((! *directory) && dptr_path(dptr_num)) {
2165 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2166 if (!directory) {
2167 reply_nterror(req, NT_STATUS_NO_MEMORY);
2171 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2172 smb_fn_name(req->cmd),
2173 mask, directory, dirtype, numentries ) );
2176 * Force a name mangle here to ensure that the
2177 * mask as an 8.3 name is top of the mangled cache.
2178 * The reasons for this are subtle. Don't remove
2179 * this code unless you know what you are doing
2180 * (see PR#13758). JRA.
2183 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2184 char mangled_name[13];
2185 name_to_8_3(mask, mangled_name, True, conn->params);
2188 return;
2191 /****************************************************************************
2192 Reply to a TRANS2_FINDNEXT.
2193 ****************************************************************************/
2195 static void call_trans2findnext(connection_struct *conn,
2196 struct smb_request *req,
2197 char **pparams, int total_params,
2198 char **ppdata, int total_data,
2199 unsigned int max_data_bytes)
2201 /* We must be careful here that we don't return more than the
2202 allowed number of data bytes. If this means returning fewer than
2203 maxentries then so be it. We assume that the redirector has
2204 enough room for the fixed number of parameter bytes it has
2205 requested. */
2206 char *params = *pparams;
2207 char *pdata = *ppdata;
2208 char *data_end;
2209 int dptr_num;
2210 int maxentries;
2211 uint16 info_level;
2212 uint32 resume_key;
2213 uint16 findnext_flags;
2214 bool close_after_request;
2215 bool close_if_end;
2216 bool requires_resume_key;
2217 bool continue_bit;
2218 bool mask_contains_wcard = False;
2219 char *resume_name = NULL;
2220 const char *mask = NULL;
2221 const char *directory = NULL;
2222 char *p = NULL;
2223 uint16 dirtype;
2224 int numentries = 0;
2225 int i, last_entry_off=0;
2226 bool finished = False;
2227 bool dont_descend = False;
2228 bool out_of_space = False;
2229 int space_remaining;
2230 struct ea_list *ea_list = NULL;
2231 NTSTATUS ntstatus = NT_STATUS_OK;
2232 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2233 TALLOC_CTX *ctx = talloc_tos();
2235 if (total_params < 13) {
2236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2237 return;
2240 dptr_num = SVAL(params,0);
2241 maxentries = SVAL(params,2);
2242 info_level = SVAL(params,4);
2243 resume_key = IVAL(params,6);
2244 findnext_flags = SVAL(params,10);
2245 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2246 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2247 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2248 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2250 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2251 params+12,
2252 total_params - 12, STR_TERMINATE, &ntstatus,
2253 &mask_contains_wcard);
2254 if (!NT_STATUS_IS_OK(ntstatus)) {
2255 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2256 complain (it thinks we're asking for the directory above the shared
2257 path or an invalid name). Catch this as the resume name is only compared, never used in
2258 a file access. JRA. */
2259 srvstr_pull_talloc(ctx, params, req->flags2,
2260 &resume_name, params+12,
2261 total_params - 12,
2262 STR_TERMINATE);
2264 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2265 reply_nterror(req, ntstatus);
2266 return;
2270 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2271 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2272 resume_key = %d resume name = %s continue=%d level = %d\n",
2273 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2274 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2276 if (!maxentries) {
2277 /* W2K3 seems to treat zero as 1. */
2278 maxentries = 1;
2281 switch (info_level) {
2282 case SMB_FIND_INFO_STANDARD:
2283 case SMB_FIND_EA_SIZE:
2284 case SMB_FIND_EA_LIST:
2285 case SMB_FIND_FILE_DIRECTORY_INFO:
2286 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2287 case SMB_FIND_FILE_NAMES_INFO:
2288 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2289 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2290 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2291 break;
2292 case SMB_FIND_FILE_UNIX:
2293 case SMB_FIND_FILE_UNIX_INFO2:
2294 /* Always use filesystem for UNIX mtime query. */
2295 ask_sharemode = false;
2296 if (!lp_unix_extensions()) {
2297 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2298 return;
2300 break;
2301 default:
2302 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2303 return;
2306 if (info_level == SMB_FIND_EA_LIST) {
2307 uint32 ea_size;
2309 if (total_data < 4) {
2310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2311 return;
2314 ea_size = IVAL(pdata,0);
2315 if (ea_size != total_data) {
2316 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2317 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2319 return;
2322 if (!lp_ea_support(SNUM(conn))) {
2323 reply_doserror(req, ERRDOS, ERReasnotsupported);
2324 return;
2327 /* Pull out the list of names. */
2328 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2329 if (!ea_list) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 return;
2335 *ppdata = (char *)SMB_REALLOC(
2336 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2337 if(*ppdata == NULL) {
2338 reply_nterror(req, NT_STATUS_NO_MEMORY);
2339 return;
2342 pdata = *ppdata;
2343 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2345 /* Realloc the params space */
2346 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2347 if(*pparams == NULL ) {
2348 reply_nterror(req, NT_STATUS_NO_MEMORY);
2349 return;
2352 params = *pparams;
2354 /* Check that the dptr is valid */
2355 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2356 reply_doserror(req, ERRDOS, ERRnofiles);
2357 return;
2360 string_set(&conn->dirpath,dptr_path(dptr_num));
2362 /* Get the wildcard mask from the dptr */
2363 if((p = dptr_wcard(dptr_num))== NULL) {
2364 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2365 reply_doserror(req, ERRDOS, ERRnofiles);
2366 return;
2369 mask = p;
2370 directory = conn->dirpath;
2372 /* Get the attr mask from the dptr */
2373 dirtype = dptr_attr(dptr_num);
2375 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2376 dptr_num, mask, dirtype,
2377 (long)conn->dirptr,
2378 dptr_TellDir(conn->dirptr)));
2380 /* Initialize per TRANS2_FIND_NEXT operation data */
2381 dptr_init_search_op(conn->dirptr);
2383 /* We don't need to check for VOL here as this is returned by
2384 a different TRANS2 call. */
2386 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2387 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2388 dont_descend = True;
2390 p = pdata;
2391 space_remaining = max_data_bytes;
2392 out_of_space = False;
2395 * Seek to the correct position. We no longer use the resume key but
2396 * depend on the last file name instead.
2399 if(*resume_name && !continue_bit) {
2400 SMB_STRUCT_STAT st;
2402 long current_pos = 0;
2404 * Remember, name_to_8_3 is called by
2405 * get_lanman2_dir_entry(), so the resume name
2406 * could be mangled. Ensure we check the unmangled name.
2409 if (mangle_is_mangled(resume_name, conn->params)) {
2410 char *new_resume_name = NULL;
2411 mangle_lookup_name_from_8_3(ctx,
2412 resume_name,
2413 &new_resume_name,
2414 conn->params);
2415 if (new_resume_name) {
2416 resume_name = new_resume_name;
2421 * Fix for NT redirector problem triggered by resume key indexes
2422 * changing between directory scans. We now return a resume key of 0
2423 * and instead look for the filename to continue from (also given
2424 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2425 * findfirst/findnext (as is usual) then the directory pointer
2426 * should already be at the correct place.
2429 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2430 } /* end if resume_name && !continue_bit */
2432 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2433 bool got_exact_match = False;
2435 /* this is a heuristic to avoid seeking the dirptr except when
2436 absolutely necessary. It allows for a filename of about 40 chars */
2437 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2438 out_of_space = True;
2439 finished = False;
2440 } else {
2441 finished = !get_lanman2_dir_entry(ctx,
2442 conn,
2443 req->flags2,
2444 mask,dirtype,info_level,
2445 requires_resume_key,dont_descend,
2446 ask_sharemode,
2447 &p,pdata,data_end,
2448 space_remaining, &out_of_space,
2449 &got_exact_match,
2450 &last_entry_off, ea_list);
2453 if (finished && out_of_space)
2454 finished = False;
2456 if (!finished && !out_of_space)
2457 numentries++;
2460 * As an optimisation if we know we aren't looking
2461 * for a wildcard name (ie. the name matches the wildcard exactly)
2462 * then we can finish on any (first) match.
2463 * This speeds up large directory searches. JRA.
2466 if(got_exact_match)
2467 finished = True;
2469 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2472 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2473 smb_fn_name(req->cmd),
2474 mask, directory, dirtype, numentries ) );
2476 /* Check if we can close the dirptr */
2477 if(close_after_request || (finished && close_if_end)) {
2478 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2479 dptr_close(&dptr_num); /* This frees up the saved mask */
2482 /* Set up the return parameter block */
2483 SSVAL(params,0,numentries);
2484 SSVAL(params,2,finished);
2485 SSVAL(params,4,0); /* Never an EA error */
2486 SSVAL(params,6,last_entry_off);
2488 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2489 max_data_bytes);
2491 return;
2494 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2496 E_md4hash(lp_servicename(SNUM(conn)),objid);
2497 return objid;
2500 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2502 SMB_ASSERT(extended_info != NULL);
2504 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2505 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2506 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2507 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2508 #ifdef SAMBA_VERSION_REVISION
2509 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2510 #endif
2511 extended_info->samba_subversion = 0;
2512 #ifdef SAMBA_VERSION_RC_RELEASE
2513 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2514 #else
2515 #ifdef SAMBA_VERSION_PRE_RELEASE
2516 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2517 #endif
2518 #endif
2519 #ifdef SAMBA_VERSION_VENDOR_PATCH
2520 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2521 #endif
2522 extended_info->samba_gitcommitdate = 0;
2523 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2524 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2525 #endif
2527 memset(extended_info->samba_version_string, 0,
2528 sizeof(extended_info->samba_version_string));
2530 snprintf (extended_info->samba_version_string,
2531 sizeof(extended_info->samba_version_string),
2532 "%s", samba_version_string());
2535 /****************************************************************************
2536 Reply to a TRANS2_QFSINFO (query filesystem info).
2537 ****************************************************************************/
2539 static void call_trans2qfsinfo(connection_struct *conn,
2540 struct smb_request *req,
2541 char **pparams, int total_params,
2542 char **ppdata, int total_data,
2543 unsigned int max_data_bytes)
2545 char *pdata, *end_data;
2546 char *params = *pparams;
2547 uint16 info_level;
2548 int data_len, len;
2549 SMB_STRUCT_STAT st;
2550 const char *vname = volume_label(SNUM(conn));
2551 int snum = SNUM(conn);
2552 char *fstype = lp_fstype(SNUM(conn));
2553 uint32 additional_flags = 0;
2555 if (total_params < 2) {
2556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2557 return;
2560 info_level = SVAL(params,0);
2562 if (IS_IPC(conn)) {
2563 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2564 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2565 "info level (0x%x) on IPC$.\n",
2566 (unsigned int)info_level));
2567 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2568 return;
2572 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2573 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2574 DEBUG(0,("call_trans2qfsinfo: encryption required "
2575 "and info level 0x%x sent.\n",
2576 (unsigned int)info_level));
2577 exit_server_cleanly("encryption required "
2578 "on connection");
2579 return;
2583 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2585 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2586 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2587 reply_doserror(req, ERRSRV, ERRinvdevice);
2588 return;
2591 *ppdata = (char *)SMB_REALLOC(
2592 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2593 if (*ppdata == NULL ) {
2594 reply_nterror(req, NT_STATUS_NO_MEMORY);
2595 return;
2598 pdata = *ppdata;
2599 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2600 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2602 switch (info_level) {
2603 case SMB_INFO_ALLOCATION:
2605 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2606 data_len = 18;
2607 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2608 reply_unixerror(req, ERRHRD, ERRgeneral);
2609 return;
2612 block_size = lp_block_size(snum);
2613 if (bsize < block_size) {
2614 uint64_t factor = block_size/bsize;
2615 bsize = block_size;
2616 dsize /= factor;
2617 dfree /= factor;
2619 if (bsize > block_size) {
2620 uint64_t factor = bsize/block_size;
2621 bsize = block_size;
2622 dsize *= factor;
2623 dfree *= factor;
2625 bytes_per_sector = 512;
2626 sectors_per_unit = bsize/bytes_per_sector;
2628 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2629 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2630 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2632 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2633 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2634 SIVAL(pdata,l1_cUnit,dsize);
2635 SIVAL(pdata,l1_cUnitAvail,dfree);
2636 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2637 break;
2640 case SMB_INFO_VOLUME:
2641 /* Return volume name */
2643 * Add volume serial number - hash of a combination of
2644 * the called hostname and the service name.
2646 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2648 * Win2k3 and previous mess this up by sending a name length
2649 * one byte short. I believe only older clients (OS/2 Win9x) use
2650 * this call so try fixing this by adding a terminating null to
2651 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2653 len = srvstr_push(
2654 pdata, req->flags2,
2655 pdata+l2_vol_szVolLabel, vname,
2656 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2657 STR_NOALIGN|STR_TERMINATE);
2658 SCVAL(pdata,l2_vol_cch,len);
2659 data_len = l2_vol_szVolLabel + len;
2660 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2661 (unsigned)st.st_ctime, len, vname));
2662 break;
2664 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2665 case SMB_FS_ATTRIBUTE_INFORMATION:
2667 additional_flags = 0;
2668 #if defined(HAVE_SYS_QUOTAS)
2669 additional_flags |= FILE_VOLUME_QUOTAS;
2670 #endif
2672 if(lp_nt_acl_support(SNUM(conn))) {
2673 additional_flags |= FILE_PERSISTENT_ACLS;
2676 /* Capabilities are filled in at connection time through STATVFS call */
2677 additional_flags |= conn->fs_capabilities;
2679 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2680 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2681 additional_flags); /* FS ATTRIBUTES */
2683 SIVAL(pdata,4,255); /* Max filename component length */
2684 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2685 and will think we can't do long filenames */
2686 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2687 PTR_DIFF(end_data, pdata+12),
2688 STR_UNICODE);
2689 SIVAL(pdata,8,len);
2690 data_len = 12 + len;
2691 break;
2693 case SMB_QUERY_FS_LABEL_INFO:
2694 case SMB_FS_LABEL_INFORMATION:
2695 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2696 PTR_DIFF(end_data, pdata+4), 0);
2697 data_len = 4 + len;
2698 SIVAL(pdata,0,len);
2699 break;
2701 case SMB_QUERY_FS_VOLUME_INFO:
2702 case SMB_FS_VOLUME_INFORMATION:
2705 * Add volume serial number - hash of a combination of
2706 * the called hostname and the service name.
2708 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2709 (str_checksum(get_local_machine_name())<<16));
2711 /* Max label len is 32 characters. */
2712 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2713 PTR_DIFF(end_data, pdata+18),
2714 STR_UNICODE);
2715 SIVAL(pdata,12,len);
2716 data_len = 18+len;
2718 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2719 (int)strlen(vname),vname, lp_servicename(snum)));
2720 break;
2722 case SMB_QUERY_FS_SIZE_INFO:
2723 case SMB_FS_SIZE_INFORMATION:
2725 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2726 data_len = 24;
2727 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2728 reply_unixerror(req, ERRHRD, ERRgeneral);
2729 return;
2731 block_size = lp_block_size(snum);
2732 if (bsize < block_size) {
2733 uint64_t factor = block_size/bsize;
2734 bsize = block_size;
2735 dsize /= factor;
2736 dfree /= factor;
2738 if (bsize > block_size) {
2739 uint64_t factor = bsize/block_size;
2740 bsize = block_size;
2741 dsize *= factor;
2742 dfree *= factor;
2744 bytes_per_sector = 512;
2745 sectors_per_unit = bsize/bytes_per_sector;
2746 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2747 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2748 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2749 SBIG_UINT(pdata,0,dsize);
2750 SBIG_UINT(pdata,8,dfree);
2751 SIVAL(pdata,16,sectors_per_unit);
2752 SIVAL(pdata,20,bytes_per_sector);
2753 break;
2756 case SMB_FS_FULL_SIZE_INFORMATION:
2758 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2759 data_len = 32;
2760 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2761 reply_unixerror(req, ERRHRD, ERRgeneral);
2762 return;
2764 block_size = lp_block_size(snum);
2765 if (bsize < block_size) {
2766 uint64_t factor = block_size/bsize;
2767 bsize = block_size;
2768 dsize /= factor;
2769 dfree /= factor;
2771 if (bsize > block_size) {
2772 uint64_t factor = bsize/block_size;
2773 bsize = block_size;
2774 dsize *= factor;
2775 dfree *= factor;
2777 bytes_per_sector = 512;
2778 sectors_per_unit = bsize/bytes_per_sector;
2779 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2780 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2781 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2782 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2783 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2784 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2785 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2786 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2787 break;
2790 case SMB_QUERY_FS_DEVICE_INFO:
2791 case SMB_FS_DEVICE_INFORMATION:
2792 data_len = 8;
2793 SIVAL(pdata,0,0); /* dev type */
2794 SIVAL(pdata,4,0); /* characteristics */
2795 break;
2797 #ifdef HAVE_SYS_QUOTAS
2798 case SMB_FS_QUOTA_INFORMATION:
2800 * what we have to send --metze:
2802 * Unknown1: 24 NULL bytes
2803 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2804 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2805 * Quota Flags: 2 byte :
2806 * Unknown3: 6 NULL bytes
2808 * 48 bytes total
2810 * details for Quota Flags:
2812 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2813 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2814 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2815 * 0x0001 Enable Quotas: enable quota for this fs
2819 /* we need to fake up a fsp here,
2820 * because its not send in this call
2822 files_struct fsp;
2823 SMB_NTQUOTA_STRUCT quotas;
2825 ZERO_STRUCT(fsp);
2826 ZERO_STRUCT(quotas);
2828 fsp.conn = conn;
2829 fsp.fnum = -1;
2831 /* access check */
2832 if (conn->server_info->utok.uid != 0) {
2833 DEBUG(0,("set_user_quota: access_denied "
2834 "service [%s] user [%s]\n",
2835 lp_servicename(SNUM(conn)),
2836 conn->server_info->unix_name));
2837 reply_doserror(req, ERRDOS, ERRnoaccess);
2838 return;
2841 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2842 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2843 reply_doserror(req, ERRSRV, ERRerror);
2844 return;
2847 data_len = 48;
2849 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2851 /* Unknown1 24 NULL bytes*/
2852 SBIG_UINT(pdata,0,(uint64_t)0);
2853 SBIG_UINT(pdata,8,(uint64_t)0);
2854 SBIG_UINT(pdata,16,(uint64_t)0);
2856 /* Default Soft Quota 8 bytes */
2857 SBIG_UINT(pdata,24,quotas.softlim);
2859 /* Default Hard Quota 8 bytes */
2860 SBIG_UINT(pdata,32,quotas.hardlim);
2862 /* Quota flag 2 bytes */
2863 SSVAL(pdata,40,quotas.qflags);
2865 /* Unknown3 6 NULL bytes */
2866 SSVAL(pdata,42,0);
2867 SIVAL(pdata,44,0);
2869 break;
2871 #endif /* HAVE_SYS_QUOTAS */
2872 case SMB_FS_OBJECTID_INFORMATION:
2874 unsigned char objid[16];
2875 struct smb_extended_info extended_info;
2876 memcpy(pdata,create_volume_objectid(conn, objid),16);
2877 samba_extended_info_version (&extended_info);
2878 SIVAL(pdata,16,extended_info.samba_magic);
2879 SIVAL(pdata,20,extended_info.samba_version);
2880 SIVAL(pdata,24,extended_info.samba_subversion);
2881 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2882 memcpy(pdata+36,extended_info.samba_version_string,28);
2883 data_len = 64;
2884 break;
2888 * Query the version and capabilities of the CIFS UNIX extensions
2889 * in use.
2892 case SMB_QUERY_CIFS_UNIX_INFO:
2894 bool large_write = lp_min_receive_file_size() &&
2895 !srv_is_signing_active();
2896 bool large_read = !srv_is_signing_active();
2897 int encrypt_caps = 0;
2899 if (!lp_unix_extensions()) {
2900 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2901 return;
2904 switch (conn->encrypt_level) {
2905 case 0:
2906 encrypt_caps = 0;
2907 break;
2908 case 1:
2909 case Auto:
2910 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2911 break;
2912 case Required:
2913 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2914 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2915 large_write = false;
2916 large_read = false;
2917 break;
2920 data_len = 12;
2921 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2922 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2924 /* We have POSIX ACLs, pathname, encryption,
2925 * large read/write, and locking capability. */
2927 SBIG_UINT(pdata,4,((uint64_t)(
2928 CIFS_UNIX_POSIX_ACLS_CAP|
2929 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2930 CIFS_UNIX_FCNTL_LOCKS_CAP|
2931 CIFS_UNIX_EXTATTR_CAP|
2932 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2933 encrypt_caps|
2934 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2935 (large_write ?
2936 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2937 break;
2940 case SMB_QUERY_POSIX_FS_INFO:
2942 int rc;
2943 vfs_statvfs_struct svfs;
2945 if (!lp_unix_extensions()) {
2946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2947 return;
2950 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2952 if (!rc) {
2953 data_len = 56;
2954 SIVAL(pdata,0,svfs.OptimalTransferSize);
2955 SIVAL(pdata,4,svfs.BlockSize);
2956 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2957 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2958 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2959 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2960 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2961 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2962 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2963 #ifdef EOPNOTSUPP
2964 } else if (rc == EOPNOTSUPP) {
2965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2966 return;
2967 #endif /* EOPNOTSUPP */
2968 } else {
2969 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2970 reply_doserror(req, ERRSRV, ERRerror);
2971 return;
2973 break;
2976 case SMB_QUERY_POSIX_WHOAMI:
2978 uint32_t flags = 0;
2979 uint32_t sid_bytes;
2980 int i;
2982 if (!lp_unix_extensions()) {
2983 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2984 return;
2987 if (max_data_bytes < 40) {
2988 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2989 return;
2992 /* We ARE guest if global_sid_Builtin_Guests is
2993 * in our list of SIDs.
2995 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2996 conn->server_info->ptok)) {
2997 flags |= SMB_WHOAMI_GUEST;
3000 /* We are NOT guest if global_sid_Authenticated_Users
3001 * is in our list of SIDs.
3003 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3004 conn->server_info->ptok)) {
3005 flags &= ~SMB_WHOAMI_GUEST;
3008 /* NOTE: 8 bytes for UID/GID, irrespective of native
3009 * platform size. This matches
3010 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3012 data_len = 4 /* flags */
3013 + 4 /* flag mask */
3014 + 8 /* uid */
3015 + 8 /* gid */
3016 + 4 /* ngroups */
3017 + 4 /* num_sids */
3018 + 4 /* SID bytes */
3019 + 4 /* pad/reserved */
3020 + (conn->server_info->utok.ngroups * 8)
3021 /* groups list */
3022 + (conn->server_info->ptok->num_sids *
3023 SID_MAX_SIZE)
3024 /* SID list */;
3026 SIVAL(pdata, 0, flags);
3027 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3028 SBIG_UINT(pdata, 8,
3029 (uint64_t)conn->server_info->utok.uid);
3030 SBIG_UINT(pdata, 16,
3031 (uint64_t)conn->server_info->utok.gid);
3034 if (data_len >= max_data_bytes) {
3035 /* Potential overflow, skip the GIDs and SIDs. */
3037 SIVAL(pdata, 24, 0); /* num_groups */
3038 SIVAL(pdata, 28, 0); /* num_sids */
3039 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3040 SIVAL(pdata, 36, 0); /* reserved */
3042 data_len = 40;
3043 break;
3046 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3047 SIVAL(pdata, 28, conn->server_info->num_sids);
3049 /* We walk the SID list twice, but this call is fairly
3050 * infrequent, and I don't expect that it's performance
3051 * sensitive -- jpeach
3053 for (i = 0, sid_bytes = 0;
3054 i < conn->server_info->ptok->num_sids; ++i) {
3055 sid_bytes += ndr_size_dom_sid(
3056 &conn->server_info->ptok->user_sids[i],
3057 NULL,
3061 /* SID list byte count */
3062 SIVAL(pdata, 32, sid_bytes);
3064 /* 4 bytes pad/reserved - must be zero */
3065 SIVAL(pdata, 36, 0);
3066 data_len = 40;
3068 /* GID list */
3069 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3070 SBIG_UINT(pdata, data_len,
3071 (uint64_t)conn->server_info->utok.groups[i]);
3072 data_len += 8;
3075 /* SID list */
3076 for (i = 0;
3077 i < conn->server_info->ptok->num_sids; ++i) {
3078 int sid_len = ndr_size_dom_sid(
3079 &conn->server_info->ptok->user_sids[i],
3080 NULL,
3083 sid_linearize(pdata + data_len, sid_len,
3084 &conn->server_info->ptok->user_sids[i]);
3085 data_len += sid_len;
3088 break;
3091 case SMB_MAC_QUERY_FS_INFO:
3093 * Thursby MAC extension... ONLY on NTFS filesystems
3094 * once we do streams then we don't need this
3096 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3097 data_len = 88;
3098 SIVAL(pdata,84,0x100); /* Don't support mac... */
3099 break;
3101 /* drop through */
3102 default:
3103 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3104 return;
3108 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3109 max_data_bytes);
3111 DEBUG( 4, ( "%s info_level = %d\n",
3112 smb_fn_name(req->cmd), info_level) );
3114 return;
3117 /****************************************************************************
3118 Reply to a TRANS2_SETFSINFO (set filesystem info).
3119 ****************************************************************************/
3121 static void call_trans2setfsinfo(connection_struct *conn,
3122 struct smb_request *req,
3123 char **pparams, int total_params,
3124 char **ppdata, int total_data,
3125 unsigned int max_data_bytes)
3127 char *pdata = *ppdata;
3128 char *params = *pparams;
3129 uint16 info_level;
3131 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3133 /* */
3134 if (total_params < 4) {
3135 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3136 total_params));
3137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3138 return;
3141 info_level = SVAL(params,2);
3143 if (IS_IPC(conn)) {
3144 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3145 info_level != SMB_SET_CIFS_UNIX_INFO) {
3146 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3147 "info level (0x%x) on IPC$.\n",
3148 (unsigned int)info_level));
3149 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3150 return;
3154 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3155 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3156 DEBUG(0,("call_trans2setfsinfo: encryption required "
3157 "and info level 0x%x sent.\n",
3158 (unsigned int)info_level));
3159 exit_server_cleanly("encryption required "
3160 "on connection");
3161 return;
3165 switch(info_level) {
3166 case SMB_SET_CIFS_UNIX_INFO:
3168 uint16 client_unix_major;
3169 uint16 client_unix_minor;
3170 uint32 client_unix_cap_low;
3171 uint32 client_unix_cap_high;
3173 if (!lp_unix_extensions()) {
3174 reply_nterror(req,
3175 NT_STATUS_INVALID_LEVEL);
3176 return;
3179 /* There should be 12 bytes of capabilities set. */
3180 if (total_data < 8) {
3181 reply_nterror(
3182 req,
3183 NT_STATUS_INVALID_PARAMETER);
3184 return;
3186 client_unix_major = SVAL(pdata,0);
3187 client_unix_minor = SVAL(pdata,2);
3188 client_unix_cap_low = IVAL(pdata,4);
3189 client_unix_cap_high = IVAL(pdata,8);
3190 /* Just print these values for now. */
3191 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3192 cap_low = 0x%x, cap_high = 0x%x\n",
3193 (unsigned int)client_unix_major,
3194 (unsigned int)client_unix_minor,
3195 (unsigned int)client_unix_cap_low,
3196 (unsigned int)client_unix_cap_high ));
3198 /* Here is where we must switch to posix pathname processing... */
3199 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3200 lp_set_posix_pathnames();
3201 mangle_change_to_posix();
3204 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3205 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3206 /* Client that knows how to do posix locks,
3207 * but not posix open/mkdir operations. Set a
3208 * default type for read/write checks. */
3210 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3213 break;
3216 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3218 NTSTATUS status;
3219 size_t param_len = 0;
3220 size_t data_len = total_data;
3222 if (!lp_unix_extensions()) {
3223 reply_nterror(
3224 req,
3225 NT_STATUS_INVALID_LEVEL);
3226 return;
3229 if (lp_smb_encrypt(SNUM(conn)) == false) {
3230 reply_nterror(
3231 req,
3232 NT_STATUS_NOT_SUPPORTED);
3233 return;
3236 DEBUG( 4,("call_trans2setfsinfo: "
3237 "request transport encryption.\n"));
3239 status = srv_request_encryption_setup(conn,
3240 (unsigned char **)ppdata,
3241 &data_len,
3242 (unsigned char **)pparams,
3243 &param_len);
3245 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3246 !NT_STATUS_IS_OK(status)) {
3247 reply_nterror(req, status);
3248 return;
3251 send_trans2_replies(conn, req,
3252 *pparams,
3253 param_len,
3254 *ppdata,
3255 data_len,
3256 max_data_bytes);
3258 if (NT_STATUS_IS_OK(status)) {
3259 /* Server-side transport
3260 * encryption is now *on*. */
3261 status = srv_encryption_start(conn);
3262 if (!NT_STATUS_IS_OK(status)) {
3263 exit_server_cleanly(
3264 "Failure in setting "
3265 "up encrypted transport");
3268 return;
3271 case SMB_FS_QUOTA_INFORMATION:
3273 files_struct *fsp = NULL;
3274 SMB_NTQUOTA_STRUCT quotas;
3276 ZERO_STRUCT(quotas);
3278 /* access check */
3279 if ((conn->server_info->utok.uid != 0)
3280 ||!CAN_WRITE(conn)) {
3281 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3282 lp_servicename(SNUM(conn)),
3283 conn->server_info->unix_name));
3284 reply_doserror(req, ERRSRV, ERRaccess);
3285 return;
3288 /* note: normaly there're 48 bytes,
3289 * but we didn't use the last 6 bytes for now
3290 * --metze
3292 fsp = file_fsp(req, SVAL(params,0));
3294 if (!check_fsp_ntquota_handle(conn, req,
3295 fsp)) {
3296 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3297 reply_nterror(
3298 req, NT_STATUS_INVALID_HANDLE);
3299 return;
3302 if (total_data < 42) {
3303 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3304 total_data));
3305 reply_nterror(
3306 req,
3307 NT_STATUS_INVALID_PARAMETER);
3308 return;
3311 /* unknown_1 24 NULL bytes in pdata*/
3313 /* the soft quotas 8 bytes (uint64_t)*/
3314 quotas.softlim = (uint64_t)IVAL(pdata,24);
3315 #ifdef LARGE_SMB_OFF_T
3316 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3317 #else /* LARGE_SMB_OFF_T */
3318 if ((IVAL(pdata,28) != 0)&&
3319 ((quotas.softlim != 0xFFFFFFFF)||
3320 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3321 /* more than 32 bits? */
3322 reply_nterror(
3323 req,
3324 NT_STATUS_INVALID_PARAMETER);
3325 return;
3327 #endif /* LARGE_SMB_OFF_T */
3329 /* the hard quotas 8 bytes (uint64_t)*/
3330 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3331 #ifdef LARGE_SMB_OFF_T
3332 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3333 #else /* LARGE_SMB_OFF_T */
3334 if ((IVAL(pdata,36) != 0)&&
3335 ((quotas.hardlim != 0xFFFFFFFF)||
3336 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3337 /* more than 32 bits? */
3338 reply_nterror(
3339 req,
3340 NT_STATUS_INVALID_PARAMETER);
3341 return;
3343 #endif /* LARGE_SMB_OFF_T */
3345 /* quota_flags 2 bytes **/
3346 quotas.qflags = SVAL(pdata,40);
3348 /* unknown_2 6 NULL bytes follow*/
3350 /* now set the quotas */
3351 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3352 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3353 reply_doserror(req, ERRSRV, ERRerror);
3354 return;
3357 break;
3359 default:
3360 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3361 info_level));
3362 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3363 return;
3364 break;
3368 * sending this reply works fine,
3369 * but I'm not sure it's the same
3370 * like windows do...
3371 * --metze
3373 reply_outbuf(req, 10, 0);
3376 #if defined(HAVE_POSIX_ACLS)
3377 /****************************************************************************
3378 Utility function to count the number of entries in a POSIX acl.
3379 ****************************************************************************/
3381 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3383 unsigned int ace_count = 0;
3384 int entry_id = SMB_ACL_FIRST_ENTRY;
3385 SMB_ACL_ENTRY_T entry;
3387 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3388 /* get_next... */
3389 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3390 entry_id = SMB_ACL_NEXT_ENTRY;
3392 ace_count++;
3394 return ace_count;
3397 /****************************************************************************
3398 Utility function to marshall a POSIX acl into wire format.
3399 ****************************************************************************/
3401 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3403 int entry_id = SMB_ACL_FIRST_ENTRY;
3404 SMB_ACL_ENTRY_T entry;
3406 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3407 SMB_ACL_TAG_T tagtype;
3408 SMB_ACL_PERMSET_T permset;
3409 unsigned char perms = 0;
3410 unsigned int own_grp;
3412 /* get_next... */
3413 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3414 entry_id = SMB_ACL_NEXT_ENTRY;
3417 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3418 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3419 return False;
3422 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3423 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3424 return False;
3427 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3428 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3429 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3431 SCVAL(pdata,1,perms);
3433 switch (tagtype) {
3434 case SMB_ACL_USER_OBJ:
3435 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3436 own_grp = (unsigned int)pst->st_uid;
3437 SIVAL(pdata,2,own_grp);
3438 SIVAL(pdata,6,0);
3439 break;
3440 case SMB_ACL_USER:
3442 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3443 if (!puid) {
3444 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3445 return False;
3447 own_grp = (unsigned int)*puid;
3448 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3449 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3450 SIVAL(pdata,2,own_grp);
3451 SIVAL(pdata,6,0);
3452 break;
3454 case SMB_ACL_GROUP_OBJ:
3455 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3456 own_grp = (unsigned int)pst->st_gid;
3457 SIVAL(pdata,2,own_grp);
3458 SIVAL(pdata,6,0);
3459 break;
3460 case SMB_ACL_GROUP:
3462 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3463 if (!pgid) {
3464 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3465 return False;
3467 own_grp = (unsigned int)*pgid;
3468 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3469 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3470 SIVAL(pdata,2,own_grp);
3471 SIVAL(pdata,6,0);
3472 break;
3474 case SMB_ACL_MASK:
3475 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3476 SIVAL(pdata,2,0xFFFFFFFF);
3477 SIVAL(pdata,6,0xFFFFFFFF);
3478 break;
3479 case SMB_ACL_OTHER:
3480 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3481 SIVAL(pdata,2,0xFFFFFFFF);
3482 SIVAL(pdata,6,0xFFFFFFFF);
3483 break;
3484 default:
3485 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3486 return False;
3488 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3491 return True;
3493 #endif
3495 /****************************************************************************
3496 Store the FILE_UNIX_BASIC info.
3497 ****************************************************************************/
3499 static char *store_file_unix_basic(connection_struct *conn,
3500 char *pdata,
3501 files_struct *fsp,
3502 const SMB_STRUCT_STAT *psbuf)
3504 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3505 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3507 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3508 pdata += 8;
3510 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3511 pdata += 8;
3513 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3514 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3515 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3516 pdata += 24;
3518 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3519 SIVAL(pdata,4,0);
3520 pdata += 8;
3522 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3523 SIVAL(pdata,4,0);
3524 pdata += 8;
3526 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3527 pdata += 4;
3529 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3530 SIVAL(pdata,4,0);
3531 pdata += 8;
3533 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3534 SIVAL(pdata,4,0);
3535 pdata += 8;
3537 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3538 pdata += 8;
3540 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3541 SIVAL(pdata,4,0);
3542 pdata += 8;
3544 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3545 SIVAL(pdata,4,0);
3546 pdata += 8;
3548 return pdata;
3551 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3552 * the chflags(2) (or equivalent) flags.
3554 * XXX: this really should be behind the VFS interface. To do this, we would
3555 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3556 * Each VFS module could then implement its own mapping as appropriate for the
3557 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3559 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3560 info2_flags_map[] =
3562 #ifdef UF_NODUMP
3563 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3564 #endif
3566 #ifdef UF_IMMUTABLE
3567 { UF_IMMUTABLE, EXT_IMMUTABLE },
3568 #endif
3570 #ifdef UF_APPEND
3571 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3572 #endif
3574 #ifdef UF_HIDDEN
3575 { UF_HIDDEN, EXT_HIDDEN },
3576 #endif
3578 /* Do not remove. We need to guarantee that this array has at least one
3579 * entry to build on HP-UX.
3581 { 0, 0 }
3585 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3586 uint32 *smb_fflags, uint32 *smb_fmask)
3588 #ifdef HAVE_STAT_ST_FLAGS
3589 int i;
3591 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3592 *smb_fmask |= info2_flags_map[i].smb_fflag;
3593 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3594 *smb_fflags |= info2_flags_map[i].smb_fflag;
3597 #endif /* HAVE_STAT_ST_FLAGS */
3600 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3601 const uint32 smb_fflags,
3602 const uint32 smb_fmask,
3603 int *stat_fflags)
3605 #ifdef HAVE_STAT_ST_FLAGS
3606 uint32 max_fmask = 0;
3607 int i;
3609 *stat_fflags = psbuf->st_flags;
3611 /* For each flags requested in smb_fmask, check the state of the
3612 * corresponding flag in smb_fflags and set or clear the matching
3613 * stat flag.
3616 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3617 max_fmask |= info2_flags_map[i].smb_fflag;
3618 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3619 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3620 *stat_fflags |= info2_flags_map[i].stat_fflag;
3621 } else {
3622 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3627 /* If smb_fmask is asking to set any bits that are not supported by
3628 * our flag mappings, we should fail.
3630 if ((smb_fmask & max_fmask) != smb_fmask) {
3631 return False;
3634 return True;
3635 #else
3636 return False;
3637 #endif /* HAVE_STAT_ST_FLAGS */
3641 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3642 * of file flags and birth (create) time.
3644 static char *store_file_unix_basic_info2(connection_struct *conn,
3645 char *pdata,
3646 files_struct *fsp,
3647 const SMB_STRUCT_STAT *psbuf)
3649 uint32 file_flags = 0;
3650 uint32 flags_mask = 0;
3652 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3654 /* Create (birth) time 64 bit */
3655 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3656 pdata += 8;
3658 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3659 SIVAL(pdata, 0, file_flags); /* flags */
3660 SIVAL(pdata, 4, flags_mask); /* mask */
3661 pdata += 8;
3663 return pdata;
3666 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3667 const struct stream_struct *streams,
3668 char *data,
3669 unsigned int max_data_bytes,
3670 unsigned int *data_size)
3672 unsigned int i;
3673 unsigned int ofs = 0;
3675 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3676 unsigned int next_offset;
3677 size_t namelen;
3678 smb_ucs2_t *namebuf;
3680 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3681 streams[i].name, &namelen) ||
3682 namelen <= 2)
3684 return NT_STATUS_INVALID_PARAMETER;
3688 * name_buf is now null-terminated, we need to marshall as not
3689 * terminated
3692 namelen -= 2;
3694 SIVAL(data, ofs+4, namelen);
3695 SOFF_T(data, ofs+8, streams[i].size);
3696 SOFF_T(data, ofs+16, streams[i].alloc_size);
3697 memcpy(data+ofs+24, namebuf, namelen);
3698 TALLOC_FREE(namebuf);
3700 next_offset = ofs + 24 + namelen;
3702 if (i == num_streams-1) {
3703 SIVAL(data, ofs, 0);
3705 else {
3706 unsigned int align = ndr_align_size(next_offset, 8);
3708 memset(data+next_offset, 0, align);
3709 next_offset += align;
3711 SIVAL(data, ofs, next_offset - ofs);
3712 ofs = next_offset;
3715 ofs = next_offset;
3718 *data_size = ofs;
3720 return NT_STATUS_OK;
3723 /****************************************************************************
3724 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3725 ****************************************************************************/
3727 static void call_trans2qpipeinfo(connection_struct *conn,
3728 struct smb_request *req,
3729 unsigned int tran_call,
3730 char **pparams, int total_params,
3731 char **ppdata, int total_data,
3732 unsigned int max_data_bytes)
3734 char *params = *pparams;
3735 char *pdata = *ppdata;
3736 unsigned int data_size = 0;
3737 unsigned int param_size = 2;
3738 uint16 info_level;
3739 files_struct *fsp;
3741 if (!params) {
3742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3743 return;
3746 if (total_params < 4) {
3747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 return;
3751 fsp = file_fsp(req, SVAL(params,0));
3752 if (!fsp_is_np(fsp)) {
3753 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3754 return;
3757 info_level = SVAL(params,2);
3759 *pparams = (char *)SMB_REALLOC(*pparams,2);
3760 if (*pparams == NULL) {
3761 reply_nterror(req, NT_STATUS_NO_MEMORY);
3762 return;
3764 params = *pparams;
3765 SSVAL(params,0,0);
3766 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3767 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3768 if (*ppdata == NULL ) {
3769 reply_nterror(req, NT_STATUS_NO_MEMORY);
3770 return;
3772 pdata = *ppdata;
3774 switch (info_level) {
3775 case SMB_FILE_STANDARD_INFORMATION:
3776 memset(pdata,0,24);
3777 SOFF_T(pdata,0,4096LL);
3778 SIVAL(pdata,16,1);
3779 SIVAL(pdata,20,1);
3780 data_size = 24;
3781 break;
3783 default:
3784 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3785 return;
3788 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3789 max_data_bytes);
3791 return;
3794 /****************************************************************************
3795 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3796 file name or file id).
3797 ****************************************************************************/
3799 static void call_trans2qfilepathinfo(connection_struct *conn,
3800 struct smb_request *req,
3801 unsigned int tran_call,
3802 char **pparams, int total_params,
3803 char **ppdata, int total_data,
3804 unsigned int max_data_bytes)
3806 char *params = *pparams;
3807 char *pdata = *ppdata;
3808 char *dstart, *dend;
3809 uint16 info_level;
3810 int mode=0;
3811 int nlink;
3812 SMB_OFF_T file_size=0;
3813 uint64_t allocation_size=0;
3814 unsigned int data_size = 0;
3815 unsigned int param_size = 2;
3816 SMB_STRUCT_STAT sbuf;
3817 char *dos_fname = NULL;
3818 char *fname = NULL;
3819 char *fullpathname;
3820 char *base_name;
3821 char *p;
3822 SMB_OFF_T pos = 0;
3823 bool delete_pending = False;
3824 int len;
3825 time_t create_time, mtime, atime;
3826 struct timespec create_time_ts, mtime_ts, atime_ts;
3827 struct timespec write_time_ts;
3828 files_struct *fsp = NULL;
3829 struct file_id fileid;
3830 struct ea_list *ea_list = NULL;
3831 char *lock_data = NULL;
3832 bool ms_dfs_link = false;
3833 TALLOC_CTX *ctx = talloc_tos();
3835 if (!params) {
3836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3837 return;
3840 ZERO_STRUCT(sbuf);
3841 ZERO_STRUCT(write_time_ts);
3843 if (tran_call == TRANSACT2_QFILEINFO) {
3844 if (total_params < 4) {
3845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3846 return;
3849 if (IS_IPC(conn)) {
3850 call_trans2qpipeinfo(conn, req, tran_call,
3851 pparams, total_params,
3852 ppdata, total_data,
3853 max_data_bytes);
3854 return;
3857 fsp = file_fsp(req, SVAL(params,0));
3858 info_level = SVAL(params,2);
3860 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3862 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3864 return;
3867 /* Initial check for valid fsp ptr. */
3868 if (!check_fsp_open(conn, req, fsp)) {
3869 return;
3872 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3873 if (!fname) {
3874 reply_nterror(req, NT_STATUS_NO_MEMORY);
3875 return;
3878 if(fsp->fake_file_handle) {
3880 * This is actually for the QUOTA_FAKE_FILE --metze
3883 /* We know this name is ok, it's already passed the checks. */
3885 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3887 * This is actually a QFILEINFO on a directory
3888 * handle (returned from an NT SMB). NT5.0 seems
3889 * to do this call. JRA.
3892 if (INFO_LEVEL_IS_UNIX(info_level)) {
3893 /* Always do lstat for UNIX calls. */
3894 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3895 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3896 reply_unixerror(req,ERRDOS,ERRbadpath);
3897 return;
3899 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3900 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3901 reply_unixerror(req, ERRDOS, ERRbadpath);
3902 return;
3905 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3906 get_file_infos(fileid, &delete_pending, &write_time_ts);
3907 } else {
3909 * Original code - this is an open file.
3911 if (!check_fsp(conn, req, fsp)) {
3912 return;
3915 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3916 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3917 reply_unixerror(req, ERRDOS, ERRbadfid);
3918 return;
3920 pos = fsp->fh->position_information;
3921 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3922 get_file_infos(fileid, &delete_pending, &write_time_ts);
3925 } else {
3926 NTSTATUS status = NT_STATUS_OK;
3928 /* qpathinfo */
3929 if (total_params < 7) {
3930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3931 return;
3934 info_level = SVAL(params,0);
3936 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3938 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3939 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3940 return;
3943 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3944 total_params - 6,
3945 STR_TERMINATE, &status);
3946 if (!NT_STATUS_IS_OK(status)) {
3947 reply_nterror(req, status);
3948 return;
3951 status = resolve_dfspath(ctx,
3952 conn,
3953 req->flags2 & FLAGS2_DFS_PATHNAMES,
3954 fname,
3955 &fname);
3956 if (!NT_STATUS_IS_OK(status)) {
3957 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3958 reply_botherror(req,
3959 NT_STATUS_PATH_NOT_COVERED,
3960 ERRSRV, ERRbadpath);
3962 reply_nterror(req, status);
3963 return;
3966 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 reply_nterror(req, status);
3969 return;
3971 status = check_name(conn, fname);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3974 reply_nterror(req, status);
3975 return;
3978 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3979 && is_ntfs_stream_name(fname)) {
3980 char *base;
3981 SMB_STRUCT_STAT bsbuf;
3983 status = split_ntfs_stream_name(talloc_tos(), fname,
3984 &base, NULL);
3985 if (!NT_STATUS_IS_OK(status)) {
3986 DEBUG(10, ("create_file_unixpath: "
3987 "split_ntfs_stream_name failed: %s\n",
3988 nt_errstr(status)));
3989 reply_nterror(req, status);
3990 return;
3993 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3995 if (INFO_LEVEL_IS_UNIX(info_level)) {
3996 /* Always do lstat for UNIX calls. */
3997 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
3998 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
3999 reply_unixerror(req,ERRDOS,ERRbadpath);
4000 return;
4002 } else {
4003 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4004 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4005 reply_unixerror(req,ERRDOS,ERRbadpath);
4006 return;
4010 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4011 get_file_infos(fileid, &delete_pending, NULL);
4012 if (delete_pending) {
4013 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4014 return;
4018 if (INFO_LEVEL_IS_UNIX(info_level)) {
4019 /* Always do lstat for UNIX calls. */
4020 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4021 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4022 reply_unixerror(req, ERRDOS, ERRbadpath);
4023 return;
4026 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4027 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4029 if (!ms_dfs_link) {
4030 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4031 reply_unixerror(req, ERRDOS, ERRbadpath);
4032 return;
4036 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4037 get_file_infos(fileid, &delete_pending, &write_time_ts);
4038 if (delete_pending) {
4039 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4040 return;
4044 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4045 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4046 return;
4049 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4050 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4052 p = strrchr_m(fname,'/');
4053 if (!p)
4054 base_name = fname;
4055 else
4056 base_name = p+1;
4058 if (ms_dfs_link) {
4059 mode = dos_mode_msdfs(conn,fname,&sbuf);
4060 } else {
4061 mode = dos_mode(conn,fname,&sbuf);
4063 if (!mode)
4064 mode = FILE_ATTRIBUTE_NORMAL;
4066 nlink = sbuf.st_nlink;
4068 if (nlink && (mode&aDIR)) {
4069 nlink = 1;
4072 if ((nlink > 0) && delete_pending) {
4073 nlink -= 1;
4076 fullpathname = fname;
4077 if (!(mode & aDIR))
4078 file_size = get_file_size_stat(&sbuf);
4080 /* Pull out any data sent here before we realloc. */
4081 switch (info_level) {
4082 case SMB_INFO_QUERY_EAS_FROM_LIST:
4084 /* Pull any EA list from the data portion. */
4085 uint32 ea_size;
4087 if (total_data < 4) {
4088 reply_nterror(
4089 req, NT_STATUS_INVALID_PARAMETER);
4090 return;
4092 ea_size = IVAL(pdata,0);
4094 if (total_data > 0 && ea_size != total_data) {
4095 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4096 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4097 reply_nterror(
4098 req, NT_STATUS_INVALID_PARAMETER);
4099 return;
4102 if (!lp_ea_support(SNUM(conn))) {
4103 reply_doserror(req, ERRDOS,
4104 ERReasnotsupported);
4105 return;
4108 /* Pull out the list of names. */
4109 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4110 if (!ea_list) {
4111 reply_nterror(
4112 req, NT_STATUS_INVALID_PARAMETER);
4113 return;
4115 break;
4118 case SMB_QUERY_POSIX_LOCK:
4120 if (fsp == NULL || fsp->fh->fd == -1) {
4121 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4122 return;
4125 if (total_data != POSIX_LOCK_DATA_SIZE) {
4126 reply_nterror(
4127 req, NT_STATUS_INVALID_PARAMETER);
4128 return;
4131 /* Copy the lock range data. */
4132 lock_data = (char *)TALLOC_MEMDUP(
4133 ctx, pdata, total_data);
4134 if (!lock_data) {
4135 reply_nterror(req, NT_STATUS_NO_MEMORY);
4136 return;
4139 default:
4140 break;
4143 *pparams = (char *)SMB_REALLOC(*pparams,2);
4144 if (*pparams == NULL) {
4145 reply_nterror(req, NT_STATUS_NO_MEMORY);
4146 return;
4148 params = *pparams;
4149 SSVAL(params,0,0);
4150 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4151 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4152 if (*ppdata == NULL ) {
4153 reply_nterror(req, NT_STATUS_NO_MEMORY);
4154 return;
4156 pdata = *ppdata;
4157 dstart = pdata;
4158 dend = dstart + data_size - 1;
4160 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4161 mtime_ts = get_mtimespec(&sbuf);
4162 atime_ts = get_atimespec(&sbuf);
4164 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4166 if (!fsp) {
4167 /* Do we have this path open ? */
4168 files_struct *fsp1;
4169 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4170 fsp1 = file_find_di_first(fileid);
4171 if (fsp1 && fsp1->initial_allocation_size) {
4172 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4176 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4177 mtime_ts = write_time_ts;
4180 if (lp_dos_filetime_resolution(SNUM(conn))) {
4181 dos_filetime_timespec(&create_time_ts);
4182 dos_filetime_timespec(&mtime_ts);
4183 dos_filetime_timespec(&atime_ts);
4186 create_time = convert_timespec_to_time_t(create_time_ts);
4187 mtime = convert_timespec_to_time_t(mtime_ts);
4188 atime = convert_timespec_to_time_t(atime_ts);
4190 /* NT expects the name to be in an exact form of the *full*
4191 filename. See the trans2 torture test */
4192 if (ISDOT(base_name)) {
4193 dos_fname = talloc_strdup(ctx, "\\");
4194 if (!dos_fname) {
4195 reply_nterror(req, NT_STATUS_NO_MEMORY);
4196 return;
4198 } else {
4199 dos_fname = talloc_asprintf(ctx,
4200 "\\%s",
4201 fname);
4202 if (!dos_fname) {
4203 reply_nterror(req, NT_STATUS_NO_MEMORY);
4204 return;
4206 string_replace(dos_fname, '/', '\\');
4209 switch (info_level) {
4210 case SMB_INFO_STANDARD:
4211 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4212 data_size = 22;
4213 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4214 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4215 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4216 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4217 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4218 SSVAL(pdata,l1_attrFile,mode);
4219 break;
4221 case SMB_INFO_QUERY_EA_SIZE:
4223 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4224 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4225 data_size = 26;
4226 srv_put_dos_date2(pdata,0,create_time);
4227 srv_put_dos_date2(pdata,4,atime);
4228 srv_put_dos_date2(pdata,8,mtime); /* write time */
4229 SIVAL(pdata,12,(uint32)file_size);
4230 SIVAL(pdata,16,(uint32)allocation_size);
4231 SSVAL(pdata,20,mode);
4232 SIVAL(pdata,22,ea_size);
4233 break;
4236 case SMB_INFO_IS_NAME_VALID:
4237 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4238 if (tran_call == TRANSACT2_QFILEINFO) {
4239 /* os/2 needs this ? really ?*/
4240 reply_doserror(req, ERRDOS, ERRbadfunc);
4241 return;
4243 data_size = 0;
4244 param_size = 0;
4245 break;
4247 case SMB_INFO_QUERY_EAS_FROM_LIST:
4249 size_t total_ea_len = 0;
4250 struct ea_list *ea_file_list = NULL;
4252 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4254 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4255 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4257 if (!ea_list || (total_ea_len > data_size)) {
4258 data_size = 4;
4259 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4260 break;
4263 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4264 break;
4267 case SMB_INFO_QUERY_ALL_EAS:
4269 /* We have data_size bytes to put EA's into. */
4270 size_t total_ea_len = 0;
4272 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4274 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4275 if (!ea_list || (total_ea_len > data_size)) {
4276 data_size = 4;
4277 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4278 break;
4281 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4282 break;
4285 case SMB_FILE_BASIC_INFORMATION:
4286 case SMB_QUERY_FILE_BASIC_INFO:
4288 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4289 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4290 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4291 } else {
4292 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4293 data_size = 40;
4294 SIVAL(pdata,36,0);
4296 put_long_date_timespec(pdata,create_time_ts);
4297 put_long_date_timespec(pdata+8,atime_ts);
4298 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4299 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4300 SIVAL(pdata,32,mode);
4302 DEBUG(5,("SMB_QFBI - "));
4303 DEBUG(5,("create: %s ", ctime(&create_time)));
4304 DEBUG(5,("access: %s ", ctime(&atime)));
4305 DEBUG(5,("write: %s ", ctime(&mtime)));
4306 DEBUG(5,("change: %s ", ctime(&mtime)));
4307 DEBUG(5,("mode: %x\n", mode));
4308 break;
4310 case SMB_FILE_STANDARD_INFORMATION:
4311 case SMB_QUERY_FILE_STANDARD_INFO:
4313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4314 data_size = 24;
4315 SOFF_T(pdata,0,allocation_size);
4316 SOFF_T(pdata,8,file_size);
4317 SIVAL(pdata,16,nlink);
4318 SCVAL(pdata,20,delete_pending?1:0);
4319 SCVAL(pdata,21,(mode&aDIR)?1:0);
4320 SSVAL(pdata,22,0); /* Padding. */
4321 break;
4323 case SMB_FILE_EA_INFORMATION:
4324 case SMB_QUERY_FILE_EA_INFO:
4326 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4327 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4328 data_size = 4;
4329 SIVAL(pdata,0,ea_size);
4330 break;
4333 /* Get the 8.3 name - used if NT SMB was negotiated. */
4334 case SMB_QUERY_FILE_ALT_NAME_INFO:
4335 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4337 char mangled_name[13];
4338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4339 if (!name_to_8_3(base_name,mangled_name,
4340 True,conn->params)) {
4341 reply_nterror(
4342 req,
4343 NT_STATUS_NO_MEMORY);
4345 len = srvstr_push(dstart, req->flags2,
4346 pdata+4, mangled_name,
4347 PTR_DIFF(dend, pdata+4),
4348 STR_UNICODE);
4349 data_size = 4 + len;
4350 SIVAL(pdata,0,len);
4351 break;
4354 case SMB_QUERY_FILE_NAME_INFO:
4356 this must be *exactly* right for ACLs on mapped drives to work
4358 len = srvstr_push(dstart, req->flags2,
4359 pdata+4, dos_fname,
4360 PTR_DIFF(dend, pdata+4),
4361 STR_UNICODE);
4362 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4363 data_size = 4 + len;
4364 SIVAL(pdata,0,len);
4365 break;
4367 case SMB_FILE_ALLOCATION_INFORMATION:
4368 case SMB_QUERY_FILE_ALLOCATION_INFO:
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4370 data_size = 8;
4371 SOFF_T(pdata,0,allocation_size);
4372 break;
4374 case SMB_FILE_END_OF_FILE_INFORMATION:
4375 case SMB_QUERY_FILE_END_OF_FILEINFO:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4377 data_size = 8;
4378 SOFF_T(pdata,0,file_size);
4379 break;
4381 case SMB_QUERY_FILE_ALL_INFO:
4382 case SMB_FILE_ALL_INFORMATION:
4384 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4386 put_long_date_timespec(pdata,create_time_ts);
4387 put_long_date_timespec(pdata+8,atime_ts);
4388 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4389 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4390 SIVAL(pdata,32,mode);
4391 SIVAL(pdata,36,0); /* padding. */
4392 pdata += 40;
4393 SOFF_T(pdata,0,allocation_size);
4394 SOFF_T(pdata,8,file_size);
4395 SIVAL(pdata,16,nlink);
4396 SCVAL(pdata,20,delete_pending);
4397 SCVAL(pdata,21,(mode&aDIR)?1:0);
4398 SSVAL(pdata,22,0);
4399 pdata += 24;
4400 SIVAL(pdata,0,ea_size);
4401 pdata += 4; /* EA info */
4402 len = srvstr_push(dstart, req->flags2,
4403 pdata+4, dos_fname,
4404 PTR_DIFF(dend, pdata+4),
4405 STR_UNICODE);
4406 SIVAL(pdata,0,len);
4407 pdata += 4 + len;
4408 data_size = PTR_DIFF(pdata,(*ppdata));
4409 break;
4411 case SMB_FILE_INTERNAL_INFORMATION:
4412 /* This should be an index number - looks like
4413 dev/ino to me :-)
4415 I think this causes us to fail the IFSKIT
4416 BasicFileInformationTest. -tpot */
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4419 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4420 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4421 data_size = 8;
4422 break;
4424 case SMB_FILE_ACCESS_INFORMATION:
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4426 if (fsp) {
4427 SIVAL(pdata,0,fsp->access_mask);
4428 } else {
4429 /* GENERIC_EXECUTE mapping from Windows */
4430 SIVAL(pdata,0,0x12019F);
4432 data_size = 4;
4433 break;
4435 case SMB_FILE_NAME_INFORMATION:
4436 /* Pathname with leading '\'. */
4438 size_t byte_len;
4439 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4441 SIVAL(pdata,0,byte_len);
4442 data_size = 4 + byte_len;
4443 break;
4446 case SMB_FILE_DISPOSITION_INFORMATION:
4447 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4448 data_size = 1;
4449 SCVAL(pdata,0,delete_pending);
4450 break;
4452 case SMB_FILE_POSITION_INFORMATION:
4453 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4454 data_size = 8;
4455 SOFF_T(pdata,0,pos);
4456 break;
4458 case SMB_FILE_MODE_INFORMATION:
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4460 SIVAL(pdata,0,mode);
4461 data_size = 4;
4462 break;
4464 case SMB_FILE_ALIGNMENT_INFORMATION:
4465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4466 SIVAL(pdata,0,0); /* No alignment needed. */
4467 data_size = 4;
4468 break;
4471 * NT4 server just returns "invalid query" to this - if we try
4472 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4473 * want this. JRA.
4475 /* The first statement above is false - verified using Thursby
4476 * client against NT4 -- gcolley.
4478 case SMB_QUERY_FILE_STREAM_INFO:
4479 case SMB_FILE_STREAM_INFORMATION: {
4480 unsigned int num_streams;
4481 struct stream_struct *streams;
4482 NTSTATUS status;
4484 DEBUG(10,("call_trans2qfilepathinfo: "
4485 "SMB_FILE_STREAM_INFORMATION\n"));
4487 status = SMB_VFS_STREAMINFO(
4488 conn, fsp, fname, talloc_tos(),
4489 &num_streams, &streams);
4491 if (!NT_STATUS_IS_OK(status)) {
4492 DEBUG(10, ("could not get stream info: %s\n",
4493 nt_errstr(status)));
4494 reply_nterror(req, status);
4495 return;
4498 status = marshall_stream_info(num_streams, streams,
4499 pdata, max_data_bytes,
4500 &data_size);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 DEBUG(10, ("marshall_stream_info failed: %s\n",
4504 nt_errstr(status)));
4505 reply_nterror(req, status);
4506 return;
4509 TALLOC_FREE(streams);
4511 break;
4513 case SMB_QUERY_COMPRESSION_INFO:
4514 case SMB_FILE_COMPRESSION_INFORMATION:
4515 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4516 SOFF_T(pdata,0,file_size);
4517 SIVAL(pdata,8,0); /* ??? */
4518 SIVAL(pdata,12,0); /* ??? */
4519 data_size = 16;
4520 break;
4522 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4523 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4524 put_long_date_timespec(pdata,create_time_ts);
4525 put_long_date_timespec(pdata+8,atime_ts);
4526 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4527 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4528 SOFF_T(pdata,32,allocation_size);
4529 SOFF_T(pdata,40,file_size);
4530 SIVAL(pdata,48,mode);
4531 SIVAL(pdata,52,0); /* ??? */
4532 data_size = 56;
4533 break;
4535 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4536 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4537 SIVAL(pdata,0,mode);
4538 SIVAL(pdata,4,0);
4539 data_size = 8;
4540 break;
4543 * CIFS UNIX Extensions.
4546 case SMB_QUERY_FILE_UNIX_BASIC:
4548 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4549 data_size = PTR_DIFF(pdata,(*ppdata));
4552 int i;
4553 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4555 for (i=0; i<100; i++)
4556 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4557 DEBUG(4,("\n"));
4560 break;
4562 case SMB_QUERY_FILE_UNIX_INFO2:
4564 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4568 int i;
4569 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4571 for (i=0; i<100; i++)
4572 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4573 DEBUG(4,("\n"));
4576 break;
4578 case SMB_QUERY_FILE_UNIX_LINK:
4580 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4582 if (!buffer) {
4583 reply_nterror(req, NT_STATUS_NO_MEMORY);
4584 return;
4587 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4588 #ifdef S_ISLNK
4589 if(!S_ISLNK(sbuf.st_mode)) {
4590 reply_unixerror(req, ERRSRV,
4591 ERRbadlink);
4592 return;
4594 #else
4595 reply_unixerror(req, ERRDOS, ERRbadlink);
4596 return;
4597 #endif
4598 len = SMB_VFS_READLINK(conn,fullpathname,
4599 buffer, PATH_MAX);
4600 if (len == -1) {
4601 reply_unixerror(req, ERRDOS,
4602 ERRnoaccess);
4603 return;
4605 buffer[len] = 0;
4606 len = srvstr_push(dstart, req->flags2,
4607 pdata, buffer,
4608 PTR_DIFF(dend, pdata),
4609 STR_TERMINATE);
4610 pdata += len;
4611 data_size = PTR_DIFF(pdata,(*ppdata));
4613 break;
4616 #if defined(HAVE_POSIX_ACLS)
4617 case SMB_QUERY_POSIX_ACL:
4619 SMB_ACL_T file_acl = NULL;
4620 SMB_ACL_T def_acl = NULL;
4621 uint16 num_file_acls = 0;
4622 uint16 num_def_acls = 0;
4624 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4625 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4626 } else {
4627 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4630 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4631 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4632 fname ));
4633 reply_nterror(
4634 req,
4635 NT_STATUS_NOT_IMPLEMENTED);
4636 return;
4639 if (S_ISDIR(sbuf.st_mode)) {
4640 if (fsp && fsp->is_directory) {
4641 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4642 } else {
4643 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4645 def_acl = free_empty_sys_acl(conn, def_acl);
4648 num_file_acls = count_acl_entries(conn, file_acl);
4649 num_def_acls = count_acl_entries(conn, def_acl);
4651 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4652 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4653 data_size,
4654 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4655 SMB_POSIX_ACL_HEADER_SIZE) ));
4656 if (file_acl) {
4657 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4659 if (def_acl) {
4660 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4662 reply_nterror(
4663 req,
4664 NT_STATUS_BUFFER_TOO_SMALL);
4665 return;
4668 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4669 SSVAL(pdata,2,num_file_acls);
4670 SSVAL(pdata,4,num_def_acls);
4671 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4672 if (file_acl) {
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4675 if (def_acl) {
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4678 reply_nterror(
4679 req, NT_STATUS_INTERNAL_ERROR);
4680 return;
4682 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4683 if (file_acl) {
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4686 if (def_acl) {
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4689 reply_nterror(
4690 req,
4691 NT_STATUS_INTERNAL_ERROR);
4692 return;
4695 if (file_acl) {
4696 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4698 if (def_acl) {
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4701 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4702 break;
4704 #endif
4707 case SMB_QUERY_POSIX_LOCK:
4709 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4710 uint64_t count;
4711 uint64_t offset;
4712 uint32 lock_pid;
4713 enum brl_type lock_type;
4715 if (total_data != POSIX_LOCK_DATA_SIZE) {
4716 reply_nterror(
4717 req, NT_STATUS_INVALID_PARAMETER);
4718 return;
4721 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4722 case POSIX_LOCK_TYPE_READ:
4723 lock_type = READ_LOCK;
4724 break;
4725 case POSIX_LOCK_TYPE_WRITE:
4726 lock_type = WRITE_LOCK;
4727 break;
4728 case POSIX_LOCK_TYPE_UNLOCK:
4729 default:
4730 /* There's no point in asking for an unlock... */
4731 reply_nterror(
4732 req,
4733 NT_STATUS_INVALID_PARAMETER);
4734 return;
4737 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4738 #if defined(HAVE_LONGLONG)
4739 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4740 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4741 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4742 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4743 #else /* HAVE_LONGLONG */
4744 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4745 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4746 #endif /* HAVE_LONGLONG */
4748 status = query_lock(fsp,
4749 &lock_pid,
4750 &count,
4751 &offset,
4752 &lock_type,
4753 POSIX_LOCK);
4755 if (ERROR_WAS_LOCK_DENIED(status)) {
4756 /* Here we need to report who has it locked... */
4757 data_size = POSIX_LOCK_DATA_SIZE;
4759 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4760 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4761 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4762 #if defined(HAVE_LONGLONG)
4763 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4764 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4765 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4766 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4767 #else /* HAVE_LONGLONG */
4768 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4769 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4770 #endif /* HAVE_LONGLONG */
4772 } else if (NT_STATUS_IS_OK(status)) {
4773 /* For success we just return a copy of what we sent
4774 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4775 data_size = POSIX_LOCK_DATA_SIZE;
4776 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4777 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4778 } else {
4779 reply_nterror(req, status);
4780 return;
4782 break;
4785 default:
4786 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4787 return;
4790 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4791 max_data_bytes);
4793 return;
4796 /****************************************************************************
4797 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4798 code.
4799 ****************************************************************************/
4801 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4802 connection_struct *conn,
4803 const char *oldname_in,
4804 const char *newname_in)
4806 SMB_STRUCT_STAT sbuf1, sbuf2;
4807 char *last_component_oldname = NULL;
4808 char *last_component_newname = NULL;
4809 char *oldname = NULL;
4810 char *newname = NULL;
4811 NTSTATUS status = NT_STATUS_OK;
4813 ZERO_STRUCT(sbuf1);
4814 ZERO_STRUCT(sbuf2);
4816 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4817 &last_component_oldname, &sbuf1);
4818 if (!NT_STATUS_IS_OK(status)) {
4819 return status;
4822 status = check_name(conn, oldname);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 return status;
4827 /* source must already exist. */
4828 if (!VALID_STAT(sbuf1)) {
4829 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4832 status = unix_convert(ctx, conn, newname_in, False, &newname,
4833 &last_component_newname, &sbuf2);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 return status;
4838 status = check_name(conn, newname);
4839 if (!NT_STATUS_IS_OK(status)) {
4840 return status;
4843 /* Disallow if newname already exists. */
4844 if (VALID_STAT(sbuf2)) {
4845 return NT_STATUS_OBJECT_NAME_COLLISION;
4848 /* No links from a directory. */
4849 if (S_ISDIR(sbuf1.st_mode)) {
4850 return NT_STATUS_FILE_IS_A_DIRECTORY;
4853 /* Ensure this is within the share. */
4854 status = check_reduced_name(conn, oldname);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 return status;
4859 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4861 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4862 status = map_nt_error_from_unix(errno);
4863 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4864 nt_errstr(status), newname, oldname));
4867 return status;
4870 /****************************************************************************
4871 Deal with setting the time from any of the setfilepathinfo functions.
4872 ****************************************************************************/
4874 NTSTATUS smb_set_file_time(connection_struct *conn,
4875 files_struct *fsp,
4876 const char *fname,
4877 const SMB_STRUCT_STAT *psbuf,
4878 struct smb_file_time *ft,
4879 bool setting_write_time)
4881 uint32 action =
4882 FILE_NOTIFY_CHANGE_LAST_ACCESS
4883 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4885 if (!VALID_STAT(*psbuf)) {
4886 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4889 /* get some defaults (no modifications) if any info is zero or -1. */
4890 if (null_timespec(ft->atime)) {
4891 ft->atime= get_atimespec(psbuf);
4892 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4895 if (null_timespec(ft->mtime)) {
4896 ft->mtime = get_mtimespec(psbuf);
4897 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4900 if (!setting_write_time) {
4901 /* ft->mtime comes from change time, not write time. */
4902 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4905 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4906 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4907 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4908 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4909 if (!null_timespec(ft->create_time)) {
4910 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4911 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4915 * Try and set the times of this file if
4916 * they are different from the current values.
4920 struct timespec mts = get_mtimespec(psbuf);
4921 struct timespec ats = get_atimespec(psbuf);
4922 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4923 (timespec_compare(&ft->mtime, &mts) == 0)) {
4924 return NT_STATUS_OK;
4928 if (setting_write_time) {
4930 * This was a setfileinfo on an open file.
4931 * NT does this a lot. We also need to
4932 * set the time here, as it can be read by
4933 * FindFirst/FindNext and with the patch for bug #2045
4934 * in smbd/fileio.c it ensures that this timestamp is
4935 * kept sticky even after a write. We save the request
4936 * away and will set it on file close and after a write. JRA.
4939 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4940 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4942 if (fsp != NULL) {
4943 if (fsp->base_fsp) {
4944 set_sticky_write_time_fsp(fsp->base_fsp,
4945 ft->mtime);
4946 } else {
4947 set_sticky_write_time_fsp(fsp, ft->mtime);
4949 } else {
4950 set_sticky_write_time_path(conn, fname,
4951 vfs_file_id_from_sbuf(conn, psbuf),
4952 ft->mtime);
4956 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4958 if (fsp && fsp->base_fsp) {
4959 fname = fsp->base_fsp->fsp_name;
4962 if(file_ntimes(conn, fname, ft)!=0) {
4963 return map_nt_error_from_unix(errno);
4965 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4967 return NT_STATUS_OK;
4970 /****************************************************************************
4971 Deal with setting the dosmode from any of the setfilepathinfo functions.
4972 ****************************************************************************/
4974 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4975 files_struct *fsp,
4976 const char *fname,
4977 SMB_STRUCT_STAT *psbuf,
4978 uint32 dosmode)
4980 if (!VALID_STAT(*psbuf)) {
4981 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4984 if (fsp) {
4985 if (fsp->base_fsp) {
4986 fname = fsp->base_fsp->fsp_name;
4987 } else {
4988 fname = fsp->fsp_name;
4992 if (dosmode) {
4993 if (S_ISDIR(psbuf->st_mode)) {
4994 dosmode |= aDIR;
4995 } else {
4996 dosmode &= ~aDIR;
5000 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5002 /* check the mode isn't different, before changing it */
5003 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5005 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5006 fname, (unsigned int)dosmode ));
5008 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5009 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5010 fname, strerror(errno)));
5011 return map_nt_error_from_unix(errno);
5014 return NT_STATUS_OK;
5017 /****************************************************************************
5018 Deal with setting the size from any of the setfilepathinfo functions.
5019 ****************************************************************************/
5021 static NTSTATUS smb_set_file_size(connection_struct *conn,
5022 struct smb_request *req,
5023 files_struct *fsp,
5024 const char *fname,
5025 SMB_STRUCT_STAT *psbuf,
5026 SMB_OFF_T size)
5028 NTSTATUS status = NT_STATUS_OK;
5029 files_struct *new_fsp = NULL;
5031 if (!VALID_STAT(*psbuf)) {
5032 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5035 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5037 if (size == get_file_size_stat(psbuf)) {
5038 return NT_STATUS_OK;
5041 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5042 fname, (double)size ));
5044 if (fsp && fsp->fh->fd != -1) {
5045 /* Handle based call. */
5046 if (vfs_set_filelen(fsp, size) == -1) {
5047 return map_nt_error_from_unix(errno);
5049 trigger_write_time_update_immediate(fsp);
5050 return NT_STATUS_OK;
5053 status = SMB_VFS_CREATE_FILE(
5054 conn, /* conn */
5055 req, /* req */
5056 0, /* root_dir_fid */
5057 fname, /* fname */
5058 0, /* create_file_flags */
5059 FILE_WRITE_ATTRIBUTES, /* access_mask */
5060 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5061 FILE_SHARE_DELETE),
5062 FILE_OPEN, /* create_disposition*/
5063 0, /* create_options */
5064 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5065 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5066 0, /* allocation_size */
5067 NULL, /* sd */
5068 NULL, /* ea_list */
5069 &new_fsp, /* result */
5070 NULL, /* pinfo */
5071 psbuf); /* psbuf */
5073 if (!NT_STATUS_IS_OK(status)) {
5074 /* NB. We check for open_was_deferred in the caller. */
5075 return status;
5078 if (vfs_set_filelen(new_fsp, size) == -1) {
5079 status = map_nt_error_from_unix(errno);
5080 close_file(req, new_fsp,NORMAL_CLOSE);
5081 return status;
5084 trigger_write_time_update_immediate(new_fsp);
5085 close_file(req, new_fsp,NORMAL_CLOSE);
5086 return NT_STATUS_OK;
5089 /****************************************************************************
5090 Deal with SMB_INFO_SET_EA.
5091 ****************************************************************************/
5093 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5094 const char *pdata,
5095 int total_data,
5096 files_struct *fsp,
5097 const char *fname)
5099 struct ea_list *ea_list = NULL;
5100 TALLOC_CTX *ctx = NULL;
5101 NTSTATUS status = NT_STATUS_OK;
5103 if (total_data < 10) {
5105 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5106 length. They seem to have no effect. Bug #3212. JRA */
5108 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5109 /* We're done. We only get EA info in this call. */
5110 return NT_STATUS_OK;
5113 return NT_STATUS_INVALID_PARAMETER;
5116 if (IVAL(pdata,0) > total_data) {
5117 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5118 IVAL(pdata,0), (unsigned int)total_data));
5119 return NT_STATUS_INVALID_PARAMETER;
5122 ctx = talloc_tos();
5123 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5124 if (!ea_list) {
5125 return NT_STATUS_INVALID_PARAMETER;
5127 status = set_ea(conn, fsp, fname, ea_list);
5129 return status;
5132 /****************************************************************************
5133 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5134 ****************************************************************************/
5136 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5137 const char *pdata,
5138 int total_data,
5139 files_struct *fsp,
5140 const char *fname,
5141 SMB_STRUCT_STAT *psbuf)
5143 NTSTATUS status = NT_STATUS_OK;
5144 bool delete_on_close;
5145 uint32 dosmode = 0;
5147 if (total_data < 1) {
5148 return NT_STATUS_INVALID_PARAMETER;
5151 if (fsp == NULL) {
5152 return NT_STATUS_INVALID_HANDLE;
5155 delete_on_close = (CVAL(pdata,0) ? True : False);
5156 dosmode = dos_mode(conn, fname, psbuf);
5158 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5159 "delete_on_close = %u\n",
5160 fsp->fsp_name,
5161 (unsigned int)dosmode,
5162 (unsigned int)delete_on_close ));
5164 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 return status;
5170 /* The set is across all open files on this dev/inode pair. */
5171 if (!set_delete_on_close(fsp, delete_on_close,
5172 &conn->server_info->utok)) {
5173 return NT_STATUS_ACCESS_DENIED;
5175 return NT_STATUS_OK;
5178 /****************************************************************************
5179 Deal with SMB_FILE_POSITION_INFORMATION.
5180 ****************************************************************************/
5182 static NTSTATUS smb_file_position_information(connection_struct *conn,
5183 const char *pdata,
5184 int total_data,
5185 files_struct *fsp)
5187 uint64_t position_information;
5189 if (total_data < 8) {
5190 return NT_STATUS_INVALID_PARAMETER;
5193 if (fsp == NULL) {
5194 /* Ignore on pathname based set. */
5195 return NT_STATUS_OK;
5198 position_information = (uint64_t)IVAL(pdata,0);
5199 #ifdef LARGE_SMB_OFF_T
5200 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5201 #else /* LARGE_SMB_OFF_T */
5202 if (IVAL(pdata,4) != 0) {
5203 /* more than 32 bits? */
5204 return NT_STATUS_INVALID_PARAMETER;
5206 #endif /* LARGE_SMB_OFF_T */
5208 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5209 fsp->fsp_name, (double)position_information ));
5210 fsp->fh->position_information = position_information;
5211 return NT_STATUS_OK;
5214 /****************************************************************************
5215 Deal with SMB_FILE_MODE_INFORMATION.
5216 ****************************************************************************/
5218 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5219 const char *pdata,
5220 int total_data)
5222 uint32 mode;
5224 if (total_data < 4) {
5225 return NT_STATUS_INVALID_PARAMETER;
5227 mode = IVAL(pdata,0);
5228 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5229 return NT_STATUS_INVALID_PARAMETER;
5231 return NT_STATUS_OK;
5234 /****************************************************************************
5235 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5236 ****************************************************************************/
5238 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5239 struct smb_request *req,
5240 const char *pdata,
5241 int total_data,
5242 const char *fname)
5244 char *link_target = NULL;
5245 const char *newname = fname;
5246 NTSTATUS status = NT_STATUS_OK;
5247 TALLOC_CTX *ctx = talloc_tos();
5249 /* Set a symbolic link. */
5250 /* Don't allow this if follow links is false. */
5252 if (total_data == 0) {
5253 return NT_STATUS_INVALID_PARAMETER;
5256 if (!lp_symlinks(SNUM(conn))) {
5257 return NT_STATUS_ACCESS_DENIED;
5260 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5261 total_data, STR_TERMINATE);
5263 if (!link_target) {
5264 return NT_STATUS_INVALID_PARAMETER;
5267 /* !widelinks forces the target path to be within the share. */
5268 /* This means we can interpret the target as a pathname. */
5269 if (!lp_widelinks(SNUM(conn))) {
5270 char *rel_name = NULL;
5271 char *last_dirp = NULL;
5273 if (*link_target == '/') {
5274 /* No absolute paths allowed. */
5275 return NT_STATUS_ACCESS_DENIED;
5277 rel_name = talloc_strdup(ctx,newname);
5278 if (!rel_name) {
5279 return NT_STATUS_NO_MEMORY;
5281 last_dirp = strrchr_m(rel_name, '/');
5282 if (last_dirp) {
5283 last_dirp[1] = '\0';
5284 } else {
5285 rel_name = talloc_strdup(ctx,"./");
5286 if (!rel_name) {
5287 return NT_STATUS_NO_MEMORY;
5290 rel_name = talloc_asprintf_append(rel_name,
5291 "%s",
5292 link_target);
5293 if (!rel_name) {
5294 return NT_STATUS_NO_MEMORY;
5297 status = check_name(conn, rel_name);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 return status;
5303 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5304 newname, link_target ));
5306 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5307 return map_nt_error_from_unix(errno);
5310 return NT_STATUS_OK;
5313 /****************************************************************************
5314 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5315 ****************************************************************************/
5317 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5318 struct smb_request *req,
5319 const char *pdata, int total_data,
5320 const char *fname)
5322 char *oldname = NULL;
5323 TALLOC_CTX *ctx = talloc_tos();
5324 NTSTATUS status = NT_STATUS_OK;
5326 /* Set a hard link. */
5327 if (total_data == 0) {
5328 return NT_STATUS_INVALID_PARAMETER;
5331 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5332 total_data, STR_TERMINATE, &status);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 return status;
5337 status = resolve_dfspath(ctx, conn,
5338 req->flags2 & FLAGS2_DFS_PATHNAMES,
5339 oldname,
5340 &oldname);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 return status;
5345 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5346 fname, oldname));
5348 return hardlink_internals(ctx, conn, oldname, fname);
5351 /****************************************************************************
5352 Deal with SMB_FILE_RENAME_INFORMATION.
5353 ****************************************************************************/
5355 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5356 struct smb_request *req,
5357 const char *pdata,
5358 int total_data,
5359 files_struct *fsp,
5360 const char *fname)
5362 bool overwrite;
5363 uint32 root_fid;
5364 uint32 len;
5365 char *newname = NULL;
5366 char *base_name = NULL;
5367 bool dest_has_wcard = False;
5368 SMB_STRUCT_STAT sbuf;
5369 char *newname_last_component = NULL;
5370 NTSTATUS status = NT_STATUS_OK;
5371 char *p;
5372 TALLOC_CTX *ctx = talloc_tos();
5374 if (total_data < 13) {
5375 return NT_STATUS_INVALID_PARAMETER;
5378 ZERO_STRUCT(sbuf);
5380 overwrite = (CVAL(pdata,0) ? True : False);
5381 root_fid = IVAL(pdata,4);
5382 len = IVAL(pdata,8);
5384 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5385 return NT_STATUS_INVALID_PARAMETER;
5388 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5389 len, 0, &status,
5390 &dest_has_wcard);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 return status;
5395 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5396 newname));
5398 status = resolve_dfspath_wcard(ctx, conn,
5399 req->flags2 & FLAGS2_DFS_PATHNAMES,
5400 newname,
5401 &newname,
5402 &dest_has_wcard);
5403 if (!NT_STATUS_IS_OK(status)) {
5404 return status;
5407 /* Check the new name has no '/' characters. */
5408 if (strchr_m(newname, '/')) {
5409 return NT_STATUS_NOT_SUPPORTED;
5412 if (fsp && fsp->base_fsp) {
5413 /* newname must be a stream name. */
5414 if (newname[0] != ':') {
5415 return NT_STATUS_NOT_SUPPORTED;
5417 base_name = talloc_asprintf(ctx, "%s%s",
5418 fsp->base_fsp->fsp_name,
5419 newname);
5420 if (!base_name) {
5421 return NT_STATUS_NO_MEMORY;
5423 } else {
5424 /* newname must *not* be a stream name. */
5425 if (is_ntfs_stream_name(newname)) {
5426 return NT_STATUS_NOT_SUPPORTED;
5429 /* Create the base directory. */
5430 base_name = talloc_strdup(ctx, fname);
5431 if (!base_name) {
5432 return NT_STATUS_NO_MEMORY;
5434 p = strrchr_m(base_name, '/');
5435 if (p) {
5436 p[1] = '\0';
5437 } else {
5438 base_name = talloc_strdup(ctx, "./");
5439 if (!base_name) {
5440 return NT_STATUS_NO_MEMORY;
5443 /* Append the new name. */
5444 base_name = talloc_asprintf_append(base_name,
5445 "%s",
5446 newname);
5447 if (!base_name) {
5448 return NT_STATUS_NO_MEMORY;
5451 status = unix_convert(ctx, conn, newname, False,
5452 &newname,
5453 &newname_last_component,
5454 &sbuf);
5456 /* If an error we expect this to be
5457 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5459 if (!NT_STATUS_IS_OK(status)
5460 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5461 status)) {
5462 return status;
5466 if (fsp) {
5467 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5468 fsp->fnum, fsp->fsp_name, base_name ));
5469 status = rename_internals_fsp(conn, fsp, base_name,
5470 newname_last_component, 0,
5471 overwrite);
5472 } else {
5473 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5474 fname, base_name ));
5475 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5476 overwrite, False, dest_has_wcard,
5477 FILE_WRITE_ATTRIBUTES);
5480 return status;
5483 /****************************************************************************
5484 Deal with SMB_SET_POSIX_ACL.
5485 ****************************************************************************/
5487 #if defined(HAVE_POSIX_ACLS)
5488 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5489 const char *pdata,
5490 int total_data,
5491 files_struct *fsp,
5492 const char *fname,
5493 SMB_STRUCT_STAT *psbuf)
5495 uint16 posix_acl_version;
5496 uint16 num_file_acls;
5497 uint16 num_def_acls;
5498 bool valid_file_acls = True;
5499 bool valid_def_acls = True;
5501 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5502 return NT_STATUS_INVALID_PARAMETER;
5504 posix_acl_version = SVAL(pdata,0);
5505 num_file_acls = SVAL(pdata,2);
5506 num_def_acls = SVAL(pdata,4);
5508 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5509 valid_file_acls = False;
5510 num_file_acls = 0;
5513 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5514 valid_def_acls = False;
5515 num_def_acls = 0;
5518 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5519 return NT_STATUS_INVALID_PARAMETER;
5522 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5523 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5524 return NT_STATUS_INVALID_PARAMETER;
5527 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5528 fname ? fname : fsp->fsp_name,
5529 (unsigned int)num_file_acls,
5530 (unsigned int)num_def_acls));
5532 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5533 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5534 return map_nt_error_from_unix(errno);
5537 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5538 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5539 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5540 return map_nt_error_from_unix(errno);
5542 return NT_STATUS_OK;
5544 #endif
5546 /****************************************************************************
5547 Deal with SMB_SET_POSIX_LOCK.
5548 ****************************************************************************/
5550 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5551 struct smb_request *req,
5552 const char *pdata,
5553 int total_data,
5554 files_struct *fsp)
5556 uint64_t count;
5557 uint64_t offset;
5558 uint32 lock_pid;
5559 bool blocking_lock = False;
5560 enum brl_type lock_type;
5562 NTSTATUS status = NT_STATUS_OK;
5564 if (fsp == NULL || fsp->fh->fd == -1) {
5565 return NT_STATUS_INVALID_HANDLE;
5568 if (total_data != POSIX_LOCK_DATA_SIZE) {
5569 return NT_STATUS_INVALID_PARAMETER;
5572 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5573 case POSIX_LOCK_TYPE_READ:
5574 lock_type = READ_LOCK;
5575 break;
5576 case POSIX_LOCK_TYPE_WRITE:
5577 /* Return the right POSIX-mappable error code for files opened read-only. */
5578 if (!fsp->can_write) {
5579 return NT_STATUS_INVALID_HANDLE;
5581 lock_type = WRITE_LOCK;
5582 break;
5583 case POSIX_LOCK_TYPE_UNLOCK:
5584 lock_type = UNLOCK_LOCK;
5585 break;
5586 default:
5587 return NT_STATUS_INVALID_PARAMETER;
5590 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5591 blocking_lock = False;
5592 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5593 blocking_lock = True;
5594 } else {
5595 return NT_STATUS_INVALID_PARAMETER;
5598 if (!lp_blocking_locks(SNUM(conn))) {
5599 blocking_lock = False;
5602 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5603 #if defined(HAVE_LONGLONG)
5604 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5605 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5606 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5607 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5608 #else /* HAVE_LONGLONG */
5609 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5610 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5611 #endif /* HAVE_LONGLONG */
5613 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5614 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5615 fsp->fsp_name,
5616 (unsigned int)lock_type,
5617 (unsigned int)lock_pid,
5618 (double)count,
5619 (double)offset ));
5621 if (lock_type == UNLOCK_LOCK) {
5622 status = do_unlock(smbd_messaging_context(),
5623 fsp,
5624 lock_pid,
5625 count,
5626 offset,
5627 POSIX_LOCK);
5628 } else {
5629 uint32 block_smbpid;
5631 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5632 fsp,
5633 lock_pid,
5634 count,
5635 offset,
5636 lock_type,
5637 POSIX_LOCK,
5638 blocking_lock,
5639 &status,
5640 &block_smbpid,
5641 NULL);
5643 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5645 * A blocking lock was requested. Package up
5646 * this smb into a queued request and push it
5647 * onto the blocking lock queue.
5649 if(push_blocking_lock_request(br_lck,
5650 req,
5651 fsp,
5652 -1, /* infinite timeout. */
5654 lock_pid,
5655 lock_type,
5656 POSIX_LOCK,
5657 offset,
5658 count,
5659 block_smbpid)) {
5660 TALLOC_FREE(br_lck);
5661 return status;
5664 TALLOC_FREE(br_lck);
5667 return status;
5670 /****************************************************************************
5671 Deal with SMB_INFO_STANDARD.
5672 ****************************************************************************/
5674 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5675 const char *pdata,
5676 int total_data,
5677 files_struct *fsp,
5678 const char *fname,
5679 const SMB_STRUCT_STAT *psbuf)
5681 struct smb_file_time ft;
5682 ZERO_STRUCT(ft);
5684 if (total_data < 12) {
5685 return NT_STATUS_INVALID_PARAMETER;
5688 /* create time */
5689 ft.create_time = interpret_long_date(pdata);
5691 /* access time */
5692 ft.atime = interpret_long_date(pdata + 8);
5694 /* write time */
5695 ft.mtime = interpret_long_date(pdata + 16);
5697 DEBUG(10,("smb_set_info_standard: file %s\n",
5698 fname ? fname : fsp->fsp_name ));
5700 return smb_set_file_time(conn,
5701 fsp,
5702 fname,
5703 psbuf,
5704 &ft,
5705 true);
5708 /****************************************************************************
5709 Deal with SMB_SET_FILE_BASIC_INFO.
5710 ****************************************************************************/
5712 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5713 const char *pdata,
5714 int total_data,
5715 files_struct *fsp,
5716 const char *fname,
5717 SMB_STRUCT_STAT *psbuf)
5719 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5720 struct timespec write_time;
5721 struct timespec changed_time;
5722 struct smb_file_time ft;
5723 uint32 dosmode = 0;
5724 NTSTATUS status = NT_STATUS_OK;
5725 bool setting_write_time = true;
5727 ZERO_STRUCT(ft);
5729 if (total_data < 36) {
5730 return NT_STATUS_INVALID_PARAMETER;
5733 /* Set the attributes */
5734 dosmode = IVAL(pdata,32);
5735 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5736 if (!NT_STATUS_IS_OK(status)) {
5737 return status;
5740 /* access time */
5741 ft.atime = interpret_long_date(pdata+8);
5743 write_time = interpret_long_date(pdata+16);
5744 changed_time = interpret_long_date(pdata+24);
5746 /* mtime */
5747 ft.mtime = timespec_min(&write_time, &changed_time);
5749 /* create time */
5750 ft.create_time = interpret_long_date(pdata);
5752 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5753 !null_timespec(write_time)) {
5754 ft.mtime = write_time;
5757 /* Prefer a defined time to an undefined one. */
5758 if (null_timespec(ft.mtime)) {
5759 if (null_timespec(write_time)) {
5760 ft.mtime = changed_time;
5761 setting_write_time = false;
5762 } else {
5763 ft.mtime = write_time;
5767 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5768 fname ? fname : fsp->fsp_name ));
5770 return smb_set_file_time(conn,
5771 fsp,
5772 fname,
5773 psbuf,
5774 &ft,
5775 setting_write_time);
5778 /****************************************************************************
5779 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5780 ****************************************************************************/
5782 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5783 struct smb_request *req,
5784 const char *pdata,
5785 int total_data,
5786 files_struct *fsp,
5787 const char *fname,
5788 SMB_STRUCT_STAT *psbuf)
5790 uint64_t allocation_size = 0;
5791 NTSTATUS status = NT_STATUS_OK;
5792 files_struct *new_fsp = NULL;
5794 if (!VALID_STAT(*psbuf)) {
5795 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5798 if (total_data < 8) {
5799 return NT_STATUS_INVALID_PARAMETER;
5802 allocation_size = (uint64_t)IVAL(pdata,0);
5803 #ifdef LARGE_SMB_OFF_T
5804 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5805 #else /* LARGE_SMB_OFF_T */
5806 if (IVAL(pdata,4) != 0) {
5807 /* more than 32 bits? */
5808 return NT_STATUS_INVALID_PARAMETER;
5810 #endif /* LARGE_SMB_OFF_T */
5812 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5813 fname, (double)allocation_size ));
5815 if (allocation_size) {
5816 allocation_size = smb_roundup(conn, allocation_size);
5819 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5820 fname, (double)allocation_size ));
5822 if (fsp && fsp->fh->fd != -1) {
5823 /* Open file handle. */
5824 /* Only change if needed. */
5825 if (allocation_size != get_file_size_stat(psbuf)) {
5826 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5827 return map_nt_error_from_unix(errno);
5830 /* But always update the time. */
5832 * This is equivalent to a write. Ensure it's seen immediately
5833 * if there are no pending writes.
5835 trigger_write_time_update_immediate(fsp);
5836 return NT_STATUS_OK;
5839 /* Pathname or stat or directory file. */
5841 status = SMB_VFS_CREATE_FILE(
5842 conn, /* conn */
5843 req, /* req */
5844 0, /* root_dir_fid */
5845 fname, /* fname */
5846 0, /* create_file_flags */
5847 FILE_WRITE_DATA, /* access_mask */
5848 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5849 FILE_SHARE_DELETE),
5850 FILE_OPEN, /* create_disposition*/
5851 0, /* create_options */
5852 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5853 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5854 0, /* allocation_size */
5855 NULL, /* sd */
5856 NULL, /* ea_list */
5857 &new_fsp, /* result */
5858 NULL, /* pinfo */
5859 psbuf); /* psbuf */
5861 if (!NT_STATUS_IS_OK(status)) {
5862 /* NB. We check for open_was_deferred in the caller. */
5863 return status;
5866 /* Only change if needed. */
5867 if (allocation_size != get_file_size_stat(psbuf)) {
5868 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5869 status = map_nt_error_from_unix(errno);
5870 close_file(req, new_fsp, NORMAL_CLOSE);
5871 return status;
5875 /* Changing the allocation size should set the last mod time. */
5877 * This is equivalent to a write. Ensure it's seen immediately
5878 * if there are no pending writes.
5880 trigger_write_time_update_immediate(new_fsp);
5882 close_file(req, new_fsp, NORMAL_CLOSE);
5883 return NT_STATUS_OK;
5886 /****************************************************************************
5887 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5888 ****************************************************************************/
5890 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5891 struct smb_request *req,
5892 const char *pdata,
5893 int total_data,
5894 files_struct *fsp,
5895 const char *fname,
5896 SMB_STRUCT_STAT *psbuf)
5898 SMB_OFF_T size;
5900 if (total_data < 8) {
5901 return NT_STATUS_INVALID_PARAMETER;
5904 size = IVAL(pdata,0);
5905 #ifdef LARGE_SMB_OFF_T
5906 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5907 #else /* LARGE_SMB_OFF_T */
5908 if (IVAL(pdata,4) != 0) {
5909 /* more than 32 bits? */
5910 return NT_STATUS_INVALID_PARAMETER;
5912 #endif /* LARGE_SMB_OFF_T */
5913 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5914 "file %s to %.0f\n", fname, (double)size ));
5916 return smb_set_file_size(conn, req,
5917 fsp,
5918 fname,
5919 psbuf,
5920 size);
5923 /****************************************************************************
5924 Allow a UNIX info mknod.
5925 ****************************************************************************/
5927 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5928 const char *pdata,
5929 int total_data,
5930 const char *fname,
5931 SMB_STRUCT_STAT *psbuf)
5933 uint32 file_type = IVAL(pdata,56);
5934 #if defined(HAVE_MAKEDEV)
5935 uint32 dev_major = IVAL(pdata,60);
5936 uint32 dev_minor = IVAL(pdata,68);
5937 #endif
5938 SMB_DEV_T dev = (SMB_DEV_T)0;
5939 uint32 raw_unixmode = IVAL(pdata,84);
5940 NTSTATUS status;
5941 mode_t unixmode;
5943 if (total_data < 100) {
5944 return NT_STATUS_INVALID_PARAMETER;
5947 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 return status;
5952 #if defined(HAVE_MAKEDEV)
5953 dev = makedev(dev_major, dev_minor);
5954 #endif
5956 switch (file_type) {
5957 #if defined(S_IFIFO)
5958 case UNIX_TYPE_FIFO:
5959 unixmode |= S_IFIFO;
5960 break;
5961 #endif
5962 #if defined(S_IFSOCK)
5963 case UNIX_TYPE_SOCKET:
5964 unixmode |= S_IFSOCK;
5965 break;
5966 #endif
5967 #if defined(S_IFCHR)
5968 case UNIX_TYPE_CHARDEV:
5969 unixmode |= S_IFCHR;
5970 break;
5971 #endif
5972 #if defined(S_IFBLK)
5973 case UNIX_TYPE_BLKDEV:
5974 unixmode |= S_IFBLK;
5975 break;
5976 #endif
5977 default:
5978 return NT_STATUS_INVALID_PARAMETER;
5981 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5982 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5984 /* Ok - do the mknod. */
5985 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5986 return map_nt_error_from_unix(errno);
5989 /* If any of the other "set" calls fail we
5990 * don't want to end up with a half-constructed mknod.
5993 if (lp_inherit_perms(SNUM(conn))) {
5994 char *parent;
5995 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5996 return NT_STATUS_NO_MEMORY;
5998 inherit_access_posix_acl(conn, parent, fname, unixmode);
5999 TALLOC_FREE(parent);
6002 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6003 status = map_nt_error_from_unix(errno);
6004 SMB_VFS_UNLINK(conn,fname);
6005 return status;
6007 return NT_STATUS_OK;
6010 /****************************************************************************
6011 Deal with SMB_SET_FILE_UNIX_BASIC.
6012 ****************************************************************************/
6014 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6015 struct smb_request *req,
6016 const char *pdata,
6017 int total_data,
6018 files_struct *fsp,
6019 const char *fname,
6020 SMB_STRUCT_STAT *psbuf)
6022 struct smb_file_time ft;
6023 uint32 raw_unixmode;
6024 mode_t unixmode;
6025 SMB_OFF_T size = 0;
6026 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6027 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6028 NTSTATUS status = NT_STATUS_OK;
6029 bool delete_on_fail = False;
6030 enum perm_type ptype;
6032 ZERO_STRUCT(ft);
6034 if (total_data < 100) {
6035 return NT_STATUS_INVALID_PARAMETER;
6038 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6039 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6040 size=IVAL(pdata,0); /* first 8 Bytes are size */
6041 #ifdef LARGE_SMB_OFF_T
6042 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6043 #else /* LARGE_SMB_OFF_T */
6044 if (IVAL(pdata,4) != 0) {
6045 /* more than 32 bits? */
6046 return NT_STATUS_INVALID_PARAMETER;
6048 #endif /* LARGE_SMB_OFF_T */
6051 ft.atime = interpret_long_date(pdata+24); /* access_time */
6052 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6053 set_owner = (uid_t)IVAL(pdata,40);
6054 set_grp = (gid_t)IVAL(pdata,48);
6055 raw_unixmode = IVAL(pdata,84);
6057 if (VALID_STAT(*psbuf)) {
6058 if (S_ISDIR(psbuf->st_mode)) {
6059 ptype = PERM_EXISTING_DIR;
6060 } else {
6061 ptype = PERM_EXISTING_FILE;
6063 } else {
6064 ptype = PERM_NEW_FILE;
6067 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6068 if (!NT_STATUS_IS_OK(status)) {
6069 return status;
6072 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6073 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6074 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6076 if (!VALID_STAT(*psbuf)) {
6078 * The only valid use of this is to create character and block
6079 * devices, and named pipes. This is deprecated (IMHO) and
6080 * a new info level should be used for mknod. JRA.
6083 status = smb_unix_mknod(conn,
6084 pdata,
6085 total_data,
6086 fname,
6087 psbuf);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 return status;
6092 /* Ensure we don't try and change anything else. */
6093 raw_unixmode = SMB_MODE_NO_CHANGE;
6094 size = get_file_size_stat(psbuf);
6095 ft.atime = get_atimespec(psbuf);
6096 ft.mtime = get_mtimespec(psbuf);
6098 * We continue here as we might want to change the
6099 * owner uid/gid.
6101 delete_on_fail = True;
6104 #if 1
6105 /* Horrible backwards compatibility hack as an old server bug
6106 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6107 * */
6109 if (!size) {
6110 size = get_file_size_stat(psbuf);
6112 #endif
6115 * Deal with the UNIX specific mode set.
6118 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6119 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6120 (unsigned int)unixmode, fname ));
6121 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6122 return map_nt_error_from_unix(errno);
6127 * Deal with the UNIX specific uid set.
6130 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6131 int ret;
6133 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6134 (unsigned int)set_owner, fname ));
6136 if (S_ISLNK(psbuf->st_mode)) {
6137 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6138 } else {
6139 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6142 if (ret != 0) {
6143 status = map_nt_error_from_unix(errno);
6144 if (delete_on_fail) {
6145 SMB_VFS_UNLINK(conn,fname);
6147 return status;
6152 * Deal with the UNIX specific gid set.
6155 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6156 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6157 (unsigned int)set_owner, fname ));
6158 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6159 status = map_nt_error_from_unix(errno);
6160 if (delete_on_fail) {
6161 SMB_VFS_UNLINK(conn,fname);
6163 return status;
6167 /* Deal with any size changes. */
6169 status = smb_set_file_size(conn, req,
6170 fsp,
6171 fname,
6172 psbuf,
6173 size);
6174 if (!NT_STATUS_IS_OK(status)) {
6175 return status;
6178 /* Deal with any time changes. */
6180 return smb_set_file_time(conn,
6181 fsp,
6182 fname,
6183 psbuf,
6184 &ft,
6185 true);
6188 /****************************************************************************
6189 Deal with SMB_SET_FILE_UNIX_INFO2.
6190 ****************************************************************************/
6192 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6193 struct smb_request *req,
6194 const char *pdata,
6195 int total_data,
6196 files_struct *fsp,
6197 const char *fname,
6198 SMB_STRUCT_STAT *psbuf)
6200 NTSTATUS status;
6201 uint32 smb_fflags;
6202 uint32 smb_fmask;
6204 if (total_data < 116) {
6205 return NT_STATUS_INVALID_PARAMETER;
6208 /* Start by setting all the fields that are common between UNIX_BASIC
6209 * and UNIX_INFO2.
6211 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6212 fsp, fname, psbuf);
6213 if (!NT_STATUS_IS_OK(status)) {
6214 return status;
6217 smb_fflags = IVAL(pdata, 108);
6218 smb_fmask = IVAL(pdata, 112);
6220 /* NB: We should only attempt to alter the file flags if the client
6221 * sends a non-zero mask.
6223 if (smb_fmask != 0) {
6224 int stat_fflags = 0;
6226 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6227 &stat_fflags)) {
6228 /* Client asked to alter a flag we don't understand. */
6229 return NT_STATUS_INVALID_PARAMETER;
6232 if (fsp && fsp->fh->fd != -1) {
6233 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6234 return NT_STATUS_NOT_SUPPORTED;
6235 } else {
6236 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6237 return map_nt_error_from_unix(errno);
6242 /* XXX: need to add support for changing the create_time here. You
6243 * can do this for paths on Darwin with setattrlist(2). The right way
6244 * to hook this up is probably by extending the VFS utimes interface.
6247 return NT_STATUS_OK;
6250 /****************************************************************************
6251 Create a directory with POSIX semantics.
6252 ****************************************************************************/
6254 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6255 struct smb_request *req,
6256 char **ppdata,
6257 int total_data,
6258 const char *fname,
6259 SMB_STRUCT_STAT *psbuf,
6260 int *pdata_return_size)
6262 NTSTATUS status = NT_STATUS_OK;
6263 uint32 raw_unixmode = 0;
6264 uint32 mod_unixmode = 0;
6265 mode_t unixmode = (mode_t)0;
6266 files_struct *fsp = NULL;
6267 uint16 info_level_return = 0;
6268 int info;
6269 char *pdata = *ppdata;
6271 if (total_data < 18) {
6272 return NT_STATUS_INVALID_PARAMETER;
6275 raw_unixmode = IVAL(pdata,8);
6276 /* Next 4 bytes are not yet defined. */
6278 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 return status;
6283 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6285 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6286 fname, (unsigned int)unixmode ));
6288 status = SMB_VFS_CREATE_FILE(
6289 conn, /* conn */
6290 req, /* req */
6291 0, /* root_dir_fid */
6292 fname, /* fname */
6293 0, /* create_file_flags */
6294 FILE_READ_ATTRIBUTES, /* access_mask */
6295 FILE_SHARE_NONE, /* share_access */
6296 FILE_CREATE, /* create_disposition*/
6297 FILE_DIRECTORY_FILE, /* create_options */
6298 mod_unixmode, /* file_attributes */
6299 0, /* oplock_request */
6300 0, /* allocation_size */
6301 NULL, /* sd */
6302 NULL, /* ea_list */
6303 &fsp, /* result */
6304 &info, /* pinfo */
6305 psbuf); /* psbuf */
6307 if (NT_STATUS_IS_OK(status)) {
6308 close_file(req, fsp, NORMAL_CLOSE);
6311 info_level_return = SVAL(pdata,16);
6313 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6314 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6315 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6316 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6317 } else {
6318 *pdata_return_size = 12;
6321 /* Realloc the data size */
6322 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6323 if (*ppdata == NULL) {
6324 *pdata_return_size = 0;
6325 return NT_STATUS_NO_MEMORY;
6327 pdata = *ppdata;
6329 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6330 SSVAL(pdata,2,0); /* No fnum. */
6331 SIVAL(pdata,4,info); /* Was directory created. */
6333 switch (info_level_return) {
6334 case SMB_QUERY_FILE_UNIX_BASIC:
6335 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6336 SSVAL(pdata,10,0); /* Padding. */
6337 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6338 break;
6339 case SMB_QUERY_FILE_UNIX_INFO2:
6340 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6341 SSVAL(pdata,10,0); /* Padding. */
6342 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6343 break;
6344 default:
6345 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6346 SSVAL(pdata,10,0); /* Padding. */
6347 break;
6350 return status;
6353 /****************************************************************************
6354 Open/Create a file with POSIX semantics.
6355 ****************************************************************************/
6357 static NTSTATUS smb_posix_open(connection_struct *conn,
6358 struct smb_request *req,
6359 char **ppdata,
6360 int total_data,
6361 const char *fname,
6362 SMB_STRUCT_STAT *psbuf,
6363 int *pdata_return_size)
6365 bool extended_oplock_granted = False;
6366 char *pdata = *ppdata;
6367 uint32 flags = 0;
6368 uint32 wire_open_mode = 0;
6369 uint32 raw_unixmode = 0;
6370 uint32 mod_unixmode = 0;
6371 uint32 create_disp = 0;
6372 uint32 access_mask = 0;
6373 uint32 create_options = 0;
6374 NTSTATUS status = NT_STATUS_OK;
6375 mode_t unixmode = (mode_t)0;
6376 files_struct *fsp = NULL;
6377 int oplock_request = 0;
6378 int info = 0;
6379 uint16 info_level_return = 0;
6381 if (total_data < 18) {
6382 return NT_STATUS_INVALID_PARAMETER;
6385 flags = IVAL(pdata,0);
6386 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6387 if (oplock_request) {
6388 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6391 wire_open_mode = IVAL(pdata,4);
6393 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6394 return smb_posix_mkdir(conn, req,
6395 ppdata,
6396 total_data,
6397 fname,
6398 psbuf,
6399 pdata_return_size);
6402 switch (wire_open_mode & SMB_ACCMODE) {
6403 case SMB_O_RDONLY:
6404 access_mask = FILE_READ_DATA;
6405 break;
6406 case SMB_O_WRONLY:
6407 access_mask = FILE_WRITE_DATA;
6408 break;
6409 case SMB_O_RDWR:
6410 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6411 break;
6412 default:
6413 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6414 (unsigned int)wire_open_mode ));
6415 return NT_STATUS_INVALID_PARAMETER;
6418 wire_open_mode &= ~SMB_ACCMODE;
6420 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6421 create_disp = FILE_CREATE;
6422 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6423 create_disp = FILE_OVERWRITE_IF;
6424 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6425 create_disp = FILE_OPEN_IF;
6426 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6427 create_disp = FILE_OPEN;
6428 } else {
6429 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6430 (unsigned int)wire_open_mode ));
6431 return NT_STATUS_INVALID_PARAMETER;
6434 raw_unixmode = IVAL(pdata,8);
6435 /* Next 4 bytes are not yet defined. */
6437 status = unix_perms_from_wire(conn,
6438 psbuf,
6439 raw_unixmode,
6440 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6441 &unixmode);
6443 if (!NT_STATUS_IS_OK(status)) {
6444 return status;
6447 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6449 if (wire_open_mode & SMB_O_SYNC) {
6450 create_options |= FILE_WRITE_THROUGH;
6452 if (wire_open_mode & SMB_O_APPEND) {
6453 access_mask |= FILE_APPEND_DATA;
6455 if (wire_open_mode & SMB_O_DIRECT) {
6456 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6459 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6460 fname,
6461 (unsigned int)wire_open_mode,
6462 (unsigned int)unixmode ));
6464 status = SMB_VFS_CREATE_FILE(
6465 conn, /* conn */
6466 req, /* req */
6467 0, /* root_dir_fid */
6468 fname, /* fname */
6469 0, /* create_file_flags */
6470 access_mask, /* access_mask */
6471 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6472 FILE_SHARE_DELETE),
6473 create_disp, /* create_disposition*/
6474 0, /* create_options */
6475 mod_unixmode, /* file_attributes */
6476 oplock_request, /* oplock_request */
6477 0, /* allocation_size */
6478 NULL, /* sd */
6479 NULL, /* ea_list */
6480 &fsp, /* result */
6481 &info, /* pinfo */
6482 psbuf); /* psbuf */
6484 if (!NT_STATUS_IS_OK(status)) {
6485 return status;
6488 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6489 extended_oplock_granted = True;
6492 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6493 extended_oplock_granted = True;
6496 info_level_return = SVAL(pdata,16);
6498 /* Allocate the correct return size. */
6500 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6501 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6502 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6503 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6504 } else {
6505 *pdata_return_size = 12;
6508 /* Realloc the data size */
6509 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6510 if (*ppdata == NULL) {
6511 close_file(req, fsp, ERROR_CLOSE);
6512 *pdata_return_size = 0;
6513 return NT_STATUS_NO_MEMORY;
6515 pdata = *ppdata;
6517 if (extended_oplock_granted) {
6518 if (flags & REQUEST_BATCH_OPLOCK) {
6519 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6520 } else {
6521 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6523 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6524 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6525 } else {
6526 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6529 SSVAL(pdata,2,fsp->fnum);
6530 SIVAL(pdata,4,info); /* Was file created etc. */
6532 switch (info_level_return) {
6533 case SMB_QUERY_FILE_UNIX_BASIC:
6534 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6535 SSVAL(pdata,10,0); /* padding. */
6536 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6537 break;
6538 case SMB_QUERY_FILE_UNIX_INFO2:
6539 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6540 SSVAL(pdata,10,0); /* padding. */
6541 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6542 break;
6543 default:
6544 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6545 SSVAL(pdata,10,0); /* padding. */
6546 break;
6548 return NT_STATUS_OK;
6551 /****************************************************************************
6552 Delete a file with POSIX semantics.
6553 ****************************************************************************/
6555 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6556 struct smb_request *req,
6557 const char *pdata,
6558 int total_data,
6559 const char *fname,
6560 SMB_STRUCT_STAT *psbuf)
6562 NTSTATUS status = NT_STATUS_OK;
6563 files_struct *fsp = NULL;
6564 uint16 flags = 0;
6565 char del = 1;
6566 int info = 0;
6567 int create_options = 0;
6568 int i;
6569 struct share_mode_lock *lck = NULL;
6571 if (total_data < 2) {
6572 return NT_STATUS_INVALID_PARAMETER;
6575 flags = SVAL(pdata,0);
6577 if (!VALID_STAT(*psbuf)) {
6578 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6581 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6582 !VALID_STAT_OF_DIR(*psbuf)) {
6583 return NT_STATUS_NOT_A_DIRECTORY;
6586 DEBUG(10,("smb_posix_unlink: %s %s\n",
6587 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6588 fname));
6590 if (VALID_STAT_OF_DIR(*psbuf)) {
6591 create_options |= FILE_DIRECTORY_FILE;
6594 status = SMB_VFS_CREATE_FILE(
6595 conn, /* conn */
6596 req, /* req */
6597 0, /* root_dir_fid */
6598 fname, /* fname */
6599 0, /* create_file_flags */
6600 DELETE_ACCESS, /* access_mask */
6601 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6602 FILE_SHARE_DELETE),
6603 FILE_OPEN, /* create_disposition*/
6604 create_options, /* create_options */
6605 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6606 0, /* oplock_request */
6607 0, /* allocation_size */
6608 NULL, /* sd */
6609 NULL, /* ea_list */
6610 &fsp, /* result */
6611 &info, /* pinfo */
6612 psbuf); /* psbuf */
6614 if (!NT_STATUS_IS_OK(status)) {
6615 return status;
6619 * Don't lie to client. If we can't really delete due to
6620 * non-POSIX opens return SHARING_VIOLATION.
6623 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6624 NULL);
6625 if (lck == NULL) {
6626 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6627 "lock for file %s\n", fsp->fsp_name));
6628 close_file(req, fsp, NORMAL_CLOSE);
6629 return NT_STATUS_INVALID_PARAMETER;
6633 * See if others still have the file open. If this is the case, then
6634 * don't delete. If all opens are POSIX delete we can set the delete
6635 * on close disposition.
6637 for (i=0; i<lck->num_share_modes; i++) {
6638 struct share_mode_entry *e = &lck->share_modes[i];
6639 if (is_valid_share_mode_entry(e)) {
6640 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6641 continue;
6643 /* Fail with sharing violation. */
6644 close_file(req, fsp, NORMAL_CLOSE);
6645 TALLOC_FREE(lck);
6646 return NT_STATUS_SHARING_VIOLATION;
6651 * Set the delete on close.
6653 status = smb_set_file_disposition_info(conn,
6654 &del,
6656 fsp,
6657 fname,
6658 psbuf);
6660 if (!NT_STATUS_IS_OK(status)) {
6661 close_file(req, fsp, NORMAL_CLOSE);
6662 TALLOC_FREE(lck);
6663 return status;
6665 TALLOC_FREE(lck);
6666 return close_file(req, fsp, NORMAL_CLOSE);
6669 /****************************************************************************
6670 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6671 ****************************************************************************/
6673 static void call_trans2setfilepathinfo(connection_struct *conn,
6674 struct smb_request *req,
6675 unsigned int tran_call,
6676 char **pparams, int total_params,
6677 char **ppdata, int total_data,
6678 unsigned int max_data_bytes)
6680 char *params = *pparams;
6681 char *pdata = *ppdata;
6682 uint16 info_level;
6683 SMB_STRUCT_STAT sbuf;
6684 char *fname = NULL;
6685 files_struct *fsp = NULL;
6686 NTSTATUS status = NT_STATUS_OK;
6687 int data_return_size = 0;
6688 TALLOC_CTX *ctx = talloc_tos();
6690 if (!params) {
6691 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6692 return;
6695 ZERO_STRUCT(sbuf);
6697 if (tran_call == TRANSACT2_SETFILEINFO) {
6698 if (total_params < 4) {
6699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6700 return;
6703 fsp = file_fsp(req, SVAL(params,0));
6704 /* Basic check for non-null fsp. */
6705 if (!check_fsp_open(conn, req, fsp)) {
6706 return;
6708 info_level = SVAL(params,2);
6710 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6711 if (!fname) {
6712 reply_nterror(req, NT_STATUS_NO_MEMORY);
6713 return;
6716 if(fsp->is_directory || fsp->fh->fd == -1) {
6718 * This is actually a SETFILEINFO on a directory
6719 * handle (returned from an NT SMB). NT5.0 seems
6720 * to do this call. JRA.
6722 if (INFO_LEVEL_IS_UNIX(info_level)) {
6723 /* Always do lstat for UNIX calls. */
6724 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6725 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6726 reply_unixerror(req,ERRDOS,ERRbadpath);
6727 return;
6729 } else {
6730 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6731 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6732 reply_unixerror(req,ERRDOS,ERRbadpath);
6733 return;
6736 } else if (fsp->print_file) {
6738 * Doing a DELETE_ON_CLOSE should cancel a print job.
6740 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6741 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6743 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6745 SSVAL(params,0,0);
6746 send_trans2_replies(conn, req, params, 2,
6747 *ppdata, 0,
6748 max_data_bytes);
6749 return;
6750 } else {
6751 reply_unixerror(req, ERRDOS, ERRbadpath);
6752 return;
6754 } else {
6756 * Original code - this is an open file.
6758 if (!check_fsp(conn, req, fsp)) {
6759 return;
6762 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6763 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6764 reply_unixerror(req, ERRDOS, ERRbadfid);
6765 return;
6768 } else {
6769 /* set path info */
6770 if (total_params < 7) {
6771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6772 return;
6775 info_level = SVAL(params,0);
6776 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6777 total_params - 6, STR_TERMINATE,
6778 &status);
6779 if (!NT_STATUS_IS_OK(status)) {
6780 reply_nterror(req, status);
6781 return;
6784 status = resolve_dfspath(ctx, conn,
6785 req->flags2 & FLAGS2_DFS_PATHNAMES,
6786 fname,
6787 &fname);
6788 if (!NT_STATUS_IS_OK(status)) {
6789 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6790 reply_botherror(req,
6791 NT_STATUS_PATH_NOT_COVERED,
6792 ERRSRV, ERRbadpath);
6793 return;
6795 reply_nterror(req, status);
6796 return;
6799 status = unix_convert(ctx, conn, fname, False,
6800 &fname, NULL, &sbuf);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 reply_nterror(req, status);
6803 return;
6806 status = check_name(conn, fname);
6807 if (!NT_STATUS_IS_OK(status)) {
6808 reply_nterror(req, status);
6809 return;
6812 if (INFO_LEVEL_IS_UNIX(info_level)) {
6814 * For CIFS UNIX extensions the target name may not exist.
6817 /* Always do lstat for UNIX calls. */
6818 SMB_VFS_LSTAT(conn,fname,&sbuf);
6820 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6821 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6822 reply_unixerror(req, ERRDOS, ERRbadpath);
6823 return;
6827 if (!CAN_WRITE(conn)) {
6828 reply_doserror(req, ERRSRV, ERRaccess);
6829 return;
6832 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6833 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6834 return;
6837 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6838 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6840 /* Realloc the parameter size */
6841 *pparams = (char *)SMB_REALLOC(*pparams,2);
6842 if (*pparams == NULL) {
6843 reply_nterror(req, NT_STATUS_NO_MEMORY);
6844 return;
6846 params = *pparams;
6848 SSVAL(params,0,0);
6850 switch (info_level) {
6852 case SMB_INFO_STANDARD:
6854 status = smb_set_info_standard(conn,
6855 pdata,
6856 total_data,
6857 fsp,
6858 fname,
6859 &sbuf);
6860 break;
6863 case SMB_INFO_SET_EA:
6865 status = smb_info_set_ea(conn,
6866 pdata,
6867 total_data,
6868 fsp,
6869 fname);
6870 break;
6873 case SMB_SET_FILE_BASIC_INFO:
6874 case SMB_FILE_BASIC_INFORMATION:
6876 status = smb_set_file_basic_info(conn,
6877 pdata,
6878 total_data,
6879 fsp,
6880 fname,
6881 &sbuf);
6882 break;
6885 case SMB_FILE_ALLOCATION_INFORMATION:
6886 case SMB_SET_FILE_ALLOCATION_INFO:
6888 status = smb_set_file_allocation_info(conn, req,
6889 pdata,
6890 total_data,
6891 fsp,
6892 fname,
6893 &sbuf);
6894 break;
6897 case SMB_FILE_END_OF_FILE_INFORMATION:
6898 case SMB_SET_FILE_END_OF_FILE_INFO:
6900 status = smb_set_file_end_of_file_info(conn, req,
6901 pdata,
6902 total_data,
6903 fsp,
6904 fname,
6905 &sbuf);
6906 break;
6909 case SMB_FILE_DISPOSITION_INFORMATION:
6910 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6912 #if 0
6913 /* JRA - We used to just ignore this on a path ?
6914 * Shouldn't this be invalid level on a pathname
6915 * based call ?
6917 if (tran_call != TRANSACT2_SETFILEINFO) {
6918 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6920 #endif
6921 status = smb_set_file_disposition_info(conn,
6922 pdata,
6923 total_data,
6924 fsp,
6925 fname,
6926 &sbuf);
6927 break;
6930 case SMB_FILE_POSITION_INFORMATION:
6932 status = smb_file_position_information(conn,
6933 pdata,
6934 total_data,
6935 fsp);
6936 break;
6939 /* From tridge Samba4 :
6940 * MODE_INFORMATION in setfileinfo (I have no
6941 * idea what "mode information" on a file is - it takes a value of 0,
6942 * 2, 4 or 6. What could it be?).
6945 case SMB_FILE_MODE_INFORMATION:
6947 status = smb_file_mode_information(conn,
6948 pdata,
6949 total_data);
6950 break;
6954 * CIFS UNIX extensions.
6957 case SMB_SET_FILE_UNIX_BASIC:
6959 status = smb_set_file_unix_basic(conn, req,
6960 pdata,
6961 total_data,
6962 fsp,
6963 fname,
6964 &sbuf);
6965 break;
6968 case SMB_SET_FILE_UNIX_INFO2:
6970 status = smb_set_file_unix_info2(conn, req,
6971 pdata,
6972 total_data,
6973 fsp,
6974 fname,
6975 &sbuf);
6976 break;
6979 case SMB_SET_FILE_UNIX_LINK:
6981 if (tran_call != TRANSACT2_SETPATHINFO) {
6982 /* We must have a pathname for this. */
6983 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6984 return;
6986 status = smb_set_file_unix_link(conn, req, pdata,
6987 total_data, fname);
6988 break;
6991 case SMB_SET_FILE_UNIX_HLINK:
6993 if (tran_call != TRANSACT2_SETPATHINFO) {
6994 /* We must have a pathname for this. */
6995 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6996 return;
6998 status = smb_set_file_unix_hlink(conn, req,
6999 pdata, total_data,
7000 fname);
7001 break;
7004 case SMB_FILE_RENAME_INFORMATION:
7006 status = smb_file_rename_information(conn, req,
7007 pdata, total_data,
7008 fsp, fname);
7009 break;
7012 #if defined(HAVE_POSIX_ACLS)
7013 case SMB_SET_POSIX_ACL:
7015 status = smb_set_posix_acl(conn,
7016 pdata,
7017 total_data,
7018 fsp,
7019 fname,
7020 &sbuf);
7021 break;
7023 #endif
7025 case SMB_SET_POSIX_LOCK:
7027 if (tran_call != TRANSACT2_SETFILEINFO) {
7028 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7029 return;
7031 status = smb_set_posix_lock(conn, req,
7032 pdata, total_data, fsp);
7033 break;
7036 case SMB_POSIX_PATH_OPEN:
7038 if (tran_call != TRANSACT2_SETPATHINFO) {
7039 /* We must have a pathname for this. */
7040 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7041 return;
7044 status = smb_posix_open(conn, req,
7045 ppdata,
7046 total_data,
7047 fname,
7048 &sbuf,
7049 &data_return_size);
7050 break;
7053 case SMB_POSIX_PATH_UNLINK:
7055 if (tran_call != TRANSACT2_SETPATHINFO) {
7056 /* We must have a pathname for this. */
7057 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7058 return;
7061 status = smb_posix_unlink(conn, req,
7062 pdata,
7063 total_data,
7064 fname,
7065 &sbuf);
7066 break;
7069 default:
7070 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7071 return;
7075 if (!NT_STATUS_IS_OK(status)) {
7076 if (open_was_deferred(req->mid)) {
7077 /* We have re-scheduled this call. */
7078 return;
7080 if (blocking_lock_was_deferred(req->mid)) {
7081 /* We have re-scheduled this call. */
7082 return;
7084 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7085 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7086 ERRSRV, ERRbadpath);
7087 return;
7089 if (info_level == SMB_POSIX_PATH_OPEN) {
7090 reply_openerror(req, status);
7091 return;
7094 reply_nterror(req, status);
7095 return;
7098 SSVAL(params,0,0);
7099 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7100 max_data_bytes);
7102 return;
7105 /****************************************************************************
7106 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7107 ****************************************************************************/
7109 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7110 char **pparams, int total_params,
7111 char **ppdata, int total_data,
7112 unsigned int max_data_bytes)
7114 char *params = *pparams;
7115 char *pdata = *ppdata;
7116 char *directory = NULL;
7117 SMB_STRUCT_STAT sbuf;
7118 NTSTATUS status = NT_STATUS_OK;
7119 struct ea_list *ea_list = NULL;
7120 TALLOC_CTX *ctx = talloc_tos();
7122 if (!CAN_WRITE(conn)) {
7123 reply_doserror(req, ERRSRV, ERRaccess);
7124 return;
7127 if (total_params < 5) {
7128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7129 return;
7132 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7133 total_params - 4, STR_TERMINATE,
7134 &status);
7135 if (!NT_STATUS_IS_OK(status)) {
7136 reply_nterror(req, status);
7137 return;
7140 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7142 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7143 if (!NT_STATUS_IS_OK(status)) {
7144 reply_nterror(req, status);
7145 return;
7148 status = check_name(conn, directory);
7149 if (!NT_STATUS_IS_OK(status)) {
7150 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7151 reply_nterror(req, status);
7152 return;
7155 /* Any data in this call is an EA list. */
7156 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7157 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7158 return;
7162 * OS/2 workplace shell seems to send SET_EA requests of "null"
7163 * length (4 bytes containing IVAL 4).
7164 * They seem to have no effect. Bug #3212. JRA.
7167 if (total_data != 4) {
7168 if (total_data < 10) {
7169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7170 return;
7173 if (IVAL(pdata,0) > total_data) {
7174 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7175 IVAL(pdata,0), (unsigned int)total_data));
7176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7177 return;
7180 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7181 total_data - 4);
7182 if (!ea_list) {
7183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7184 return;
7187 /* If total_data == 4 Windows doesn't care what values
7188 * are placed in that field, it just ignores them.
7189 * The System i QNTC IBM SMB client puts bad values here,
7190 * so ignore them. */
7192 status = create_directory(conn, req, directory);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 reply_nterror(req, status);
7196 return;
7199 /* Try and set any given EA. */
7200 if (ea_list) {
7201 status = set_ea(conn, NULL, directory, ea_list);
7202 if (!NT_STATUS_IS_OK(status)) {
7203 reply_nterror(req, status);
7204 return;
7208 /* Realloc the parameter and data sizes */
7209 *pparams = (char *)SMB_REALLOC(*pparams,2);
7210 if(*pparams == NULL) {
7211 reply_nterror(req, NT_STATUS_NO_MEMORY);
7212 return;
7214 params = *pparams;
7216 SSVAL(params,0,0);
7218 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7220 return;
7223 /****************************************************************************
7224 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7225 We don't actually do this - we just send a null response.
7226 ****************************************************************************/
7228 static void call_trans2findnotifyfirst(connection_struct *conn,
7229 struct smb_request *req,
7230 char **pparams, int total_params,
7231 char **ppdata, int total_data,
7232 unsigned int max_data_bytes)
7234 char *params = *pparams;
7235 uint16 info_level;
7237 if (total_params < 6) {
7238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7239 return;
7242 info_level = SVAL(params,4);
7243 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7245 switch (info_level) {
7246 case 1:
7247 case 2:
7248 break;
7249 default:
7250 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7251 return;
7254 /* Realloc the parameter and data sizes */
7255 *pparams = (char *)SMB_REALLOC(*pparams,6);
7256 if (*pparams == NULL) {
7257 reply_nterror(req, NT_STATUS_NO_MEMORY);
7258 return;
7260 params = *pparams;
7262 SSVAL(params,0,fnf_handle);
7263 SSVAL(params,2,0); /* No changes */
7264 SSVAL(params,4,0); /* No EA errors */
7266 fnf_handle++;
7268 if(fnf_handle == 0)
7269 fnf_handle = 257;
7271 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7273 return;
7276 /****************************************************************************
7277 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7278 changes). Currently this does nothing.
7279 ****************************************************************************/
7281 static void call_trans2findnotifynext(connection_struct *conn,
7282 struct smb_request *req,
7283 char **pparams, int total_params,
7284 char **ppdata, int total_data,
7285 unsigned int max_data_bytes)
7287 char *params = *pparams;
7289 DEBUG(3,("call_trans2findnotifynext\n"));
7291 /* Realloc the parameter and data sizes */
7292 *pparams = (char *)SMB_REALLOC(*pparams,4);
7293 if (*pparams == NULL) {
7294 reply_nterror(req, NT_STATUS_NO_MEMORY);
7295 return;
7297 params = *pparams;
7299 SSVAL(params,0,0); /* No changes */
7300 SSVAL(params,2,0); /* No EA errors */
7302 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7304 return;
7307 /****************************************************************************
7308 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7309 ****************************************************************************/
7311 static void call_trans2getdfsreferral(connection_struct *conn,
7312 struct smb_request *req,
7313 char **pparams, int total_params,
7314 char **ppdata, int total_data,
7315 unsigned int max_data_bytes)
7317 char *params = *pparams;
7318 char *pathname = NULL;
7319 int reply_size = 0;
7320 int max_referral_level;
7321 NTSTATUS status = NT_STATUS_OK;
7322 TALLOC_CTX *ctx = talloc_tos();
7324 DEBUG(10,("call_trans2getdfsreferral\n"));
7326 if (total_params < 3) {
7327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7328 return;
7331 max_referral_level = SVAL(params,0);
7333 if(!lp_host_msdfs()) {
7334 reply_doserror(req, ERRDOS, ERRbadfunc);
7335 return;
7338 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7339 total_params - 2, STR_TERMINATE);
7340 if (!pathname) {
7341 reply_nterror(req, NT_STATUS_NOT_FOUND);
7342 return;
7344 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7345 ppdata,&status)) < 0) {
7346 reply_nterror(req, status);
7347 return;
7350 SSVAL(req->inbuf, smb_flg2,
7351 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7352 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7354 return;
7357 #define LMCAT_SPL 0x53
7358 #define LMFUNC_GETJOBID 0x60
7360 /****************************************************************************
7361 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7362 ****************************************************************************/
7364 static void call_trans2ioctl(connection_struct *conn,
7365 struct smb_request *req,
7366 char **pparams, int total_params,
7367 char **ppdata, int total_data,
7368 unsigned int max_data_bytes)
7370 char *pdata = *ppdata;
7371 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7373 /* check for an invalid fid before proceeding */
7375 if (!fsp) {
7376 reply_doserror(req, ERRDOS, ERRbadfid);
7377 return;
7380 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7381 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7382 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7383 if (*ppdata == NULL) {
7384 reply_nterror(req, NT_STATUS_NO_MEMORY);
7385 return;
7387 pdata = *ppdata;
7389 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7390 CAN ACCEPT THIS IN UNICODE. JRA. */
7392 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7393 srvstr_push(pdata, req->flags2, pdata + 2,
7394 global_myname(), 15,
7395 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7396 srvstr_push(pdata, req->flags2, pdata+18,
7397 lp_servicename(SNUM(conn)), 13,
7398 STR_ASCII|STR_TERMINATE); /* Service name */
7399 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7400 max_data_bytes);
7401 return;
7404 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7405 reply_doserror(req, ERRSRV, ERRerror);
7408 /****************************************************************************
7409 Reply to a SMBfindclose (stop trans2 directory search).
7410 ****************************************************************************/
7412 void reply_findclose(struct smb_request *req)
7414 int dptr_num;
7416 START_PROFILE(SMBfindclose);
7418 if (req->wct < 1) {
7419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7420 END_PROFILE(SMBfindclose);
7421 return;
7424 dptr_num = SVALS(req->vwv+0, 0);
7426 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7428 dptr_close(&dptr_num);
7430 reply_outbuf(req, 0, 0);
7432 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7434 END_PROFILE(SMBfindclose);
7435 return;
7438 /****************************************************************************
7439 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7440 ****************************************************************************/
7442 void reply_findnclose(struct smb_request *req)
7444 int dptr_num;
7446 START_PROFILE(SMBfindnclose);
7448 if (req->wct < 1) {
7449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7450 END_PROFILE(SMBfindnclose);
7451 return;
7454 dptr_num = SVAL(req->vwv+0, 0);
7456 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7458 /* We never give out valid handles for a
7459 findnotifyfirst - so any dptr_num is ok here.
7460 Just ignore it. */
7462 reply_outbuf(req, 0, 0);
7464 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7466 END_PROFILE(SMBfindnclose);
7467 return;
7470 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7471 struct trans_state *state)
7473 if (Protocol >= PROTOCOL_NT1) {
7474 req->flags2 |= 0x40; /* IS_LONG_NAME */
7475 SSVAL(req->inbuf,smb_flg2,req->flags2);
7478 if (conn->encrypt_level == Required && !req->encrypted) {
7479 if (state->call != TRANSACT2_QFSINFO &&
7480 state->call != TRANSACT2_SETFSINFO) {
7481 DEBUG(0,("handle_trans2: encryption required "
7482 "with call 0x%x\n",
7483 (unsigned int)state->call));
7484 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7485 return;
7489 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7491 /* Now we must call the relevant TRANS2 function */
7492 switch(state->call) {
7493 case TRANSACT2_OPEN:
7495 START_PROFILE(Trans2_open);
7496 call_trans2open(conn, req,
7497 &state->param, state->total_param,
7498 &state->data, state->total_data,
7499 state->max_data_return);
7500 END_PROFILE(Trans2_open);
7501 break;
7504 case TRANSACT2_FINDFIRST:
7506 START_PROFILE(Trans2_findfirst);
7507 call_trans2findfirst(conn, req,
7508 &state->param, state->total_param,
7509 &state->data, state->total_data,
7510 state->max_data_return);
7511 END_PROFILE(Trans2_findfirst);
7512 break;
7515 case TRANSACT2_FINDNEXT:
7517 START_PROFILE(Trans2_findnext);
7518 call_trans2findnext(conn, req,
7519 &state->param, state->total_param,
7520 &state->data, state->total_data,
7521 state->max_data_return);
7522 END_PROFILE(Trans2_findnext);
7523 break;
7526 case TRANSACT2_QFSINFO:
7528 START_PROFILE(Trans2_qfsinfo);
7529 call_trans2qfsinfo(conn, req,
7530 &state->param, state->total_param,
7531 &state->data, state->total_data,
7532 state->max_data_return);
7533 END_PROFILE(Trans2_qfsinfo);
7534 break;
7537 case TRANSACT2_SETFSINFO:
7539 START_PROFILE(Trans2_setfsinfo);
7540 call_trans2setfsinfo(conn, req,
7541 &state->param, state->total_param,
7542 &state->data, state->total_data,
7543 state->max_data_return);
7544 END_PROFILE(Trans2_setfsinfo);
7545 break;
7548 case TRANSACT2_QPATHINFO:
7549 case TRANSACT2_QFILEINFO:
7551 START_PROFILE(Trans2_qpathinfo);
7552 call_trans2qfilepathinfo(conn, req, state->call,
7553 &state->param, state->total_param,
7554 &state->data, state->total_data,
7555 state->max_data_return);
7556 END_PROFILE(Trans2_qpathinfo);
7557 break;
7560 case TRANSACT2_SETPATHINFO:
7561 case TRANSACT2_SETFILEINFO:
7563 START_PROFILE(Trans2_setpathinfo);
7564 call_trans2setfilepathinfo(conn, req, state->call,
7565 &state->param, state->total_param,
7566 &state->data, state->total_data,
7567 state->max_data_return);
7568 END_PROFILE(Trans2_setpathinfo);
7569 break;
7572 case TRANSACT2_FINDNOTIFYFIRST:
7574 START_PROFILE(Trans2_findnotifyfirst);
7575 call_trans2findnotifyfirst(conn, req,
7576 &state->param, state->total_param,
7577 &state->data, state->total_data,
7578 state->max_data_return);
7579 END_PROFILE(Trans2_findnotifyfirst);
7580 break;
7583 case TRANSACT2_FINDNOTIFYNEXT:
7585 START_PROFILE(Trans2_findnotifynext);
7586 call_trans2findnotifynext(conn, req,
7587 &state->param, state->total_param,
7588 &state->data, state->total_data,
7589 state->max_data_return);
7590 END_PROFILE(Trans2_findnotifynext);
7591 break;
7594 case TRANSACT2_MKDIR:
7596 START_PROFILE(Trans2_mkdir);
7597 call_trans2mkdir(conn, req,
7598 &state->param, state->total_param,
7599 &state->data, state->total_data,
7600 state->max_data_return);
7601 END_PROFILE(Trans2_mkdir);
7602 break;
7605 case TRANSACT2_GET_DFS_REFERRAL:
7607 START_PROFILE(Trans2_get_dfs_referral);
7608 call_trans2getdfsreferral(conn, req,
7609 &state->param, state->total_param,
7610 &state->data, state->total_data,
7611 state->max_data_return);
7612 END_PROFILE(Trans2_get_dfs_referral);
7613 break;
7616 case TRANSACT2_IOCTL:
7618 START_PROFILE(Trans2_ioctl);
7619 call_trans2ioctl(conn, req,
7620 &state->param, state->total_param,
7621 &state->data, state->total_data,
7622 state->max_data_return);
7623 END_PROFILE(Trans2_ioctl);
7624 break;
7627 default:
7628 /* Error in request */
7629 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7630 reply_doserror(req, ERRSRV,ERRerror);
7634 /****************************************************************************
7635 Reply to a SMBtrans2.
7636 ****************************************************************************/
7638 void reply_trans2(struct smb_request *req)
7640 connection_struct *conn = req->conn;
7641 unsigned int dsoff;
7642 unsigned int dscnt;
7643 unsigned int psoff;
7644 unsigned int pscnt;
7645 unsigned int tran_call;
7646 struct trans_state *state;
7647 NTSTATUS result;
7649 START_PROFILE(SMBtrans2);
7651 if (req->wct < 14) {
7652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7653 END_PROFILE(SMBtrans2);
7654 return;
7657 dsoff = SVAL(req->vwv+12, 0);
7658 dscnt = SVAL(req->vwv+11, 0);
7659 psoff = SVAL(req->vwv+10, 0);
7660 pscnt = SVAL(req->vwv+9, 0);
7661 tran_call = SVAL(req->vwv+14, 0);
7663 result = allow_new_trans(conn->pending_trans, req->mid);
7664 if (!NT_STATUS_IS_OK(result)) {
7665 DEBUG(2, ("Got invalid trans2 request: %s\n",
7666 nt_errstr(result)));
7667 reply_nterror(req, result);
7668 END_PROFILE(SMBtrans2);
7669 return;
7672 if (IS_IPC(conn)) {
7673 switch (tran_call) {
7674 /* List the allowed trans2 calls on IPC$ */
7675 case TRANSACT2_OPEN:
7676 case TRANSACT2_GET_DFS_REFERRAL:
7677 case TRANSACT2_QFILEINFO:
7678 case TRANSACT2_QFSINFO:
7679 case TRANSACT2_SETFSINFO:
7680 break;
7681 default:
7682 reply_doserror(req, ERRSRV, ERRaccess);
7683 END_PROFILE(SMBtrans2);
7684 return;
7688 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7689 DEBUG(0, ("talloc failed\n"));
7690 reply_nterror(req, NT_STATUS_NO_MEMORY);
7691 END_PROFILE(SMBtrans2);
7692 return;
7695 state->cmd = SMBtrans2;
7697 state->mid = req->mid;
7698 state->vuid = req->vuid;
7699 state->setup_count = SVAL(req->vwv+13, 0);
7700 state->setup = NULL;
7701 state->total_param = SVAL(req->vwv+0, 0);
7702 state->param = NULL;
7703 state->total_data = SVAL(req->vwv+1, 0);
7704 state->data = NULL;
7705 state->max_param_return = SVAL(req->vwv+2, 0);
7706 state->max_data_return = SVAL(req->vwv+3, 0);
7707 state->max_setup_return = SVAL(req->vwv+4, 0);
7708 state->close_on_completion = BITSETW(req->vwv+5, 0);
7709 state->one_way = BITSETW(req->vwv+5, 1);
7711 state->call = tran_call;
7713 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7714 is so as a sanity check */
7715 if (state->setup_count != 1) {
7717 * Need to have rc=0 for ioctl to get job id for OS/2.
7718 * Network printing will fail if function is not successful.
7719 * Similar function in reply.c will be used if protocol
7720 * is LANMAN1.0 instead of LM1.2X002.
7721 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7722 * outbuf doesn't have to be set(only job id is used).
7724 if ( (state->setup_count == 4)
7725 && (tran_call == TRANSACT2_IOCTL)
7726 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7727 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7728 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7729 } else {
7730 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7731 DEBUG(2,("Transaction is %d\n",tran_call));
7732 TALLOC_FREE(state);
7733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7734 END_PROFILE(SMBtrans2);
7735 return;
7739 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7740 goto bad_param;
7742 if (state->total_data) {
7744 if (trans_oob(state->total_data, 0, dscnt)
7745 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7746 goto bad_param;
7749 /* Can't use talloc here, the core routines do realloc on the
7750 * params and data. */
7751 state->data = (char *)SMB_MALLOC(state->total_data);
7752 if (state->data == NULL) {
7753 DEBUG(0,("reply_trans2: data malloc fail for %u "
7754 "bytes !\n", (unsigned int)state->total_data));
7755 TALLOC_FREE(state);
7756 reply_nterror(req, NT_STATUS_NO_MEMORY);
7757 END_PROFILE(SMBtrans2);
7758 return;
7761 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7764 if (state->total_param) {
7766 if (trans_oob(state->total_param, 0, pscnt)
7767 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7768 goto bad_param;
7771 /* Can't use talloc here, the core routines do realloc on the
7772 * params and data. */
7773 state->param = (char *)SMB_MALLOC(state->total_param);
7774 if (state->param == NULL) {
7775 DEBUG(0,("reply_trans: param malloc fail for %u "
7776 "bytes !\n", (unsigned int)state->total_param));
7777 SAFE_FREE(state->data);
7778 TALLOC_FREE(state);
7779 reply_nterror(req, NT_STATUS_NO_MEMORY);
7780 END_PROFILE(SMBtrans2);
7781 return;
7784 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7787 state->received_data = dscnt;
7788 state->received_param = pscnt;
7790 if ((state->received_param == state->total_param) &&
7791 (state->received_data == state->total_data)) {
7793 handle_trans2(conn, req, state);
7795 SAFE_FREE(state->data);
7796 SAFE_FREE(state->param);
7797 TALLOC_FREE(state);
7798 END_PROFILE(SMBtrans2);
7799 return;
7802 DLIST_ADD(conn->pending_trans, state);
7804 /* We need to send an interim response then receive the rest
7805 of the parameter/data bytes */
7806 reply_outbuf(req, 0, 0);
7807 show_msg((char *)req->outbuf);
7808 END_PROFILE(SMBtrans2);
7809 return;
7811 bad_param:
7813 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7814 SAFE_FREE(state->data);
7815 SAFE_FREE(state->param);
7816 TALLOC_FREE(state);
7817 END_PROFILE(SMBtrans2);
7818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7822 /****************************************************************************
7823 Reply to a SMBtranss2
7824 ****************************************************************************/
7826 void reply_transs2(struct smb_request *req)
7828 connection_struct *conn = req->conn;
7829 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7830 struct trans_state *state;
7832 START_PROFILE(SMBtranss2);
7834 show_msg((char *)req->inbuf);
7836 if (req->wct < 8) {
7837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7838 END_PROFILE(SMBtranss2);
7839 return;
7842 for (state = conn->pending_trans; state != NULL;
7843 state = state->next) {
7844 if (state->mid == req->mid) {
7845 break;
7849 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7851 END_PROFILE(SMBtranss2);
7852 return;
7855 /* Revise state->total_param and state->total_data in case they have
7856 changed downwards */
7858 if (SVAL(req->vwv+0, 0) < state->total_param)
7859 state->total_param = SVAL(req->vwv+0, 0);
7860 if (SVAL(req->vwv+1, 0) < state->total_data)
7861 state->total_data = SVAL(req->vwv+1, 0);
7863 pcnt = SVAL(req->vwv+2, 0);
7864 poff = SVAL(req->vwv+3, 0);
7865 pdisp = SVAL(req->vwv+4, 0);
7867 dcnt = SVAL(req->vwv+5, 0);
7868 doff = SVAL(req->vwv+6, 0);
7869 ddisp = SVAL(req->vwv+7, 0);
7871 state->received_param += pcnt;
7872 state->received_data += dcnt;
7874 if ((state->received_data > state->total_data) ||
7875 (state->received_param > state->total_param))
7876 goto bad_param;
7878 if (pcnt) {
7879 if (trans_oob(state->total_param, pdisp, pcnt)
7880 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7881 goto bad_param;
7883 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7886 if (dcnt) {
7887 if (trans_oob(state->total_data, ddisp, dcnt)
7888 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7889 goto bad_param;
7891 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7894 if ((state->received_param < state->total_param) ||
7895 (state->received_data < state->total_data)) {
7896 END_PROFILE(SMBtranss2);
7897 return;
7900 handle_trans2(conn, req, state);
7902 DLIST_REMOVE(conn->pending_trans, state);
7903 SAFE_FREE(state->data);
7904 SAFE_FREE(state->param);
7905 TALLOC_FREE(state);
7907 END_PROFILE(SMBtranss2);
7908 return;
7910 bad_param:
7912 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7913 DLIST_REMOVE(conn->pending_trans, state);
7914 SAFE_FREE(state->data);
7915 SAFE_FREE(state->param);
7916 TALLOC_FREE(state);
7917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7918 END_PROFILE(SMBtranss2);
7919 return;