Ensure we never enter VFS_CREATE without having initialized
[Samba.git] / source3 / smbd / trans2.c
blob95051e429292c776cece1f88e45e6e4d62c3e6f4
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();
897 SET_STAT_INVALID(sbuf);
900 * Ensure we have enough parameters to perform the operation.
903 if (total_params < 29) {
904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
905 return;
908 flags = SVAL(params, 0);
909 deny_mode = SVAL(params, 2);
910 open_attr = SVAL(params,6);
911 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
912 if (oplock_request) {
913 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
916 #if 0
917 return_additional_info = BITSETW(params,0);
918 open_sattr = SVAL(params, 4);
919 open_time = make_unix_date3(params+8);
920 #endif
921 open_ofun = SVAL(params,12);
922 open_size = IVAL(params,14);
923 pname = &params[28];
925 if (IS_IPC(conn)) {
926 reply_doserror(req, ERRSRV, ERRaccess);
927 return;
930 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
931 total_params - 28, STR_TERMINATE,
932 &status);
933 if (!NT_STATUS_IS_OK(status)) {
934 reply_nterror(req, status);
935 return;
938 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
939 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
940 (unsigned int)open_ofun, open_size));
942 if (open_ofun == 0) {
943 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
944 return;
947 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
948 &access_mask,
949 &share_mode,
950 &create_disposition,
951 &create_options)) {
952 reply_doserror(req, ERRDOS, ERRbadaccess);
953 return;
956 /* Any data in this call is an EA list. */
957 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
958 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
959 return;
962 if (total_data != 4) {
963 if (total_data < 10) {
964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
965 return;
968 if (IVAL(pdata,0) > total_data) {
969 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
970 IVAL(pdata,0), (unsigned int)total_data));
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 return;
975 ea_list = read_ea_list(talloc_tos(), pdata + 4,
976 total_data - 4);
977 if (!ea_list) {
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 return;
981 } else if (IVAL(pdata,0) != 4) {
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 return;
986 status = SMB_VFS_CREATE_FILE(
987 conn, /* conn */
988 req, /* req */
989 0, /* root_dir_fid */
990 fname, /* fname */
991 CFF_DOS_PATH, /* create_file_flags */
992 access_mask, /* access_mask */
993 share_mode, /* share_access */
994 create_disposition, /* create_disposition*/
995 create_options, /* create_options */
996 open_attr, /* file_attributes */
997 oplock_request, /* oplock_request */
998 open_size, /* allocation_size */
999 NULL, /* sd */
1000 ea_list, /* ea_list */
1001 &fsp, /* result */
1002 &smb_action, /* pinfo */
1003 &sbuf); /* psbuf */
1005 if (!NT_STATUS_IS_OK(status)) {
1006 if (open_was_deferred(req->mid)) {
1007 /* We have re-scheduled this call. */
1008 return;
1010 reply_openerror(req, status);
1011 return;
1014 size = get_file_size_stat(&sbuf);
1015 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1016 mtime = sbuf.st_mtime;
1017 inode = sbuf.st_ino;
1018 if (fattr & aDIR) {
1019 close_file(req, fsp, ERROR_CLOSE);
1020 reply_doserror(req, ERRDOS,ERRnoaccess);
1021 return;
1024 /* Realloc the size of parameters and data we will return */
1025 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1026 if(*pparams == NULL ) {
1027 reply_nterror(req, NT_STATUS_NO_MEMORY);
1028 return;
1030 params = *pparams;
1032 SSVAL(params,0,fsp->fnum);
1033 SSVAL(params,2,fattr);
1034 srv_put_dos_date2(params,4, mtime);
1035 SIVAL(params,8, (uint32)size);
1036 SSVAL(params,12,deny_mode);
1037 SSVAL(params,14,0); /* open_type - file or directory. */
1038 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1040 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1041 smb_action |= EXTENDED_OPLOCK_GRANTED;
1044 SSVAL(params,18,smb_action);
1047 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1049 SIVAL(params,20,inode);
1050 SSVAL(params,24,0); /* Padding. */
1051 if (flags & 8) {
1052 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1053 SIVAL(params, 26, ea_size);
1054 } else {
1055 SIVAL(params, 26, 0);
1058 /* Send the required number of replies */
1059 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1062 /*********************************************************
1063 Routine to check if a given string matches exactly.
1064 as a special case a mask of "." does NOT match. That
1065 is required for correct wildcard semantics
1066 Case can be significant or not.
1067 **********************************************************/
1069 static bool exact_match(connection_struct *conn,
1070 const char *str,
1071 const char *mask)
1073 if (mask[0] == '.' && mask[1] == 0)
1074 return False;
1075 if (dptr_has_wild(conn->dirptr)) {
1076 return False;
1078 if (conn->case_sensitive)
1079 return strcmp(str,mask)==0;
1080 else
1081 return StrCaseCmp(str,mask) == 0;
1084 /****************************************************************************
1085 Return the filetype for UNIX extensions.
1086 ****************************************************************************/
1088 static uint32 unix_filetype(mode_t mode)
1090 if(S_ISREG(mode))
1091 return UNIX_TYPE_FILE;
1092 else if(S_ISDIR(mode))
1093 return UNIX_TYPE_DIR;
1094 #ifdef S_ISLNK
1095 else if(S_ISLNK(mode))
1096 return UNIX_TYPE_SYMLINK;
1097 #endif
1098 #ifdef S_ISCHR
1099 else if(S_ISCHR(mode))
1100 return UNIX_TYPE_CHARDEV;
1101 #endif
1102 #ifdef S_ISBLK
1103 else if(S_ISBLK(mode))
1104 return UNIX_TYPE_BLKDEV;
1105 #endif
1106 #ifdef S_ISFIFO
1107 else if(S_ISFIFO(mode))
1108 return UNIX_TYPE_FIFO;
1109 #endif
1110 #ifdef S_ISSOCK
1111 else if(S_ISSOCK(mode))
1112 return UNIX_TYPE_SOCKET;
1113 #endif
1115 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1116 return UNIX_TYPE_UNKNOWN;
1119 /****************************************************************************
1120 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1121 ****************************************************************************/
1123 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1125 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1126 SMB_STRUCT_STAT *psbuf,
1127 uint32 perms,
1128 enum perm_type ptype,
1129 mode_t *ret_perms)
1131 mode_t ret = 0;
1133 if (perms == SMB_MODE_NO_CHANGE) {
1134 if (!VALID_STAT(*psbuf)) {
1135 return NT_STATUS_INVALID_PARAMETER;
1136 } else {
1137 *ret_perms = psbuf->st_mode;
1138 return NT_STATUS_OK;
1142 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1143 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1144 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1145 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1146 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1147 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1148 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1149 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1150 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1151 #ifdef S_ISVTX
1152 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1153 #endif
1154 #ifdef S_ISGID
1155 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1156 #endif
1157 #ifdef S_ISUID
1158 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1159 #endif
1161 switch (ptype) {
1162 case PERM_NEW_FILE:
1163 /* Apply mode mask */
1164 ret &= lp_create_mask(SNUM(conn));
1165 /* Add in force bits */
1166 ret |= lp_force_create_mode(SNUM(conn));
1167 break;
1168 case PERM_NEW_DIR:
1169 ret &= lp_dir_mask(SNUM(conn));
1170 /* Add in force bits */
1171 ret |= lp_force_dir_mode(SNUM(conn));
1172 break;
1173 case PERM_EXISTING_FILE:
1174 /* Apply mode mask */
1175 ret &= lp_security_mask(SNUM(conn));
1176 /* Add in force bits */
1177 ret |= lp_force_security_mode(SNUM(conn));
1178 break;
1179 case PERM_EXISTING_DIR:
1180 /* Apply mode mask */
1181 ret &= lp_dir_security_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_dir_security_mode(SNUM(conn));
1184 break;
1187 *ret_perms = ret;
1188 return NT_STATUS_OK;
1191 /****************************************************************************
1192 Needed to show the msdfs symlinks as directories. Modifies psbuf
1193 to be a directory if it's a msdfs link.
1194 ****************************************************************************/
1196 static bool check_msdfs_link(connection_struct *conn,
1197 const char *pathname,
1198 SMB_STRUCT_STAT *psbuf)
1200 int saved_errno = errno;
1201 if(lp_host_msdfs() &&
1202 lp_msdfs_root(SNUM(conn)) &&
1203 is_msdfs_link(conn, pathname, psbuf)) {
1205 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1206 "as a directory\n",
1207 pathname));
1208 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1209 errno = saved_errno;
1210 return true;
1212 errno = saved_errno;
1213 return false;
1217 /****************************************************************************
1218 Get a level dependent lanman2 dir entry.
1219 ****************************************************************************/
1221 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1222 connection_struct *conn,
1223 uint16 flags2,
1224 const char *path_mask,
1225 uint32 dirtype,
1226 int info_level,
1227 int requires_resume_key,
1228 bool dont_descend,
1229 bool ask_sharemode,
1230 char **ppdata,
1231 char *base_data,
1232 char *end_data,
1233 int space_remaining,
1234 bool *out_of_space,
1235 bool *got_exact_match,
1236 int *last_entry_off,
1237 struct ea_list *name_list)
1239 const char *dname;
1240 bool found = False;
1241 SMB_STRUCT_STAT sbuf;
1242 const char *mask = NULL;
1243 char *pathreal = NULL;
1244 const char *fname = NULL;
1245 char *p, *q, *pdata = *ppdata;
1246 uint32 reskey=0;
1247 long prev_dirpos=0;
1248 uint32 mode=0;
1249 SMB_OFF_T file_size = 0;
1250 uint64_t allocation_size = 0;
1251 uint32 len;
1252 struct timespec mdate_ts, adate_ts, create_date_ts;
1253 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1254 char *nameptr;
1255 char *last_entry_ptr;
1256 bool was_8_3;
1257 uint32 nt_extmode; /* Used for NT connections instead of mode */
1258 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1259 bool check_mangled_names = lp_manglednames(conn->params);
1260 char mangled_name[13]; /* mangled 8.3 name. */
1262 *out_of_space = False;
1263 *got_exact_match = False;
1265 ZERO_STRUCT(mdate_ts);
1266 ZERO_STRUCT(adate_ts);
1267 ZERO_STRUCT(create_date_ts);
1269 if (!conn->dirptr) {
1270 return(False);
1273 p = strrchr_m(path_mask,'/');
1274 if(p != NULL) {
1275 if(p[1] == '\0') {
1276 mask = talloc_strdup(ctx,"*.*");
1277 } else {
1278 mask = p+1;
1280 } else {
1281 mask = path_mask;
1284 while (!found) {
1285 bool got_match;
1286 bool ms_dfs_link = False;
1288 /* Needed if we run out of space */
1289 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1290 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1293 * Due to bugs in NT client redirectors we are not using
1294 * resume keys any more - set them to zero.
1295 * Check out the related comments in findfirst/findnext.
1296 * JRA.
1299 reskey = 0;
1301 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1302 (long)conn->dirptr,curr_dirpos));
1304 if (!dname) {
1305 return(False);
1309 * fname may get mangled, dname is never mangled.
1310 * Whenever we're accessing the filesystem we use
1311 * pathreal which is composed from dname.
1314 pathreal = NULL;
1315 fname = dname;
1317 /* Mangle fname if it's an illegal name. */
1318 if (mangle_must_mangle(dname,conn->params)) {
1319 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1320 continue; /* Error - couldn't mangle. */
1322 fname = mangled_name;
1325 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1326 got_match = mask_match(fname, mask, conn->case_sensitive);
1329 if(!got_match && check_mangled_names &&
1330 !mangle_is_8_3(fname, False, conn->params)) {
1332 * It turns out that NT matches wildcards against
1333 * both long *and* short names. This may explain some
1334 * of the wildcard wierdness from old DOS clients
1335 * that some people have been seeing.... JRA.
1337 /* Force the mangling into 8.3. */
1338 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1339 continue; /* Error - couldn't mangle. */
1342 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1343 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1347 if (got_match) {
1348 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1350 if (dont_descend && !isdots) {
1351 continue;
1354 if (needslash) {
1355 pathreal = NULL;
1356 pathreal = talloc_asprintf(ctx,
1357 "%s/%s",
1358 conn->dirpath,
1359 dname);
1360 } else {
1361 pathreal = talloc_asprintf(ctx,
1362 "%s%s",
1363 conn->dirpath,
1364 dname);
1367 if (!pathreal) {
1368 return False;
1371 if (INFO_LEVEL_IS_UNIX(info_level)) {
1372 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1373 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1374 pathreal,strerror(errno)));
1375 TALLOC_FREE(pathreal);
1376 continue;
1378 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1379 /* Needed to show the msdfs symlinks as
1380 * directories */
1382 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1383 if (!ms_dfs_link) {
1384 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1385 pathreal,strerror(errno)));
1386 TALLOC_FREE(pathreal);
1387 continue;
1391 if (ms_dfs_link) {
1392 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1393 } else {
1394 mode = dos_mode(conn,pathreal,&sbuf);
1397 if (!dir_check_ftype(conn,mode,dirtype)) {
1398 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1399 TALLOC_FREE(pathreal);
1400 continue;
1403 if (!(mode & aDIR)) {
1404 file_size = get_file_size_stat(&sbuf);
1406 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1408 mdate_ts = get_mtimespec(&sbuf);
1409 adate_ts = get_atimespec(&sbuf);
1410 create_date_ts = get_create_timespec(&sbuf,
1411 lp_fake_dir_create_times(SNUM(conn)));
1413 if (ask_sharemode) {
1414 struct timespec write_time_ts;
1415 struct file_id fileid;
1417 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1418 get_file_infos(fileid, NULL, &write_time_ts);
1419 if (!null_timespec(write_time_ts)) {
1420 mdate_ts = write_time_ts;
1424 if (lp_dos_filetime_resolution(SNUM(conn))) {
1425 dos_filetime_timespec(&create_date_ts);
1426 dos_filetime_timespec(&mdate_ts);
1427 dos_filetime_timespec(&adate_ts);
1430 create_date = convert_timespec_to_time_t(create_date_ts);
1431 mdate = convert_timespec_to_time_t(mdate_ts);
1432 adate = convert_timespec_to_time_t(adate_ts);
1434 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1435 pathreal,fname));
1437 found = True;
1439 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1443 p = pdata;
1444 last_entry_ptr = p;
1446 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1448 switch (info_level) {
1449 case SMB_FIND_INFO_STANDARD:
1450 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1451 if(requires_resume_key) {
1452 SIVAL(p,0,reskey);
1453 p += 4;
1455 srv_put_dos_date2(p,0,create_date);
1456 srv_put_dos_date2(p,4,adate);
1457 srv_put_dos_date2(p,8,mdate);
1458 SIVAL(p,12,(uint32)file_size);
1459 SIVAL(p,16,(uint32)allocation_size);
1460 SSVAL(p,20,mode);
1461 p += 23;
1462 nameptr = p;
1463 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1464 p += ucs2_align(base_data, p, 0);
1466 len = srvstr_push(base_data, flags2, p,
1467 fname, PTR_DIFF(end_data, p),
1468 STR_TERMINATE);
1469 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1470 if (len > 2) {
1471 SCVAL(nameptr, -1, len - 2);
1472 } else {
1473 SCVAL(nameptr, -1, 0);
1475 } else {
1476 if (len > 1) {
1477 SCVAL(nameptr, -1, len - 1);
1478 } else {
1479 SCVAL(nameptr, -1, 0);
1482 p += len;
1483 break;
1485 case SMB_FIND_EA_SIZE:
1486 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1487 if(requires_resume_key) {
1488 SIVAL(p,0,reskey);
1489 p += 4;
1491 srv_put_dos_date2(p,0,create_date);
1492 srv_put_dos_date2(p,4,adate);
1493 srv_put_dos_date2(p,8,mdate);
1494 SIVAL(p,12,(uint32)file_size);
1495 SIVAL(p,16,(uint32)allocation_size);
1496 SSVAL(p,20,mode);
1498 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1499 SIVAL(p,22,ea_size); /* Extended attributes */
1501 p += 27;
1502 nameptr = p - 1;
1503 len = srvstr_push(base_data, flags2,
1504 p, fname, PTR_DIFF(end_data, p),
1505 STR_TERMINATE | STR_NOALIGN);
1506 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1507 if (len > 2) {
1508 len -= 2;
1509 } else {
1510 len = 0;
1512 } else {
1513 if (len > 1) {
1514 len -= 1;
1515 } else {
1516 len = 0;
1519 SCVAL(nameptr,0,len);
1520 p += len;
1521 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1522 break;
1524 case SMB_FIND_EA_LIST:
1526 struct ea_list *file_list = NULL;
1527 size_t ea_len = 0;
1529 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1530 if (!name_list) {
1531 return False;
1533 if(requires_resume_key) {
1534 SIVAL(p,0,reskey);
1535 p += 4;
1537 srv_put_dos_date2(p,0,create_date);
1538 srv_put_dos_date2(p,4,adate);
1539 srv_put_dos_date2(p,8,mdate);
1540 SIVAL(p,12,(uint32)file_size);
1541 SIVAL(p,16,(uint32)allocation_size);
1542 SSVAL(p,20,mode);
1543 p += 22; /* p now points to the EA area. */
1545 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1546 name_list = ea_list_union(name_list, file_list, &ea_len);
1548 /* We need to determine if this entry will fit in the space available. */
1549 /* Max string size is 255 bytes. */
1550 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1551 /* Move the dirptr back to prev_dirpos */
1552 dptr_SeekDir(conn->dirptr, prev_dirpos);
1553 *out_of_space = True;
1554 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1555 return False; /* Not finished - just out of space */
1558 /* Push the ea_data followed by the name. */
1559 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1560 nameptr = p;
1561 len = srvstr_push(base_data, flags2,
1562 p + 1, fname, PTR_DIFF(end_data, p+1),
1563 STR_TERMINATE | STR_NOALIGN);
1564 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1565 if (len > 2) {
1566 len -= 2;
1567 } else {
1568 len = 0;
1570 } else {
1571 if (len > 1) {
1572 len -= 1;
1573 } else {
1574 len = 0;
1577 SCVAL(nameptr,0,len);
1578 p += len + 1;
1579 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1580 break;
1583 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1584 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1585 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1586 p += 4;
1587 SIVAL(p,0,reskey); p += 4;
1588 put_long_date_timespec(p,create_date_ts); p += 8;
1589 put_long_date_timespec(p,adate_ts); p += 8;
1590 put_long_date_timespec(p,mdate_ts); p += 8;
1591 put_long_date_timespec(p,mdate_ts); p += 8;
1592 SOFF_T(p,0,file_size); p += 8;
1593 SOFF_T(p,0,allocation_size); p += 8;
1594 SIVAL(p,0,nt_extmode); p += 4;
1595 q = p; p += 4; /* q is placeholder for name length. */
1597 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1598 SIVAL(p,0,ea_size); /* Extended attributes */
1599 p += 4;
1601 /* Clear the short name buffer. This is
1602 * IMPORTANT as not doing so will trigger
1603 * a Win2k client bug. JRA.
1605 if (!was_8_3 && check_mangled_names) {
1606 if (!name_to_8_3(fname,mangled_name,True,
1607 conn->params)) {
1608 /* Error - mangle failed ! */
1609 memset(mangled_name,'\0',12);
1611 mangled_name[12] = 0;
1612 len = srvstr_push(base_data, flags2,
1613 p+2, mangled_name, 24,
1614 STR_UPPER|STR_UNICODE);
1615 if (len < 24) {
1616 memset(p + 2 + len,'\0',24 - len);
1618 SSVAL(p, 0, len);
1619 } else {
1620 memset(p,'\0',26);
1622 p += 2 + 24;
1623 len = srvstr_push(base_data, flags2, p,
1624 fname, PTR_DIFF(end_data, p),
1625 STR_TERMINATE_ASCII);
1626 SIVAL(q,0,len);
1627 p += len;
1628 SIVAL(p,0,0); /* Ensure any padding is null. */
1629 len = PTR_DIFF(p, pdata);
1630 len = (len + 3) & ~3;
1631 SIVAL(pdata,0,len);
1632 p = pdata + len;
1633 break;
1635 case SMB_FIND_FILE_DIRECTORY_INFO:
1636 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1637 p += 4;
1638 SIVAL(p,0,reskey); p += 4;
1639 put_long_date_timespec(p,create_date_ts); p += 8;
1640 put_long_date_timespec(p,adate_ts); p += 8;
1641 put_long_date_timespec(p,mdate_ts); p += 8;
1642 put_long_date_timespec(p,mdate_ts); p += 8;
1643 SOFF_T(p,0,file_size); p += 8;
1644 SOFF_T(p,0,allocation_size); p += 8;
1645 SIVAL(p,0,nt_extmode); p += 4;
1646 len = srvstr_push(base_data, flags2,
1647 p + 4, fname, PTR_DIFF(end_data, p+4),
1648 STR_TERMINATE_ASCII);
1649 SIVAL(p,0,len);
1650 p += 4 + len;
1651 SIVAL(p,0,0); /* Ensure any padding is null. */
1652 len = PTR_DIFF(p, pdata);
1653 len = (len + 3) & ~3;
1654 SIVAL(pdata,0,len);
1655 p = pdata + len;
1656 break;
1658 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1659 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1660 p += 4;
1661 SIVAL(p,0,reskey); p += 4;
1662 put_long_date_timespec(p,create_date_ts); p += 8;
1663 put_long_date_timespec(p,adate_ts); p += 8;
1664 put_long_date_timespec(p,mdate_ts); p += 8;
1665 put_long_date_timespec(p,mdate_ts); p += 8;
1666 SOFF_T(p,0,file_size); p += 8;
1667 SOFF_T(p,0,allocation_size); p += 8;
1668 SIVAL(p,0,nt_extmode); p += 4;
1669 q = p; p += 4; /* q is placeholder for name length. */
1671 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1672 SIVAL(p,0,ea_size); /* Extended attributes */
1673 p +=4;
1675 len = srvstr_push(base_data, flags2, p,
1676 fname, PTR_DIFF(end_data, p),
1677 STR_TERMINATE_ASCII);
1678 SIVAL(q, 0, len);
1679 p += len;
1681 SIVAL(p,0,0); /* Ensure any padding is null. */
1682 len = PTR_DIFF(p, pdata);
1683 len = (len + 3) & ~3;
1684 SIVAL(pdata,0,len);
1685 p = pdata + len;
1686 break;
1688 case SMB_FIND_FILE_NAMES_INFO:
1689 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1690 p += 4;
1691 SIVAL(p,0,reskey); p += 4;
1692 p += 4;
1693 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1694 acl on a dir (tridge) */
1695 len = srvstr_push(base_data, flags2, p,
1696 fname, PTR_DIFF(end_data, p),
1697 STR_TERMINATE_ASCII);
1698 SIVAL(p, -4, len);
1699 p += len;
1700 SIVAL(p,0,0); /* Ensure any padding is null. */
1701 len = PTR_DIFF(p, pdata);
1702 len = (len + 3) & ~3;
1703 SIVAL(pdata,0,len);
1704 p = pdata + len;
1705 break;
1707 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1708 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1709 p += 4;
1710 SIVAL(p,0,reskey); p += 4;
1711 put_long_date_timespec(p,create_date_ts); p += 8;
1712 put_long_date_timespec(p,adate_ts); p += 8;
1713 put_long_date_timespec(p,mdate_ts); p += 8;
1714 put_long_date_timespec(p,mdate_ts); p += 8;
1715 SOFF_T(p,0,file_size); p += 8;
1716 SOFF_T(p,0,allocation_size); p += 8;
1717 SIVAL(p,0,nt_extmode); p += 4;
1718 q = p; p += 4; /* q is placeholder for name length. */
1720 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1721 SIVAL(p,0,ea_size); /* Extended attributes */
1722 p +=4;
1724 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1725 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1726 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1727 len = srvstr_push(base_data, flags2, p,
1728 fname, PTR_DIFF(end_data, p),
1729 STR_TERMINATE_ASCII);
1730 SIVAL(q, 0, len);
1731 p += len;
1732 SIVAL(p,0,0); /* Ensure any padding is null. */
1733 len = PTR_DIFF(p, pdata);
1734 len = (len + 3) & ~3;
1735 SIVAL(pdata,0,len);
1736 p = pdata + len;
1737 break;
1739 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1740 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1741 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1742 p += 4;
1743 SIVAL(p,0,reskey); p += 4;
1744 put_long_date_timespec(p,create_date_ts); p += 8;
1745 put_long_date_timespec(p,adate_ts); p += 8;
1746 put_long_date_timespec(p,mdate_ts); p += 8;
1747 put_long_date_timespec(p,mdate_ts); p += 8;
1748 SOFF_T(p,0,file_size); p += 8;
1749 SOFF_T(p,0,allocation_size); p += 8;
1750 SIVAL(p,0,nt_extmode); p += 4;
1751 q = p; p += 4; /* q is placeholder for name length */
1753 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1754 SIVAL(p,0,ea_size); /* Extended attributes */
1755 p +=4;
1757 /* Clear the short name buffer. This is
1758 * IMPORTANT as not doing so will trigger
1759 * a Win2k client bug. JRA.
1761 if (!was_8_3 && check_mangled_names) {
1762 if (!name_to_8_3(fname,mangled_name,True,
1763 conn->params)) {
1764 /* Error - mangle failed ! */
1765 memset(mangled_name,'\0',12);
1767 mangled_name[12] = 0;
1768 len = srvstr_push(base_data, flags2,
1769 p+2, mangled_name, 24,
1770 STR_UPPER|STR_UNICODE);
1771 SSVAL(p, 0, len);
1772 if (len < 24) {
1773 memset(p + 2 + len,'\0',24 - len);
1775 SSVAL(p, 0, len);
1776 } else {
1777 memset(p,'\0',26);
1779 p += 26;
1780 SSVAL(p,0,0); p += 2; /* Reserved ? */
1781 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1782 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1783 len = srvstr_push(base_data, flags2, p,
1784 fname, PTR_DIFF(end_data, p),
1785 STR_TERMINATE_ASCII);
1786 SIVAL(q,0,len);
1787 p += len;
1788 SIVAL(p,0,0); /* Ensure any padding is null. */
1789 len = PTR_DIFF(p, pdata);
1790 len = (len + 3) & ~3;
1791 SIVAL(pdata,0,len);
1792 p = pdata + len;
1793 break;
1795 /* CIFS UNIX Extension. */
1797 case SMB_FIND_FILE_UNIX:
1798 case SMB_FIND_FILE_UNIX_INFO2:
1799 p+= 4;
1800 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1802 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1804 if (info_level == SMB_FIND_FILE_UNIX) {
1805 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1806 p = store_file_unix_basic(conn, p,
1807 NULL, &sbuf);
1808 len = srvstr_push(base_data, flags2, p,
1809 fname, PTR_DIFF(end_data, p),
1810 STR_TERMINATE);
1811 } else {
1812 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1813 p = store_file_unix_basic_info2(conn, p,
1814 NULL, &sbuf);
1815 nameptr = p;
1816 p += 4;
1817 len = srvstr_push(base_data, flags2, p, fname,
1818 PTR_DIFF(end_data, p), 0);
1819 SIVAL(nameptr, 0, len);
1822 p += len;
1823 SIVAL(p,0,0); /* Ensure any padding is null. */
1825 len = PTR_DIFF(p, pdata);
1826 len = (len + 3) & ~3;
1827 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1828 p = pdata + len;
1829 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1831 break;
1833 default:
1834 return(False);
1838 if (PTR_DIFF(p,pdata) > space_remaining) {
1839 /* Move the dirptr back to prev_dirpos */
1840 dptr_SeekDir(conn->dirptr, prev_dirpos);
1841 *out_of_space = True;
1842 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1843 return False; /* Not finished - just out of space */
1846 /* Setup the last entry pointer, as an offset from base_data */
1847 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1848 /* Advance the data pointer to the next slot */
1849 *ppdata = p;
1851 return(found);
1854 /****************************************************************************
1855 Reply to a TRANS2_FINDFIRST.
1856 ****************************************************************************/
1858 static void call_trans2findfirst(connection_struct *conn,
1859 struct smb_request *req,
1860 char **pparams, int total_params,
1861 char **ppdata, int total_data,
1862 unsigned int max_data_bytes)
1864 /* We must be careful here that we don't return more than the
1865 allowed number of data bytes. If this means returning fewer than
1866 maxentries then so be it. We assume that the redirector has
1867 enough room for the fixed number of parameter bytes it has
1868 requested. */
1869 char *params = *pparams;
1870 char *pdata = *ppdata;
1871 char *data_end;
1872 uint32 dirtype;
1873 int maxentries;
1874 uint16 findfirst_flags;
1875 bool close_after_first;
1876 bool close_if_end;
1877 bool requires_resume_key;
1878 int info_level;
1879 char *directory = NULL;
1880 char *mask = NULL;
1881 char *p;
1882 int last_entry_off=0;
1883 int dptr_num = -1;
1884 int numentries = 0;
1885 int i;
1886 bool finished = False;
1887 bool dont_descend = False;
1888 bool out_of_space = False;
1889 int space_remaining;
1890 bool mask_contains_wcard = False;
1891 SMB_STRUCT_STAT sbuf;
1892 struct ea_list *ea_list = NULL;
1893 NTSTATUS ntstatus = NT_STATUS_OK;
1894 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1895 TALLOC_CTX *ctx = talloc_tos();
1897 if (total_params < 13) {
1898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1899 return;
1902 dirtype = SVAL(params,0);
1903 maxentries = SVAL(params,2);
1904 findfirst_flags = SVAL(params,4);
1905 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1906 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1907 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1908 info_level = SVAL(params,6);
1910 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1911 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1912 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1913 info_level, max_data_bytes));
1915 if (!maxentries) {
1916 /* W2K3 seems to treat zero as 1. */
1917 maxentries = 1;
1920 switch (info_level) {
1921 case SMB_FIND_INFO_STANDARD:
1922 case SMB_FIND_EA_SIZE:
1923 case SMB_FIND_EA_LIST:
1924 case SMB_FIND_FILE_DIRECTORY_INFO:
1925 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1926 case SMB_FIND_FILE_NAMES_INFO:
1927 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1929 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1930 break;
1931 case SMB_FIND_FILE_UNIX:
1932 case SMB_FIND_FILE_UNIX_INFO2:
1933 /* Always use filesystem for UNIX mtime query. */
1934 ask_sharemode = false;
1935 if (!lp_unix_extensions()) {
1936 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1937 return;
1939 break;
1940 default:
1941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1942 return;
1945 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1946 params+12, total_params - 12,
1947 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1948 if (!NT_STATUS_IS_OK(ntstatus)) {
1949 reply_nterror(req, ntstatus);
1950 return;
1953 ntstatus = resolve_dfspath_wcard(ctx, conn,
1954 req->flags2 & FLAGS2_DFS_PATHNAMES,
1955 directory,
1956 &directory,
1957 &mask_contains_wcard);
1958 if (!NT_STATUS_IS_OK(ntstatus)) {
1959 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1960 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1961 ERRSRV, ERRbadpath);
1962 return;
1964 reply_nterror(req, ntstatus);
1965 return;
1968 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 reply_nterror(req, ntstatus);
1971 return;
1974 ntstatus = check_name(conn, directory);
1975 if (!NT_STATUS_IS_OK(ntstatus)) {
1976 reply_nterror(req, ntstatus);
1977 return;
1980 p = strrchr_m(directory,'/');
1981 if(p == NULL) {
1982 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1983 if((directory[0] == '.') && (directory[1] == '\0')) {
1984 mask = talloc_strdup(ctx,"*");
1985 if (!mask) {
1986 reply_nterror(req, NT_STATUS_NO_MEMORY);
1987 return;
1989 mask_contains_wcard = True;
1991 directory = talloc_strdup(talloc_tos(), "./");
1992 if (!directory) {
1993 reply_nterror(req, NT_STATUS_NO_MEMORY);
1994 return;
1996 } else {
1997 *p = 0;
2000 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2002 if (info_level == SMB_FIND_EA_LIST) {
2003 uint32 ea_size;
2005 if (total_data < 4) {
2006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2007 return;
2010 ea_size = IVAL(pdata,0);
2011 if (ea_size != total_data) {
2012 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2013 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2015 return;
2018 if (!lp_ea_support(SNUM(conn))) {
2019 reply_doserror(req, ERRDOS, ERReasnotsupported);
2020 return;
2023 /* Pull out the list of names. */
2024 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2025 if (!ea_list) {
2026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2027 return;
2031 *ppdata = (char *)SMB_REALLOC(
2032 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2033 if(*ppdata == NULL ) {
2034 reply_nterror(req, NT_STATUS_NO_MEMORY);
2035 return;
2037 pdata = *ppdata;
2038 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2040 /* Realloc the params space */
2041 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2042 if (*pparams == NULL) {
2043 reply_nterror(req, NT_STATUS_NO_MEMORY);
2044 return;
2046 params = *pparams;
2048 /* Save the wildcard match and attribs we are using on this directory -
2049 needed as lanman2 assumes these are being saved between calls */
2051 ntstatus = dptr_create(conn,
2052 directory,
2053 False,
2054 True,
2055 req->smbpid,
2056 mask,
2057 mask_contains_wcard,
2058 dirtype,
2059 &conn->dirptr);
2061 if (!NT_STATUS_IS_OK(ntstatus)) {
2062 reply_nterror(req, ntstatus);
2063 return;
2066 dptr_num = dptr_dnum(conn->dirptr);
2067 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2069 /* Initialize per TRANS2_FIND_FIRST operation data */
2070 dptr_init_search_op(conn->dirptr);
2072 /* We don't need to check for VOL here as this is returned by
2073 a different TRANS2 call. */
2075 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2076 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2077 dont_descend = True;
2079 p = pdata;
2080 space_remaining = max_data_bytes;
2081 out_of_space = False;
2083 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2084 bool got_exact_match = False;
2086 /* this is a heuristic to avoid seeking the dirptr except when
2087 absolutely necessary. It allows for a filename of about 40 chars */
2088 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2089 out_of_space = True;
2090 finished = False;
2091 } else {
2092 finished = !get_lanman2_dir_entry(ctx,
2093 conn,
2094 req->flags2,
2095 mask,dirtype,info_level,
2096 requires_resume_key,dont_descend,
2097 ask_sharemode,
2098 &p,pdata,data_end,
2099 space_remaining, &out_of_space,
2100 &got_exact_match,
2101 &last_entry_off, ea_list);
2104 if (finished && out_of_space)
2105 finished = False;
2107 if (!finished && !out_of_space)
2108 numentries++;
2111 * As an optimisation if we know we aren't looking
2112 * for a wildcard name (ie. the name matches the wildcard exactly)
2113 * then we can finish on any (first) match.
2114 * This speeds up large directory searches. JRA.
2117 if(got_exact_match)
2118 finished = True;
2120 /* Ensure space_remaining never goes -ve. */
2121 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2122 space_remaining = 0;
2123 out_of_space = true;
2124 } else {
2125 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2129 /* Check if we can close the dirptr */
2130 if(close_after_first || (finished && close_if_end)) {
2131 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2132 dptr_close(&dptr_num);
2136 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2137 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2138 * the protocol level is less than NT1. Tested with smbclient. JRA.
2139 * This should fix the OS/2 client bug #2335.
2142 if(numentries == 0) {
2143 dptr_close(&dptr_num);
2144 if (Protocol < PROTOCOL_NT1) {
2145 reply_doserror(req, ERRDOS, ERRnofiles);
2146 return;
2147 } else {
2148 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2149 ERRDOS, ERRbadfile);
2150 return;
2154 /* At this point pdata points to numentries directory entries. */
2156 /* Set up the return parameter block */
2157 SSVAL(params,0,dptr_num);
2158 SSVAL(params,2,numentries);
2159 SSVAL(params,4,finished);
2160 SSVAL(params,6,0); /* Never an EA error */
2161 SSVAL(params,8,last_entry_off);
2163 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2164 max_data_bytes);
2166 if ((! *directory) && dptr_path(dptr_num)) {
2167 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2168 if (!directory) {
2169 reply_nterror(req, NT_STATUS_NO_MEMORY);
2173 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2174 smb_fn_name(req->cmd),
2175 mask, directory, dirtype, numentries ) );
2178 * Force a name mangle here to ensure that the
2179 * mask as an 8.3 name is top of the mangled cache.
2180 * The reasons for this are subtle. Don't remove
2181 * this code unless you know what you are doing
2182 * (see PR#13758). JRA.
2185 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2186 char mangled_name[13];
2187 name_to_8_3(mask, mangled_name, True, conn->params);
2190 return;
2193 /****************************************************************************
2194 Reply to a TRANS2_FINDNEXT.
2195 ****************************************************************************/
2197 static void call_trans2findnext(connection_struct *conn,
2198 struct smb_request *req,
2199 char **pparams, int total_params,
2200 char **ppdata, int total_data,
2201 unsigned int max_data_bytes)
2203 /* We must be careful here that we don't return more than the
2204 allowed number of data bytes. If this means returning fewer than
2205 maxentries then so be it. We assume that the redirector has
2206 enough room for the fixed number of parameter bytes it has
2207 requested. */
2208 char *params = *pparams;
2209 char *pdata = *ppdata;
2210 char *data_end;
2211 int dptr_num;
2212 int maxentries;
2213 uint16 info_level;
2214 uint32 resume_key;
2215 uint16 findnext_flags;
2216 bool close_after_request;
2217 bool close_if_end;
2218 bool requires_resume_key;
2219 bool continue_bit;
2220 bool mask_contains_wcard = False;
2221 char *resume_name = NULL;
2222 const char *mask = NULL;
2223 const char *directory = NULL;
2224 char *p = NULL;
2225 uint16 dirtype;
2226 int numentries = 0;
2227 int i, last_entry_off=0;
2228 bool finished = False;
2229 bool dont_descend = False;
2230 bool out_of_space = False;
2231 int space_remaining;
2232 struct ea_list *ea_list = NULL;
2233 NTSTATUS ntstatus = NT_STATUS_OK;
2234 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2235 TALLOC_CTX *ctx = talloc_tos();
2237 if (total_params < 13) {
2238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2239 return;
2242 dptr_num = SVAL(params,0);
2243 maxentries = SVAL(params,2);
2244 info_level = SVAL(params,4);
2245 resume_key = IVAL(params,6);
2246 findnext_flags = SVAL(params,10);
2247 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2248 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2249 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2250 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2252 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2253 params+12,
2254 total_params - 12, STR_TERMINATE, &ntstatus,
2255 &mask_contains_wcard);
2256 if (!NT_STATUS_IS_OK(ntstatus)) {
2257 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2258 complain (it thinks we're asking for the directory above the shared
2259 path or an invalid name). Catch this as the resume name is only compared, never used in
2260 a file access. JRA. */
2261 srvstr_pull_talloc(ctx, params, req->flags2,
2262 &resume_name, params+12,
2263 total_params - 12,
2264 STR_TERMINATE);
2266 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2267 reply_nterror(req, ntstatus);
2268 return;
2272 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2273 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2274 resume_key = %d resume name = %s continue=%d level = %d\n",
2275 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2276 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2278 if (!maxentries) {
2279 /* W2K3 seems to treat zero as 1. */
2280 maxentries = 1;
2283 switch (info_level) {
2284 case SMB_FIND_INFO_STANDARD:
2285 case SMB_FIND_EA_SIZE:
2286 case SMB_FIND_EA_LIST:
2287 case SMB_FIND_FILE_DIRECTORY_INFO:
2288 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2289 case SMB_FIND_FILE_NAMES_INFO:
2290 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2291 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2292 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2293 break;
2294 case SMB_FIND_FILE_UNIX:
2295 case SMB_FIND_FILE_UNIX_INFO2:
2296 /* Always use filesystem for UNIX mtime query. */
2297 ask_sharemode = false;
2298 if (!lp_unix_extensions()) {
2299 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2300 return;
2302 break;
2303 default:
2304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2305 return;
2308 if (info_level == SMB_FIND_EA_LIST) {
2309 uint32 ea_size;
2311 if (total_data < 4) {
2312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2313 return;
2316 ea_size = IVAL(pdata,0);
2317 if (ea_size != total_data) {
2318 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2319 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2321 return;
2324 if (!lp_ea_support(SNUM(conn))) {
2325 reply_doserror(req, ERRDOS, ERReasnotsupported);
2326 return;
2329 /* Pull out the list of names. */
2330 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2331 if (!ea_list) {
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 return;
2337 *ppdata = (char *)SMB_REALLOC(
2338 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2339 if(*ppdata == NULL) {
2340 reply_nterror(req, NT_STATUS_NO_MEMORY);
2341 return;
2344 pdata = *ppdata;
2345 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2347 /* Realloc the params space */
2348 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2349 if(*pparams == NULL ) {
2350 reply_nterror(req, NT_STATUS_NO_MEMORY);
2351 return;
2354 params = *pparams;
2356 /* Check that the dptr is valid */
2357 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2358 reply_doserror(req, ERRDOS, ERRnofiles);
2359 return;
2362 string_set(&conn->dirpath,dptr_path(dptr_num));
2364 /* Get the wildcard mask from the dptr */
2365 if((p = dptr_wcard(dptr_num))== NULL) {
2366 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2367 reply_doserror(req, ERRDOS, ERRnofiles);
2368 return;
2371 mask = p;
2372 directory = conn->dirpath;
2374 /* Get the attr mask from the dptr */
2375 dirtype = dptr_attr(dptr_num);
2377 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2378 dptr_num, mask, dirtype,
2379 (long)conn->dirptr,
2380 dptr_TellDir(conn->dirptr)));
2382 /* Initialize per TRANS2_FIND_NEXT operation data */
2383 dptr_init_search_op(conn->dirptr);
2385 /* We don't need to check for VOL here as this is returned by
2386 a different TRANS2 call. */
2388 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2389 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2390 dont_descend = True;
2392 p = pdata;
2393 space_remaining = max_data_bytes;
2394 out_of_space = False;
2397 * Seek to the correct position. We no longer use the resume key but
2398 * depend on the last file name instead.
2401 if(*resume_name && !continue_bit) {
2402 SMB_STRUCT_STAT st;
2404 long current_pos = 0;
2406 * Remember, name_to_8_3 is called by
2407 * get_lanman2_dir_entry(), so the resume name
2408 * could be mangled. Ensure we check the unmangled name.
2411 if (mangle_is_mangled(resume_name, conn->params)) {
2412 char *new_resume_name = NULL;
2413 mangle_lookup_name_from_8_3(ctx,
2414 resume_name,
2415 &new_resume_name,
2416 conn->params);
2417 if (new_resume_name) {
2418 resume_name = new_resume_name;
2423 * Fix for NT redirector problem triggered by resume key indexes
2424 * changing between directory scans. We now return a resume key of 0
2425 * and instead look for the filename to continue from (also given
2426 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2427 * findfirst/findnext (as is usual) then the directory pointer
2428 * should already be at the correct place.
2431 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2432 } /* end if resume_name && !continue_bit */
2434 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2435 bool got_exact_match = False;
2437 /* this is a heuristic to avoid seeking the dirptr except when
2438 absolutely necessary. It allows for a filename of about 40 chars */
2439 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2440 out_of_space = True;
2441 finished = False;
2442 } else {
2443 finished = !get_lanman2_dir_entry(ctx,
2444 conn,
2445 req->flags2,
2446 mask,dirtype,info_level,
2447 requires_resume_key,dont_descend,
2448 ask_sharemode,
2449 &p,pdata,data_end,
2450 space_remaining, &out_of_space,
2451 &got_exact_match,
2452 &last_entry_off, ea_list);
2455 if (finished && out_of_space)
2456 finished = False;
2458 if (!finished && !out_of_space)
2459 numentries++;
2462 * As an optimisation if we know we aren't looking
2463 * for a wildcard name (ie. the name matches the wildcard exactly)
2464 * then we can finish on any (first) match.
2465 * This speeds up large directory searches. JRA.
2468 if(got_exact_match)
2469 finished = True;
2471 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2474 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2475 smb_fn_name(req->cmd),
2476 mask, directory, dirtype, numentries ) );
2478 /* Check if we can close the dirptr */
2479 if(close_after_request || (finished && close_if_end)) {
2480 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2481 dptr_close(&dptr_num); /* This frees up the saved mask */
2484 /* Set up the return parameter block */
2485 SSVAL(params,0,numentries);
2486 SSVAL(params,2,finished);
2487 SSVAL(params,4,0); /* Never an EA error */
2488 SSVAL(params,6,last_entry_off);
2490 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2491 max_data_bytes);
2493 return;
2496 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2498 E_md4hash(lp_servicename(SNUM(conn)),objid);
2499 return objid;
2502 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2504 SMB_ASSERT(extended_info != NULL);
2506 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2507 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2508 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2509 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2510 #ifdef SAMBA_VERSION_REVISION
2511 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2512 #endif
2513 extended_info->samba_subversion = 0;
2514 #ifdef SAMBA_VERSION_RC_RELEASE
2515 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2516 #else
2517 #ifdef SAMBA_VERSION_PRE_RELEASE
2518 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2519 #endif
2520 #endif
2521 #ifdef SAMBA_VERSION_VENDOR_PATCH
2522 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2523 #endif
2524 extended_info->samba_gitcommitdate = 0;
2525 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2526 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2527 #endif
2529 memset(extended_info->samba_version_string, 0,
2530 sizeof(extended_info->samba_version_string));
2532 snprintf (extended_info->samba_version_string,
2533 sizeof(extended_info->samba_version_string),
2534 "%s", samba_version_string());
2537 /****************************************************************************
2538 Reply to a TRANS2_QFSINFO (query filesystem info).
2539 ****************************************************************************/
2541 static void call_trans2qfsinfo(connection_struct *conn,
2542 struct smb_request *req,
2543 char **pparams, int total_params,
2544 char **ppdata, int total_data,
2545 unsigned int max_data_bytes)
2547 char *pdata, *end_data;
2548 char *params = *pparams;
2549 uint16 info_level;
2550 int data_len, len;
2551 SMB_STRUCT_STAT st;
2552 const char *vname = volume_label(SNUM(conn));
2553 int snum = SNUM(conn);
2554 char *fstype = lp_fstype(SNUM(conn));
2555 uint32 additional_flags = 0;
2557 if (total_params < 2) {
2558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2559 return;
2562 info_level = SVAL(params,0);
2564 if (IS_IPC(conn)) {
2565 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2566 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2567 "info level (0x%x) on IPC$.\n",
2568 (unsigned int)info_level));
2569 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2570 return;
2574 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2575 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2576 DEBUG(0,("call_trans2qfsinfo: encryption required "
2577 "and info level 0x%x sent.\n",
2578 (unsigned int)info_level));
2579 exit_server_cleanly("encryption required "
2580 "on connection");
2581 return;
2585 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2587 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2588 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2589 reply_doserror(req, ERRSRV, ERRinvdevice);
2590 return;
2593 *ppdata = (char *)SMB_REALLOC(
2594 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2595 if (*ppdata == NULL ) {
2596 reply_nterror(req, NT_STATUS_NO_MEMORY);
2597 return;
2600 pdata = *ppdata;
2601 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2602 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2604 switch (info_level) {
2605 case SMB_INFO_ALLOCATION:
2607 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2608 data_len = 18;
2609 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2610 reply_unixerror(req, ERRHRD, ERRgeneral);
2611 return;
2614 block_size = lp_block_size(snum);
2615 if (bsize < block_size) {
2616 uint64_t factor = block_size/bsize;
2617 bsize = block_size;
2618 dsize /= factor;
2619 dfree /= factor;
2621 if (bsize > block_size) {
2622 uint64_t factor = bsize/block_size;
2623 bsize = block_size;
2624 dsize *= factor;
2625 dfree *= factor;
2627 bytes_per_sector = 512;
2628 sectors_per_unit = bsize/bytes_per_sector;
2630 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2631 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2632 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2634 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2635 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2636 SIVAL(pdata,l1_cUnit,dsize);
2637 SIVAL(pdata,l1_cUnitAvail,dfree);
2638 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2639 break;
2642 case SMB_INFO_VOLUME:
2643 /* Return volume name */
2645 * Add volume serial number - hash of a combination of
2646 * the called hostname and the service name.
2648 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2650 * Win2k3 and previous mess this up by sending a name length
2651 * one byte short. I believe only older clients (OS/2 Win9x) use
2652 * this call so try fixing this by adding a terminating null to
2653 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2655 len = srvstr_push(
2656 pdata, req->flags2,
2657 pdata+l2_vol_szVolLabel, vname,
2658 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2659 STR_NOALIGN|STR_TERMINATE);
2660 SCVAL(pdata,l2_vol_cch,len);
2661 data_len = l2_vol_szVolLabel + len;
2662 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2663 (unsigned)st.st_ctime, len, vname));
2664 break;
2666 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2667 case SMB_FS_ATTRIBUTE_INFORMATION:
2669 additional_flags = 0;
2670 #if defined(HAVE_SYS_QUOTAS)
2671 additional_flags |= FILE_VOLUME_QUOTAS;
2672 #endif
2674 if(lp_nt_acl_support(SNUM(conn))) {
2675 additional_flags |= FILE_PERSISTENT_ACLS;
2678 /* Capabilities are filled in at connection time through STATVFS call */
2679 additional_flags |= conn->fs_capabilities;
2681 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2682 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2683 additional_flags); /* FS ATTRIBUTES */
2685 SIVAL(pdata,4,255); /* Max filename component length */
2686 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2687 and will think we can't do long filenames */
2688 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2689 PTR_DIFF(end_data, pdata+12),
2690 STR_UNICODE);
2691 SIVAL(pdata,8,len);
2692 data_len = 12 + len;
2693 break;
2695 case SMB_QUERY_FS_LABEL_INFO:
2696 case SMB_FS_LABEL_INFORMATION:
2697 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2698 PTR_DIFF(end_data, pdata+4), 0);
2699 data_len = 4 + len;
2700 SIVAL(pdata,0,len);
2701 break;
2703 case SMB_QUERY_FS_VOLUME_INFO:
2704 case SMB_FS_VOLUME_INFORMATION:
2707 * Add volume serial number - hash of a combination of
2708 * the called hostname and the service name.
2710 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2711 (str_checksum(get_local_machine_name())<<16));
2713 /* Max label len is 32 characters. */
2714 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2715 PTR_DIFF(end_data, pdata+18),
2716 STR_UNICODE);
2717 SIVAL(pdata,12,len);
2718 data_len = 18+len;
2720 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2721 (int)strlen(vname),vname, lp_servicename(snum)));
2722 break;
2724 case SMB_QUERY_FS_SIZE_INFO:
2725 case SMB_FS_SIZE_INFORMATION:
2727 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2728 data_len = 24;
2729 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2730 reply_unixerror(req, ERRHRD, ERRgeneral);
2731 return;
2733 block_size = lp_block_size(snum);
2734 if (bsize < block_size) {
2735 uint64_t factor = block_size/bsize;
2736 bsize = block_size;
2737 dsize /= factor;
2738 dfree /= factor;
2740 if (bsize > block_size) {
2741 uint64_t factor = bsize/block_size;
2742 bsize = block_size;
2743 dsize *= factor;
2744 dfree *= factor;
2746 bytes_per_sector = 512;
2747 sectors_per_unit = bsize/bytes_per_sector;
2748 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2749 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2750 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2751 SBIG_UINT(pdata,0,dsize);
2752 SBIG_UINT(pdata,8,dfree);
2753 SIVAL(pdata,16,sectors_per_unit);
2754 SIVAL(pdata,20,bytes_per_sector);
2755 break;
2758 case SMB_FS_FULL_SIZE_INFORMATION:
2760 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2761 data_len = 32;
2762 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2763 reply_unixerror(req, ERRHRD, ERRgeneral);
2764 return;
2766 block_size = lp_block_size(snum);
2767 if (bsize < block_size) {
2768 uint64_t factor = block_size/bsize;
2769 bsize = block_size;
2770 dsize /= factor;
2771 dfree /= factor;
2773 if (bsize > block_size) {
2774 uint64_t factor = bsize/block_size;
2775 bsize = block_size;
2776 dsize *= factor;
2777 dfree *= factor;
2779 bytes_per_sector = 512;
2780 sectors_per_unit = bsize/bytes_per_sector;
2781 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2782 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2783 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2784 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2785 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2786 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2787 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2788 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2789 break;
2792 case SMB_QUERY_FS_DEVICE_INFO:
2793 case SMB_FS_DEVICE_INFORMATION:
2794 data_len = 8;
2795 SIVAL(pdata,0,0); /* dev type */
2796 SIVAL(pdata,4,0); /* characteristics */
2797 break;
2799 #ifdef HAVE_SYS_QUOTAS
2800 case SMB_FS_QUOTA_INFORMATION:
2802 * what we have to send --metze:
2804 * Unknown1: 24 NULL bytes
2805 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2806 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2807 * Quota Flags: 2 byte :
2808 * Unknown3: 6 NULL bytes
2810 * 48 bytes total
2812 * details for Quota Flags:
2814 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2815 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2816 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2817 * 0x0001 Enable Quotas: enable quota for this fs
2821 /* we need to fake up a fsp here,
2822 * because its not send in this call
2824 files_struct fsp;
2825 SMB_NTQUOTA_STRUCT quotas;
2827 ZERO_STRUCT(fsp);
2828 ZERO_STRUCT(quotas);
2830 fsp.conn = conn;
2831 fsp.fnum = -1;
2833 /* access check */
2834 if (conn->server_info->utok.uid != 0) {
2835 DEBUG(0,("set_user_quota: access_denied "
2836 "service [%s] user [%s]\n",
2837 lp_servicename(SNUM(conn)),
2838 conn->server_info->unix_name));
2839 reply_doserror(req, ERRDOS, ERRnoaccess);
2840 return;
2843 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2844 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2845 reply_doserror(req, ERRSRV, ERRerror);
2846 return;
2849 data_len = 48;
2851 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2853 /* Unknown1 24 NULL bytes*/
2854 SBIG_UINT(pdata,0,(uint64_t)0);
2855 SBIG_UINT(pdata,8,(uint64_t)0);
2856 SBIG_UINT(pdata,16,(uint64_t)0);
2858 /* Default Soft Quota 8 bytes */
2859 SBIG_UINT(pdata,24,quotas.softlim);
2861 /* Default Hard Quota 8 bytes */
2862 SBIG_UINT(pdata,32,quotas.hardlim);
2864 /* Quota flag 2 bytes */
2865 SSVAL(pdata,40,quotas.qflags);
2867 /* Unknown3 6 NULL bytes */
2868 SSVAL(pdata,42,0);
2869 SIVAL(pdata,44,0);
2871 break;
2873 #endif /* HAVE_SYS_QUOTAS */
2874 case SMB_FS_OBJECTID_INFORMATION:
2876 unsigned char objid[16];
2877 struct smb_extended_info extended_info;
2878 memcpy(pdata,create_volume_objectid(conn, objid),16);
2879 samba_extended_info_version (&extended_info);
2880 SIVAL(pdata,16,extended_info.samba_magic);
2881 SIVAL(pdata,20,extended_info.samba_version);
2882 SIVAL(pdata,24,extended_info.samba_subversion);
2883 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2884 memcpy(pdata+36,extended_info.samba_version_string,28);
2885 data_len = 64;
2886 break;
2890 * Query the version and capabilities of the CIFS UNIX extensions
2891 * in use.
2894 case SMB_QUERY_CIFS_UNIX_INFO:
2896 bool large_write = lp_min_receive_file_size() &&
2897 !srv_is_signing_active();
2898 bool large_read = !srv_is_signing_active();
2899 int encrypt_caps = 0;
2901 if (!lp_unix_extensions()) {
2902 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2903 return;
2906 switch (conn->encrypt_level) {
2907 case 0:
2908 encrypt_caps = 0;
2909 break;
2910 case 1:
2911 case Auto:
2912 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2913 break;
2914 case Required:
2915 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2916 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2917 large_write = false;
2918 large_read = false;
2919 break;
2922 data_len = 12;
2923 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2924 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2926 /* We have POSIX ACLs, pathname, encryption,
2927 * large read/write, and locking capability. */
2929 SBIG_UINT(pdata,4,((uint64_t)(
2930 CIFS_UNIX_POSIX_ACLS_CAP|
2931 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2932 CIFS_UNIX_FCNTL_LOCKS_CAP|
2933 CIFS_UNIX_EXTATTR_CAP|
2934 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2935 encrypt_caps|
2936 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2937 (large_write ?
2938 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2939 break;
2942 case SMB_QUERY_POSIX_FS_INFO:
2944 int rc;
2945 vfs_statvfs_struct svfs;
2947 if (!lp_unix_extensions()) {
2948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2949 return;
2952 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2954 if (!rc) {
2955 data_len = 56;
2956 SIVAL(pdata,0,svfs.OptimalTransferSize);
2957 SIVAL(pdata,4,svfs.BlockSize);
2958 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2959 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2960 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2961 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2962 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2963 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2964 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2965 #ifdef EOPNOTSUPP
2966 } else if (rc == EOPNOTSUPP) {
2967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2968 return;
2969 #endif /* EOPNOTSUPP */
2970 } else {
2971 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2972 reply_doserror(req, ERRSRV, ERRerror);
2973 return;
2975 break;
2978 case SMB_QUERY_POSIX_WHOAMI:
2980 uint32_t flags = 0;
2981 uint32_t sid_bytes;
2982 int i;
2984 if (!lp_unix_extensions()) {
2985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2986 return;
2989 if (max_data_bytes < 40) {
2990 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2991 return;
2994 /* We ARE guest if global_sid_Builtin_Guests is
2995 * in our list of SIDs.
2997 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2998 conn->server_info->ptok)) {
2999 flags |= SMB_WHOAMI_GUEST;
3002 /* We are NOT guest if global_sid_Authenticated_Users
3003 * is in our list of SIDs.
3005 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3006 conn->server_info->ptok)) {
3007 flags &= ~SMB_WHOAMI_GUEST;
3010 /* NOTE: 8 bytes for UID/GID, irrespective of native
3011 * platform size. This matches
3012 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3014 data_len = 4 /* flags */
3015 + 4 /* flag mask */
3016 + 8 /* uid */
3017 + 8 /* gid */
3018 + 4 /* ngroups */
3019 + 4 /* num_sids */
3020 + 4 /* SID bytes */
3021 + 4 /* pad/reserved */
3022 + (conn->server_info->utok.ngroups * 8)
3023 /* groups list */
3024 + (conn->server_info->ptok->num_sids *
3025 SID_MAX_SIZE)
3026 /* SID list */;
3028 SIVAL(pdata, 0, flags);
3029 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3030 SBIG_UINT(pdata, 8,
3031 (uint64_t)conn->server_info->utok.uid);
3032 SBIG_UINT(pdata, 16,
3033 (uint64_t)conn->server_info->utok.gid);
3036 if (data_len >= max_data_bytes) {
3037 /* Potential overflow, skip the GIDs and SIDs. */
3039 SIVAL(pdata, 24, 0); /* num_groups */
3040 SIVAL(pdata, 28, 0); /* num_sids */
3041 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3042 SIVAL(pdata, 36, 0); /* reserved */
3044 data_len = 40;
3045 break;
3048 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3049 SIVAL(pdata, 28, conn->server_info->num_sids);
3051 /* We walk the SID list twice, but this call is fairly
3052 * infrequent, and I don't expect that it's performance
3053 * sensitive -- jpeach
3055 for (i = 0, sid_bytes = 0;
3056 i < conn->server_info->ptok->num_sids; ++i) {
3057 sid_bytes += ndr_size_dom_sid(
3058 &conn->server_info->ptok->user_sids[i],
3059 NULL,
3063 /* SID list byte count */
3064 SIVAL(pdata, 32, sid_bytes);
3066 /* 4 bytes pad/reserved - must be zero */
3067 SIVAL(pdata, 36, 0);
3068 data_len = 40;
3070 /* GID list */
3071 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3072 SBIG_UINT(pdata, data_len,
3073 (uint64_t)conn->server_info->utok.groups[i]);
3074 data_len += 8;
3077 /* SID list */
3078 for (i = 0;
3079 i < conn->server_info->ptok->num_sids; ++i) {
3080 int sid_len = ndr_size_dom_sid(
3081 &conn->server_info->ptok->user_sids[i],
3082 NULL,
3085 sid_linearize(pdata + data_len, sid_len,
3086 &conn->server_info->ptok->user_sids[i]);
3087 data_len += sid_len;
3090 break;
3093 case SMB_MAC_QUERY_FS_INFO:
3095 * Thursby MAC extension... ONLY on NTFS filesystems
3096 * once we do streams then we don't need this
3098 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3099 data_len = 88;
3100 SIVAL(pdata,84,0x100); /* Don't support mac... */
3101 break;
3103 /* drop through */
3104 default:
3105 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3106 return;
3110 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3111 max_data_bytes);
3113 DEBUG( 4, ( "%s info_level = %d\n",
3114 smb_fn_name(req->cmd), info_level) );
3116 return;
3119 /****************************************************************************
3120 Reply to a TRANS2_SETFSINFO (set filesystem info).
3121 ****************************************************************************/
3123 static void call_trans2setfsinfo(connection_struct *conn,
3124 struct smb_request *req,
3125 char **pparams, int total_params,
3126 char **ppdata, int total_data,
3127 unsigned int max_data_bytes)
3129 char *pdata = *ppdata;
3130 char *params = *pparams;
3131 uint16 info_level;
3133 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3135 /* */
3136 if (total_params < 4) {
3137 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3138 total_params));
3139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3140 return;
3143 info_level = SVAL(params,2);
3145 if (IS_IPC(conn)) {
3146 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3147 info_level != SMB_SET_CIFS_UNIX_INFO) {
3148 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3149 "info level (0x%x) on IPC$.\n",
3150 (unsigned int)info_level));
3151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3152 return;
3156 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3157 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3158 DEBUG(0,("call_trans2setfsinfo: encryption required "
3159 "and info level 0x%x sent.\n",
3160 (unsigned int)info_level));
3161 exit_server_cleanly("encryption required "
3162 "on connection");
3163 return;
3167 switch(info_level) {
3168 case SMB_SET_CIFS_UNIX_INFO:
3170 uint16 client_unix_major;
3171 uint16 client_unix_minor;
3172 uint32 client_unix_cap_low;
3173 uint32 client_unix_cap_high;
3175 if (!lp_unix_extensions()) {
3176 reply_nterror(req,
3177 NT_STATUS_INVALID_LEVEL);
3178 return;
3181 /* There should be 12 bytes of capabilities set. */
3182 if (total_data < 8) {
3183 reply_nterror(
3184 req,
3185 NT_STATUS_INVALID_PARAMETER);
3186 return;
3188 client_unix_major = SVAL(pdata,0);
3189 client_unix_minor = SVAL(pdata,2);
3190 client_unix_cap_low = IVAL(pdata,4);
3191 client_unix_cap_high = IVAL(pdata,8);
3192 /* Just print these values for now. */
3193 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3194 cap_low = 0x%x, cap_high = 0x%x\n",
3195 (unsigned int)client_unix_major,
3196 (unsigned int)client_unix_minor,
3197 (unsigned int)client_unix_cap_low,
3198 (unsigned int)client_unix_cap_high ));
3200 /* Here is where we must switch to posix pathname processing... */
3201 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3202 lp_set_posix_pathnames();
3203 mangle_change_to_posix();
3206 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3207 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3208 /* Client that knows how to do posix locks,
3209 * but not posix open/mkdir operations. Set a
3210 * default type for read/write checks. */
3212 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3215 break;
3218 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3220 NTSTATUS status;
3221 size_t param_len = 0;
3222 size_t data_len = total_data;
3224 if (!lp_unix_extensions()) {
3225 reply_nterror(
3226 req,
3227 NT_STATUS_INVALID_LEVEL);
3228 return;
3231 if (lp_smb_encrypt(SNUM(conn)) == false) {
3232 reply_nterror(
3233 req,
3234 NT_STATUS_NOT_SUPPORTED);
3235 return;
3238 DEBUG( 4,("call_trans2setfsinfo: "
3239 "request transport encryption.\n"));
3241 status = srv_request_encryption_setup(conn,
3242 (unsigned char **)ppdata,
3243 &data_len,
3244 (unsigned char **)pparams,
3245 &param_len);
3247 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3248 !NT_STATUS_IS_OK(status)) {
3249 reply_nterror(req, status);
3250 return;
3253 send_trans2_replies(conn, req,
3254 *pparams,
3255 param_len,
3256 *ppdata,
3257 data_len,
3258 max_data_bytes);
3260 if (NT_STATUS_IS_OK(status)) {
3261 /* Server-side transport
3262 * encryption is now *on*. */
3263 status = srv_encryption_start(conn);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 exit_server_cleanly(
3266 "Failure in setting "
3267 "up encrypted transport");
3270 return;
3273 case SMB_FS_QUOTA_INFORMATION:
3275 files_struct *fsp = NULL;
3276 SMB_NTQUOTA_STRUCT quotas;
3278 ZERO_STRUCT(quotas);
3280 /* access check */
3281 if ((conn->server_info->utok.uid != 0)
3282 ||!CAN_WRITE(conn)) {
3283 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3284 lp_servicename(SNUM(conn)),
3285 conn->server_info->unix_name));
3286 reply_doserror(req, ERRSRV, ERRaccess);
3287 return;
3290 /* note: normaly there're 48 bytes,
3291 * but we didn't use the last 6 bytes for now
3292 * --metze
3294 fsp = file_fsp(req, SVAL(params,0));
3296 if (!check_fsp_ntquota_handle(conn, req,
3297 fsp)) {
3298 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3299 reply_nterror(
3300 req, NT_STATUS_INVALID_HANDLE);
3301 return;
3304 if (total_data < 42) {
3305 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3306 total_data));
3307 reply_nterror(
3308 req,
3309 NT_STATUS_INVALID_PARAMETER);
3310 return;
3313 /* unknown_1 24 NULL bytes in pdata*/
3315 /* the soft quotas 8 bytes (uint64_t)*/
3316 quotas.softlim = (uint64_t)IVAL(pdata,24);
3317 #ifdef LARGE_SMB_OFF_T
3318 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3319 #else /* LARGE_SMB_OFF_T */
3320 if ((IVAL(pdata,28) != 0)&&
3321 ((quotas.softlim != 0xFFFFFFFF)||
3322 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3323 /* more than 32 bits? */
3324 reply_nterror(
3325 req,
3326 NT_STATUS_INVALID_PARAMETER);
3327 return;
3329 #endif /* LARGE_SMB_OFF_T */
3331 /* the hard quotas 8 bytes (uint64_t)*/
3332 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3333 #ifdef LARGE_SMB_OFF_T
3334 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3335 #else /* LARGE_SMB_OFF_T */
3336 if ((IVAL(pdata,36) != 0)&&
3337 ((quotas.hardlim != 0xFFFFFFFF)||
3338 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3339 /* more than 32 bits? */
3340 reply_nterror(
3341 req,
3342 NT_STATUS_INVALID_PARAMETER);
3343 return;
3345 #endif /* LARGE_SMB_OFF_T */
3347 /* quota_flags 2 bytes **/
3348 quotas.qflags = SVAL(pdata,40);
3350 /* unknown_2 6 NULL bytes follow*/
3352 /* now set the quotas */
3353 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3354 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3355 reply_doserror(req, ERRSRV, ERRerror);
3356 return;
3359 break;
3361 default:
3362 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3363 info_level));
3364 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3365 return;
3366 break;
3370 * sending this reply works fine,
3371 * but I'm not sure it's the same
3372 * like windows do...
3373 * --metze
3375 reply_outbuf(req, 10, 0);
3378 #if defined(HAVE_POSIX_ACLS)
3379 /****************************************************************************
3380 Utility function to count the number of entries in a POSIX acl.
3381 ****************************************************************************/
3383 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3385 unsigned int ace_count = 0;
3386 int entry_id = SMB_ACL_FIRST_ENTRY;
3387 SMB_ACL_ENTRY_T entry;
3389 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3390 /* get_next... */
3391 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3392 entry_id = SMB_ACL_NEXT_ENTRY;
3394 ace_count++;
3396 return ace_count;
3399 /****************************************************************************
3400 Utility function to marshall a POSIX acl into wire format.
3401 ****************************************************************************/
3403 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3405 int entry_id = SMB_ACL_FIRST_ENTRY;
3406 SMB_ACL_ENTRY_T entry;
3408 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3409 SMB_ACL_TAG_T tagtype;
3410 SMB_ACL_PERMSET_T permset;
3411 unsigned char perms = 0;
3412 unsigned int own_grp;
3414 /* get_next... */
3415 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3416 entry_id = SMB_ACL_NEXT_ENTRY;
3419 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3420 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3421 return False;
3424 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3425 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3426 return False;
3429 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3430 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3431 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3433 SCVAL(pdata,1,perms);
3435 switch (tagtype) {
3436 case SMB_ACL_USER_OBJ:
3437 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3438 own_grp = (unsigned int)pst->st_uid;
3439 SIVAL(pdata,2,own_grp);
3440 SIVAL(pdata,6,0);
3441 break;
3442 case SMB_ACL_USER:
3444 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3445 if (!puid) {
3446 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3447 return False;
3449 own_grp = (unsigned int)*puid;
3450 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3451 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3452 SIVAL(pdata,2,own_grp);
3453 SIVAL(pdata,6,0);
3454 break;
3456 case SMB_ACL_GROUP_OBJ:
3457 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3458 own_grp = (unsigned int)pst->st_gid;
3459 SIVAL(pdata,2,own_grp);
3460 SIVAL(pdata,6,0);
3461 break;
3462 case SMB_ACL_GROUP:
3464 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3465 if (!pgid) {
3466 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3467 return False;
3469 own_grp = (unsigned int)*pgid;
3470 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3471 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3472 SIVAL(pdata,2,own_grp);
3473 SIVAL(pdata,6,0);
3474 break;
3476 case SMB_ACL_MASK:
3477 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3478 SIVAL(pdata,2,0xFFFFFFFF);
3479 SIVAL(pdata,6,0xFFFFFFFF);
3480 break;
3481 case SMB_ACL_OTHER:
3482 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3483 SIVAL(pdata,2,0xFFFFFFFF);
3484 SIVAL(pdata,6,0xFFFFFFFF);
3485 break;
3486 default:
3487 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3488 return False;
3490 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3493 return True;
3495 #endif
3497 /****************************************************************************
3498 Store the FILE_UNIX_BASIC info.
3499 ****************************************************************************/
3501 static char *store_file_unix_basic(connection_struct *conn,
3502 char *pdata,
3503 files_struct *fsp,
3504 const SMB_STRUCT_STAT *psbuf)
3506 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3507 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3509 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3510 pdata += 8;
3512 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3513 pdata += 8;
3515 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3516 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3517 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3518 pdata += 24;
3520 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3521 SIVAL(pdata,4,0);
3522 pdata += 8;
3524 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3525 SIVAL(pdata,4,0);
3526 pdata += 8;
3528 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3529 pdata += 4;
3531 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3532 SIVAL(pdata,4,0);
3533 pdata += 8;
3535 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3536 SIVAL(pdata,4,0);
3537 pdata += 8;
3539 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3540 pdata += 8;
3542 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3543 SIVAL(pdata,4,0);
3544 pdata += 8;
3546 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3547 SIVAL(pdata,4,0);
3548 pdata += 8;
3550 return pdata;
3553 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3554 * the chflags(2) (or equivalent) flags.
3556 * XXX: this really should be behind the VFS interface. To do this, we would
3557 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3558 * Each VFS module could then implement its own mapping as appropriate for the
3559 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3561 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3562 info2_flags_map[] =
3564 #ifdef UF_NODUMP
3565 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3566 #endif
3568 #ifdef UF_IMMUTABLE
3569 { UF_IMMUTABLE, EXT_IMMUTABLE },
3570 #endif
3572 #ifdef UF_APPEND
3573 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3574 #endif
3576 #ifdef UF_HIDDEN
3577 { UF_HIDDEN, EXT_HIDDEN },
3578 #endif
3580 /* Do not remove. We need to guarantee that this array has at least one
3581 * entry to build on HP-UX.
3583 { 0, 0 }
3587 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3588 uint32 *smb_fflags, uint32 *smb_fmask)
3590 #ifdef HAVE_STAT_ST_FLAGS
3591 int i;
3593 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3594 *smb_fmask |= info2_flags_map[i].smb_fflag;
3595 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3596 *smb_fflags |= info2_flags_map[i].smb_fflag;
3599 #endif /* HAVE_STAT_ST_FLAGS */
3602 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3603 const uint32 smb_fflags,
3604 const uint32 smb_fmask,
3605 int *stat_fflags)
3607 #ifdef HAVE_STAT_ST_FLAGS
3608 uint32 max_fmask = 0;
3609 int i;
3611 *stat_fflags = psbuf->st_flags;
3613 /* For each flags requested in smb_fmask, check the state of the
3614 * corresponding flag in smb_fflags and set or clear the matching
3615 * stat flag.
3618 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3619 max_fmask |= info2_flags_map[i].smb_fflag;
3620 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3621 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3622 *stat_fflags |= info2_flags_map[i].stat_fflag;
3623 } else {
3624 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3629 /* If smb_fmask is asking to set any bits that are not supported by
3630 * our flag mappings, we should fail.
3632 if ((smb_fmask & max_fmask) != smb_fmask) {
3633 return False;
3636 return True;
3637 #else
3638 return False;
3639 #endif /* HAVE_STAT_ST_FLAGS */
3643 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3644 * of file flags and birth (create) time.
3646 static char *store_file_unix_basic_info2(connection_struct *conn,
3647 char *pdata,
3648 files_struct *fsp,
3649 const SMB_STRUCT_STAT *psbuf)
3651 uint32 file_flags = 0;
3652 uint32 flags_mask = 0;
3654 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3656 /* Create (birth) time 64 bit */
3657 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3658 pdata += 8;
3660 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3661 SIVAL(pdata, 0, file_flags); /* flags */
3662 SIVAL(pdata, 4, flags_mask); /* mask */
3663 pdata += 8;
3665 return pdata;
3668 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3669 const struct stream_struct *streams,
3670 char *data,
3671 unsigned int max_data_bytes,
3672 unsigned int *data_size)
3674 unsigned int i;
3675 unsigned int ofs = 0;
3677 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3678 unsigned int next_offset;
3679 size_t namelen;
3680 smb_ucs2_t *namebuf;
3682 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3683 streams[i].name, &namelen) ||
3684 namelen <= 2)
3686 return NT_STATUS_INVALID_PARAMETER;
3690 * name_buf is now null-terminated, we need to marshall as not
3691 * terminated
3694 namelen -= 2;
3696 SIVAL(data, ofs+4, namelen);
3697 SOFF_T(data, ofs+8, streams[i].size);
3698 SOFF_T(data, ofs+16, streams[i].alloc_size);
3699 memcpy(data+ofs+24, namebuf, namelen);
3700 TALLOC_FREE(namebuf);
3702 next_offset = ofs + 24 + namelen;
3704 if (i == num_streams-1) {
3705 SIVAL(data, ofs, 0);
3707 else {
3708 unsigned int align = ndr_align_size(next_offset, 8);
3710 memset(data+next_offset, 0, align);
3711 next_offset += align;
3713 SIVAL(data, ofs, next_offset - ofs);
3714 ofs = next_offset;
3717 ofs = next_offset;
3720 *data_size = ofs;
3722 return NT_STATUS_OK;
3725 /****************************************************************************
3726 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3727 ****************************************************************************/
3729 static void call_trans2qpipeinfo(connection_struct *conn,
3730 struct smb_request *req,
3731 unsigned int tran_call,
3732 char **pparams, int total_params,
3733 char **ppdata, int total_data,
3734 unsigned int max_data_bytes)
3736 char *params = *pparams;
3737 char *pdata = *ppdata;
3738 unsigned int data_size = 0;
3739 unsigned int param_size = 2;
3740 uint16 info_level;
3741 files_struct *fsp;
3743 if (!params) {
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 return;
3748 if (total_params < 4) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750 return;
3753 fsp = file_fsp(req, SVAL(params,0));
3754 if (!fsp_is_np(fsp)) {
3755 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3756 return;
3759 info_level = SVAL(params,2);
3761 *pparams = (char *)SMB_REALLOC(*pparams,2);
3762 if (*pparams == NULL) {
3763 reply_nterror(req, NT_STATUS_NO_MEMORY);
3764 return;
3766 params = *pparams;
3767 SSVAL(params,0,0);
3768 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3769 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3770 if (*ppdata == NULL ) {
3771 reply_nterror(req, NT_STATUS_NO_MEMORY);
3772 return;
3774 pdata = *ppdata;
3776 switch (info_level) {
3777 case SMB_FILE_STANDARD_INFORMATION:
3778 memset(pdata,0,24);
3779 SOFF_T(pdata,0,4096LL);
3780 SIVAL(pdata,16,1);
3781 SIVAL(pdata,20,1);
3782 data_size = 24;
3783 break;
3785 default:
3786 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3787 return;
3790 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3791 max_data_bytes);
3793 return;
3796 /****************************************************************************
3797 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3798 file name or file id).
3799 ****************************************************************************/
3801 static void call_trans2qfilepathinfo(connection_struct *conn,
3802 struct smb_request *req,
3803 unsigned int tran_call,
3804 char **pparams, int total_params,
3805 char **ppdata, int total_data,
3806 unsigned int max_data_bytes)
3808 char *params = *pparams;
3809 char *pdata = *ppdata;
3810 char *dstart, *dend;
3811 uint16 info_level;
3812 int mode=0;
3813 int nlink;
3814 SMB_OFF_T file_size=0;
3815 uint64_t allocation_size=0;
3816 unsigned int data_size = 0;
3817 unsigned int param_size = 2;
3818 SMB_STRUCT_STAT sbuf;
3819 char *dos_fname = NULL;
3820 char *fname = NULL;
3821 char *fullpathname;
3822 char *base_name;
3823 char *p;
3824 SMB_OFF_T pos = 0;
3825 bool delete_pending = False;
3826 int len;
3827 time_t create_time, mtime, atime;
3828 struct timespec create_time_ts, mtime_ts, atime_ts;
3829 struct timespec write_time_ts;
3830 files_struct *fsp = NULL;
3831 struct file_id fileid;
3832 struct ea_list *ea_list = NULL;
3833 char *lock_data = NULL;
3834 bool ms_dfs_link = false;
3835 TALLOC_CTX *ctx = talloc_tos();
3837 if (!params) {
3838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3839 return;
3842 ZERO_STRUCT(sbuf);
3843 ZERO_STRUCT(write_time_ts);
3845 if (tran_call == TRANSACT2_QFILEINFO) {
3846 if (total_params < 4) {
3847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3848 return;
3851 if (IS_IPC(conn)) {
3852 call_trans2qpipeinfo(conn, req, tran_call,
3853 pparams, total_params,
3854 ppdata, total_data,
3855 max_data_bytes);
3856 return;
3859 fsp = file_fsp(req, SVAL(params,0));
3860 info_level = SVAL(params,2);
3862 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3864 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3865 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3866 return;
3869 /* Initial check for valid fsp ptr. */
3870 if (!check_fsp_open(conn, req, fsp)) {
3871 return;
3874 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3875 if (!fname) {
3876 reply_nterror(req, NT_STATUS_NO_MEMORY);
3877 return;
3880 if(fsp->fake_file_handle) {
3882 * This is actually for the QUOTA_FAKE_FILE --metze
3885 /* We know this name is ok, it's already passed the checks. */
3887 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3889 * This is actually a QFILEINFO on a directory
3890 * handle (returned from an NT SMB). NT5.0 seems
3891 * to do this call. JRA.
3894 if (INFO_LEVEL_IS_UNIX(info_level)) {
3895 /* Always do lstat for UNIX calls. */
3896 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3897 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3898 reply_unixerror(req,ERRDOS,ERRbadpath);
3899 return;
3901 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3902 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3903 reply_unixerror(req, ERRDOS, ERRbadpath);
3904 return;
3907 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3908 get_file_infos(fileid, &delete_pending, &write_time_ts);
3909 } else {
3911 * Original code - this is an open file.
3913 if (!check_fsp(conn, req, fsp)) {
3914 return;
3917 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3918 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3919 reply_unixerror(req, ERRDOS, ERRbadfid);
3920 return;
3922 pos = fsp->fh->position_information;
3923 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3924 get_file_infos(fileid, &delete_pending, &write_time_ts);
3927 } else {
3928 NTSTATUS status = NT_STATUS_OK;
3930 /* qpathinfo */
3931 if (total_params < 7) {
3932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3933 return;
3936 info_level = SVAL(params,0);
3938 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3940 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3942 return;
3945 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3946 total_params - 6,
3947 STR_TERMINATE, &status);
3948 if (!NT_STATUS_IS_OK(status)) {
3949 reply_nterror(req, status);
3950 return;
3953 status = resolve_dfspath(ctx,
3954 conn,
3955 req->flags2 & FLAGS2_DFS_PATHNAMES,
3956 fname,
3957 &fname);
3958 if (!NT_STATUS_IS_OK(status)) {
3959 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3960 reply_botherror(req,
3961 NT_STATUS_PATH_NOT_COVERED,
3962 ERRSRV, ERRbadpath);
3964 reply_nterror(req, status);
3965 return;
3968 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3969 if (!NT_STATUS_IS_OK(status)) {
3970 reply_nterror(req, status);
3971 return;
3973 status = check_name(conn, fname);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3976 reply_nterror(req, status);
3977 return;
3980 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3981 && is_ntfs_stream_name(fname)) {
3982 char *base;
3983 SMB_STRUCT_STAT bsbuf;
3985 status = split_ntfs_stream_name(talloc_tos(), fname,
3986 &base, NULL);
3987 if (!NT_STATUS_IS_OK(status)) {
3988 DEBUG(10, ("create_file_unixpath: "
3989 "split_ntfs_stream_name failed: %s\n",
3990 nt_errstr(status)));
3991 reply_nterror(req, status);
3992 return;
3995 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3997 if (INFO_LEVEL_IS_UNIX(info_level)) {
3998 /* Always do lstat for UNIX calls. */
3999 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4000 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4001 reply_unixerror(req,ERRDOS,ERRbadpath);
4002 return;
4004 } else {
4005 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4006 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4007 reply_unixerror(req,ERRDOS,ERRbadpath);
4008 return;
4012 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4013 get_file_infos(fileid, &delete_pending, NULL);
4014 if (delete_pending) {
4015 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4016 return;
4020 if (INFO_LEVEL_IS_UNIX(info_level)) {
4021 /* Always do lstat for UNIX calls. */
4022 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4023 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4024 reply_unixerror(req, ERRDOS, ERRbadpath);
4025 return;
4028 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4029 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4031 if (!ms_dfs_link) {
4032 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4033 reply_unixerror(req, ERRDOS, ERRbadpath);
4034 return;
4038 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4039 get_file_infos(fileid, &delete_pending, &write_time_ts);
4040 if (delete_pending) {
4041 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4042 return;
4046 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4047 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4048 return;
4051 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4052 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4054 p = strrchr_m(fname,'/');
4055 if (!p)
4056 base_name = fname;
4057 else
4058 base_name = p+1;
4060 if (ms_dfs_link) {
4061 mode = dos_mode_msdfs(conn,fname,&sbuf);
4062 } else {
4063 mode = dos_mode(conn,fname,&sbuf);
4065 if (!mode)
4066 mode = FILE_ATTRIBUTE_NORMAL;
4068 nlink = sbuf.st_nlink;
4070 if (nlink && (mode&aDIR)) {
4071 nlink = 1;
4074 if ((nlink > 0) && delete_pending) {
4075 nlink -= 1;
4078 fullpathname = fname;
4079 if (!(mode & aDIR))
4080 file_size = get_file_size_stat(&sbuf);
4082 /* Pull out any data sent here before we realloc. */
4083 switch (info_level) {
4084 case SMB_INFO_QUERY_EAS_FROM_LIST:
4086 /* Pull any EA list from the data portion. */
4087 uint32 ea_size;
4089 if (total_data < 4) {
4090 reply_nterror(
4091 req, NT_STATUS_INVALID_PARAMETER);
4092 return;
4094 ea_size = IVAL(pdata,0);
4096 if (total_data > 0 && ea_size != total_data) {
4097 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4098 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4099 reply_nterror(
4100 req, NT_STATUS_INVALID_PARAMETER);
4101 return;
4104 if (!lp_ea_support(SNUM(conn))) {
4105 reply_doserror(req, ERRDOS,
4106 ERReasnotsupported);
4107 return;
4110 /* Pull out the list of names. */
4111 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4112 if (!ea_list) {
4113 reply_nterror(
4114 req, NT_STATUS_INVALID_PARAMETER);
4115 return;
4117 break;
4120 case SMB_QUERY_POSIX_LOCK:
4122 if (fsp == NULL || fsp->fh->fd == -1) {
4123 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4124 return;
4127 if (total_data != POSIX_LOCK_DATA_SIZE) {
4128 reply_nterror(
4129 req, NT_STATUS_INVALID_PARAMETER);
4130 return;
4133 /* Copy the lock range data. */
4134 lock_data = (char *)TALLOC_MEMDUP(
4135 ctx, pdata, total_data);
4136 if (!lock_data) {
4137 reply_nterror(req, NT_STATUS_NO_MEMORY);
4138 return;
4141 default:
4142 break;
4145 *pparams = (char *)SMB_REALLOC(*pparams,2);
4146 if (*pparams == NULL) {
4147 reply_nterror(req, NT_STATUS_NO_MEMORY);
4148 return;
4150 params = *pparams;
4151 SSVAL(params,0,0);
4152 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4153 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4154 if (*ppdata == NULL ) {
4155 reply_nterror(req, NT_STATUS_NO_MEMORY);
4156 return;
4158 pdata = *ppdata;
4159 dstart = pdata;
4160 dend = dstart + data_size - 1;
4162 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4163 mtime_ts = get_mtimespec(&sbuf);
4164 atime_ts = get_atimespec(&sbuf);
4166 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4168 if (!fsp) {
4169 /* Do we have this path open ? */
4170 files_struct *fsp1;
4171 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4172 fsp1 = file_find_di_first(fileid);
4173 if (fsp1 && fsp1->initial_allocation_size) {
4174 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4178 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4179 mtime_ts = write_time_ts;
4182 if (lp_dos_filetime_resolution(SNUM(conn))) {
4183 dos_filetime_timespec(&create_time_ts);
4184 dos_filetime_timespec(&mtime_ts);
4185 dos_filetime_timespec(&atime_ts);
4188 create_time = convert_timespec_to_time_t(create_time_ts);
4189 mtime = convert_timespec_to_time_t(mtime_ts);
4190 atime = convert_timespec_to_time_t(atime_ts);
4192 /* NT expects the name to be in an exact form of the *full*
4193 filename. See the trans2 torture test */
4194 if (ISDOT(base_name)) {
4195 dos_fname = talloc_strdup(ctx, "\\");
4196 if (!dos_fname) {
4197 reply_nterror(req, NT_STATUS_NO_MEMORY);
4198 return;
4200 } else {
4201 dos_fname = talloc_asprintf(ctx,
4202 "\\%s",
4203 fname);
4204 if (!dos_fname) {
4205 reply_nterror(req, NT_STATUS_NO_MEMORY);
4206 return;
4208 string_replace(dos_fname, '/', '\\');
4211 switch (info_level) {
4212 case SMB_INFO_STANDARD:
4213 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4214 data_size = 22;
4215 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4216 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4217 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4218 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4219 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4220 SSVAL(pdata,l1_attrFile,mode);
4221 break;
4223 case SMB_INFO_QUERY_EA_SIZE:
4225 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4226 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4227 data_size = 26;
4228 srv_put_dos_date2(pdata,0,create_time);
4229 srv_put_dos_date2(pdata,4,atime);
4230 srv_put_dos_date2(pdata,8,mtime); /* write time */
4231 SIVAL(pdata,12,(uint32)file_size);
4232 SIVAL(pdata,16,(uint32)allocation_size);
4233 SSVAL(pdata,20,mode);
4234 SIVAL(pdata,22,ea_size);
4235 break;
4238 case SMB_INFO_IS_NAME_VALID:
4239 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4240 if (tran_call == TRANSACT2_QFILEINFO) {
4241 /* os/2 needs this ? really ?*/
4242 reply_doserror(req, ERRDOS, ERRbadfunc);
4243 return;
4245 data_size = 0;
4246 param_size = 0;
4247 break;
4249 case SMB_INFO_QUERY_EAS_FROM_LIST:
4251 size_t total_ea_len = 0;
4252 struct ea_list *ea_file_list = NULL;
4254 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4256 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4257 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4259 if (!ea_list || (total_ea_len > data_size)) {
4260 data_size = 4;
4261 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4262 break;
4265 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4266 break;
4269 case SMB_INFO_QUERY_ALL_EAS:
4271 /* We have data_size bytes to put EA's into. */
4272 size_t total_ea_len = 0;
4274 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4276 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4277 if (!ea_list || (total_ea_len > data_size)) {
4278 data_size = 4;
4279 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4280 break;
4283 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4284 break;
4287 case SMB_FILE_BASIC_INFORMATION:
4288 case SMB_QUERY_FILE_BASIC_INFO:
4290 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4292 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4293 } else {
4294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4295 data_size = 40;
4296 SIVAL(pdata,36,0);
4298 put_long_date_timespec(pdata,create_time_ts);
4299 put_long_date_timespec(pdata+8,atime_ts);
4300 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4301 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4302 SIVAL(pdata,32,mode);
4304 DEBUG(5,("SMB_QFBI - "));
4305 DEBUG(5,("create: %s ", ctime(&create_time)));
4306 DEBUG(5,("access: %s ", ctime(&atime)));
4307 DEBUG(5,("write: %s ", ctime(&mtime)));
4308 DEBUG(5,("change: %s ", ctime(&mtime)));
4309 DEBUG(5,("mode: %x\n", mode));
4310 break;
4312 case SMB_FILE_STANDARD_INFORMATION:
4313 case SMB_QUERY_FILE_STANDARD_INFO:
4315 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4316 data_size = 24;
4317 SOFF_T(pdata,0,allocation_size);
4318 SOFF_T(pdata,8,file_size);
4319 SIVAL(pdata,16,nlink);
4320 SCVAL(pdata,20,delete_pending?1:0);
4321 SCVAL(pdata,21,(mode&aDIR)?1:0);
4322 SSVAL(pdata,22,0); /* Padding. */
4323 break;
4325 case SMB_FILE_EA_INFORMATION:
4326 case SMB_QUERY_FILE_EA_INFO:
4328 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4330 data_size = 4;
4331 SIVAL(pdata,0,ea_size);
4332 break;
4335 /* Get the 8.3 name - used if NT SMB was negotiated. */
4336 case SMB_QUERY_FILE_ALT_NAME_INFO:
4337 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4339 char mangled_name[13];
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4341 if (!name_to_8_3(base_name,mangled_name,
4342 True,conn->params)) {
4343 reply_nterror(
4344 req,
4345 NT_STATUS_NO_MEMORY);
4347 len = srvstr_push(dstart, req->flags2,
4348 pdata+4, mangled_name,
4349 PTR_DIFF(dend, pdata+4),
4350 STR_UNICODE);
4351 data_size = 4 + len;
4352 SIVAL(pdata,0,len);
4353 break;
4356 case SMB_QUERY_FILE_NAME_INFO:
4358 this must be *exactly* right for ACLs on mapped drives to work
4360 len = srvstr_push(dstart, req->flags2,
4361 pdata+4, dos_fname,
4362 PTR_DIFF(dend, pdata+4),
4363 STR_UNICODE);
4364 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4365 data_size = 4 + len;
4366 SIVAL(pdata,0,len);
4367 break;
4369 case SMB_FILE_ALLOCATION_INFORMATION:
4370 case SMB_QUERY_FILE_ALLOCATION_INFO:
4371 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4372 data_size = 8;
4373 SOFF_T(pdata,0,allocation_size);
4374 break;
4376 case SMB_FILE_END_OF_FILE_INFORMATION:
4377 case SMB_QUERY_FILE_END_OF_FILEINFO:
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4379 data_size = 8;
4380 SOFF_T(pdata,0,file_size);
4381 break;
4383 case SMB_QUERY_FILE_ALL_INFO:
4384 case SMB_FILE_ALL_INFORMATION:
4386 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4388 put_long_date_timespec(pdata,create_time_ts);
4389 put_long_date_timespec(pdata+8,atime_ts);
4390 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4391 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4392 SIVAL(pdata,32,mode);
4393 SIVAL(pdata,36,0); /* padding. */
4394 pdata += 40;
4395 SOFF_T(pdata,0,allocation_size);
4396 SOFF_T(pdata,8,file_size);
4397 SIVAL(pdata,16,nlink);
4398 SCVAL(pdata,20,delete_pending);
4399 SCVAL(pdata,21,(mode&aDIR)?1:0);
4400 SSVAL(pdata,22,0);
4401 pdata += 24;
4402 SIVAL(pdata,0,ea_size);
4403 pdata += 4; /* EA info */
4404 len = srvstr_push(dstart, req->flags2,
4405 pdata+4, dos_fname,
4406 PTR_DIFF(dend, pdata+4),
4407 STR_UNICODE);
4408 SIVAL(pdata,0,len);
4409 pdata += 4 + len;
4410 data_size = PTR_DIFF(pdata,(*ppdata));
4411 break;
4413 case SMB_FILE_INTERNAL_INFORMATION:
4414 /* This should be an index number - looks like
4415 dev/ino to me :-)
4417 I think this causes us to fail the IFSKIT
4418 BasicFileInformationTest. -tpot */
4420 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4421 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4422 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4423 data_size = 8;
4424 break;
4426 case SMB_FILE_ACCESS_INFORMATION:
4427 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4428 if (fsp) {
4429 SIVAL(pdata,0,fsp->access_mask);
4430 } else {
4431 /* GENERIC_EXECUTE mapping from Windows */
4432 SIVAL(pdata,0,0x12019F);
4434 data_size = 4;
4435 break;
4437 case SMB_FILE_NAME_INFORMATION:
4438 /* Pathname with leading '\'. */
4440 size_t byte_len;
4441 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4442 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4443 SIVAL(pdata,0,byte_len);
4444 data_size = 4 + byte_len;
4445 break;
4448 case SMB_FILE_DISPOSITION_INFORMATION:
4449 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4450 data_size = 1;
4451 SCVAL(pdata,0,delete_pending);
4452 break;
4454 case SMB_FILE_POSITION_INFORMATION:
4455 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4456 data_size = 8;
4457 SOFF_T(pdata,0,pos);
4458 break;
4460 case SMB_FILE_MODE_INFORMATION:
4461 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4462 SIVAL(pdata,0,mode);
4463 data_size = 4;
4464 break;
4466 case SMB_FILE_ALIGNMENT_INFORMATION:
4467 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4468 SIVAL(pdata,0,0); /* No alignment needed. */
4469 data_size = 4;
4470 break;
4473 * NT4 server just returns "invalid query" to this - if we try
4474 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4475 * want this. JRA.
4477 /* The first statement above is false - verified using Thursby
4478 * client against NT4 -- gcolley.
4480 case SMB_QUERY_FILE_STREAM_INFO:
4481 case SMB_FILE_STREAM_INFORMATION: {
4482 unsigned int num_streams;
4483 struct stream_struct *streams;
4484 NTSTATUS status;
4486 DEBUG(10,("call_trans2qfilepathinfo: "
4487 "SMB_FILE_STREAM_INFORMATION\n"));
4489 status = SMB_VFS_STREAMINFO(
4490 conn, fsp, fname, talloc_tos(),
4491 &num_streams, &streams);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 DEBUG(10, ("could not get stream info: %s\n",
4495 nt_errstr(status)));
4496 reply_nterror(req, status);
4497 return;
4500 status = marshall_stream_info(num_streams, streams,
4501 pdata, max_data_bytes,
4502 &data_size);
4504 if (!NT_STATUS_IS_OK(status)) {
4505 DEBUG(10, ("marshall_stream_info failed: %s\n",
4506 nt_errstr(status)));
4507 reply_nterror(req, status);
4508 return;
4511 TALLOC_FREE(streams);
4513 break;
4515 case SMB_QUERY_COMPRESSION_INFO:
4516 case SMB_FILE_COMPRESSION_INFORMATION:
4517 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4518 SOFF_T(pdata,0,file_size);
4519 SIVAL(pdata,8,0); /* ??? */
4520 SIVAL(pdata,12,0); /* ??? */
4521 data_size = 16;
4522 break;
4524 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4525 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4526 put_long_date_timespec(pdata,create_time_ts);
4527 put_long_date_timespec(pdata+8,atime_ts);
4528 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4529 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4530 SOFF_T(pdata,32,allocation_size);
4531 SOFF_T(pdata,40,file_size);
4532 SIVAL(pdata,48,mode);
4533 SIVAL(pdata,52,0); /* ??? */
4534 data_size = 56;
4535 break;
4537 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4538 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4539 SIVAL(pdata,0,mode);
4540 SIVAL(pdata,4,0);
4541 data_size = 8;
4542 break;
4545 * CIFS UNIX Extensions.
4548 case SMB_QUERY_FILE_UNIX_BASIC:
4550 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4551 data_size = PTR_DIFF(pdata,(*ppdata));
4554 int i;
4555 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4557 for (i=0; i<100; i++)
4558 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4559 DEBUG(4,("\n"));
4562 break;
4564 case SMB_QUERY_FILE_UNIX_INFO2:
4566 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4567 data_size = PTR_DIFF(pdata,(*ppdata));
4570 int i;
4571 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4573 for (i=0; i<100; i++)
4574 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4575 DEBUG(4,("\n"));
4578 break;
4580 case SMB_QUERY_FILE_UNIX_LINK:
4582 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4584 if (!buffer) {
4585 reply_nterror(req, NT_STATUS_NO_MEMORY);
4586 return;
4589 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4590 #ifdef S_ISLNK
4591 if(!S_ISLNK(sbuf.st_mode)) {
4592 reply_unixerror(req, ERRSRV,
4593 ERRbadlink);
4594 return;
4596 #else
4597 reply_unixerror(req, ERRDOS, ERRbadlink);
4598 return;
4599 #endif
4600 len = SMB_VFS_READLINK(conn,fullpathname,
4601 buffer, PATH_MAX);
4602 if (len == -1) {
4603 reply_unixerror(req, ERRDOS,
4604 ERRnoaccess);
4605 return;
4607 buffer[len] = 0;
4608 len = srvstr_push(dstart, req->flags2,
4609 pdata, buffer,
4610 PTR_DIFF(dend, pdata),
4611 STR_TERMINATE);
4612 pdata += len;
4613 data_size = PTR_DIFF(pdata,(*ppdata));
4615 break;
4618 #if defined(HAVE_POSIX_ACLS)
4619 case SMB_QUERY_POSIX_ACL:
4621 SMB_ACL_T file_acl = NULL;
4622 SMB_ACL_T def_acl = NULL;
4623 uint16 num_file_acls = 0;
4624 uint16 num_def_acls = 0;
4626 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4627 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4628 } else {
4629 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4632 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4633 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4634 fname ));
4635 reply_nterror(
4636 req,
4637 NT_STATUS_NOT_IMPLEMENTED);
4638 return;
4641 if (S_ISDIR(sbuf.st_mode)) {
4642 if (fsp && fsp->is_directory) {
4643 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4644 } else {
4645 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4647 def_acl = free_empty_sys_acl(conn, def_acl);
4650 num_file_acls = count_acl_entries(conn, file_acl);
4651 num_def_acls = count_acl_entries(conn, def_acl);
4653 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4654 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4655 data_size,
4656 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4657 SMB_POSIX_ACL_HEADER_SIZE) ));
4658 if (file_acl) {
4659 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4661 if (def_acl) {
4662 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4664 reply_nterror(
4665 req,
4666 NT_STATUS_BUFFER_TOO_SMALL);
4667 return;
4670 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4671 SSVAL(pdata,2,num_file_acls);
4672 SSVAL(pdata,4,num_def_acls);
4673 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4674 if (file_acl) {
4675 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4677 if (def_acl) {
4678 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4680 reply_nterror(
4681 req, NT_STATUS_INTERNAL_ERROR);
4682 return;
4684 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4685 if (file_acl) {
4686 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4688 if (def_acl) {
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4691 reply_nterror(
4692 req,
4693 NT_STATUS_INTERNAL_ERROR);
4694 return;
4697 if (file_acl) {
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4700 if (def_acl) {
4701 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4703 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4704 break;
4706 #endif
4709 case SMB_QUERY_POSIX_LOCK:
4711 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4712 uint64_t count;
4713 uint64_t offset;
4714 uint32 lock_pid;
4715 enum brl_type lock_type;
4717 if (total_data != POSIX_LOCK_DATA_SIZE) {
4718 reply_nterror(
4719 req, NT_STATUS_INVALID_PARAMETER);
4720 return;
4723 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4724 case POSIX_LOCK_TYPE_READ:
4725 lock_type = READ_LOCK;
4726 break;
4727 case POSIX_LOCK_TYPE_WRITE:
4728 lock_type = WRITE_LOCK;
4729 break;
4730 case POSIX_LOCK_TYPE_UNLOCK:
4731 default:
4732 /* There's no point in asking for an unlock... */
4733 reply_nterror(
4734 req,
4735 NT_STATUS_INVALID_PARAMETER);
4736 return;
4739 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4740 #if defined(HAVE_LONGLONG)
4741 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4742 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4743 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4744 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4745 #else /* HAVE_LONGLONG */
4746 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4747 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4748 #endif /* HAVE_LONGLONG */
4750 status = query_lock(fsp,
4751 &lock_pid,
4752 &count,
4753 &offset,
4754 &lock_type,
4755 POSIX_LOCK);
4757 if (ERROR_WAS_LOCK_DENIED(status)) {
4758 /* Here we need to report who has it locked... */
4759 data_size = POSIX_LOCK_DATA_SIZE;
4761 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4762 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4763 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4764 #if defined(HAVE_LONGLONG)
4765 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4766 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4767 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4768 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4769 #else /* HAVE_LONGLONG */
4770 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4771 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4772 #endif /* HAVE_LONGLONG */
4774 } else if (NT_STATUS_IS_OK(status)) {
4775 /* For success we just return a copy of what we sent
4776 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4777 data_size = POSIX_LOCK_DATA_SIZE;
4778 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4779 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4780 } else {
4781 reply_nterror(req, status);
4782 return;
4784 break;
4787 default:
4788 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4789 return;
4792 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4793 max_data_bytes);
4795 return;
4798 /****************************************************************************
4799 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4800 code.
4801 ****************************************************************************/
4803 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4804 connection_struct *conn,
4805 const char *oldname_in,
4806 const char *newname_in)
4808 SMB_STRUCT_STAT sbuf1, sbuf2;
4809 char *last_component_oldname = NULL;
4810 char *last_component_newname = NULL;
4811 char *oldname = NULL;
4812 char *newname = NULL;
4813 NTSTATUS status = NT_STATUS_OK;
4815 ZERO_STRUCT(sbuf1);
4816 ZERO_STRUCT(sbuf2);
4818 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4819 &last_component_oldname, &sbuf1);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 return status;
4824 status = check_name(conn, oldname);
4825 if (!NT_STATUS_IS_OK(status)) {
4826 return status;
4829 /* source must already exist. */
4830 if (!VALID_STAT(sbuf1)) {
4831 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4834 status = unix_convert(ctx, conn, newname_in, False, &newname,
4835 &last_component_newname, &sbuf2);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 return status;
4840 status = check_name(conn, newname);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 return status;
4845 /* Disallow if newname already exists. */
4846 if (VALID_STAT(sbuf2)) {
4847 return NT_STATUS_OBJECT_NAME_COLLISION;
4850 /* No links from a directory. */
4851 if (S_ISDIR(sbuf1.st_mode)) {
4852 return NT_STATUS_FILE_IS_A_DIRECTORY;
4855 /* Ensure this is within the share. */
4856 status = check_reduced_name(conn, oldname);
4857 if (!NT_STATUS_IS_OK(status)) {
4858 return status;
4861 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4863 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4864 status = map_nt_error_from_unix(errno);
4865 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4866 nt_errstr(status), newname, oldname));
4869 return status;
4872 /****************************************************************************
4873 Deal with setting the time from any of the setfilepathinfo functions.
4874 ****************************************************************************/
4876 NTSTATUS smb_set_file_time(connection_struct *conn,
4877 files_struct *fsp,
4878 const char *fname,
4879 const SMB_STRUCT_STAT *psbuf,
4880 struct smb_file_time *ft,
4881 bool setting_write_time)
4883 uint32 action =
4884 FILE_NOTIFY_CHANGE_LAST_ACCESS
4885 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4887 if (!VALID_STAT(*psbuf)) {
4888 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4891 /* get some defaults (no modifications) if any info is zero or -1. */
4892 if (null_timespec(ft->atime)) {
4893 ft->atime= get_atimespec(psbuf);
4894 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4897 if (null_timespec(ft->mtime)) {
4898 ft->mtime = get_mtimespec(psbuf);
4899 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4902 if (!setting_write_time) {
4903 /* ft->mtime comes from change time, not write time. */
4904 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4907 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4908 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4909 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4910 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4911 if (!null_timespec(ft->create_time)) {
4912 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4913 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4917 * Try and set the times of this file if
4918 * they are different from the current values.
4922 struct timespec mts = get_mtimespec(psbuf);
4923 struct timespec ats = get_atimespec(psbuf);
4924 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4925 (timespec_compare(&ft->mtime, &mts) == 0)) {
4926 return NT_STATUS_OK;
4930 if (setting_write_time) {
4932 * This was a setfileinfo on an open file.
4933 * NT does this a lot. We also need to
4934 * set the time here, as it can be read by
4935 * FindFirst/FindNext and with the patch for bug #2045
4936 * in smbd/fileio.c it ensures that this timestamp is
4937 * kept sticky even after a write. We save the request
4938 * away and will set it on file close and after a write. JRA.
4941 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4942 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4944 if (fsp != NULL) {
4945 if (fsp->base_fsp) {
4946 set_sticky_write_time_fsp(fsp->base_fsp,
4947 ft->mtime);
4948 } else {
4949 set_sticky_write_time_fsp(fsp, ft->mtime);
4951 } else {
4952 set_sticky_write_time_path(conn, fname,
4953 vfs_file_id_from_sbuf(conn, psbuf),
4954 ft->mtime);
4958 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4960 if (fsp && fsp->base_fsp) {
4961 fname = fsp->base_fsp->fsp_name;
4964 if(file_ntimes(conn, fname, ft)!=0) {
4965 return map_nt_error_from_unix(errno);
4967 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4969 return NT_STATUS_OK;
4972 /****************************************************************************
4973 Deal with setting the dosmode from any of the setfilepathinfo functions.
4974 ****************************************************************************/
4976 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4977 files_struct *fsp,
4978 const char *fname,
4979 SMB_STRUCT_STAT *psbuf,
4980 uint32 dosmode)
4982 if (!VALID_STAT(*psbuf)) {
4983 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4986 if (fsp) {
4987 if (fsp->base_fsp) {
4988 fname = fsp->base_fsp->fsp_name;
4989 } else {
4990 fname = fsp->fsp_name;
4994 if (dosmode) {
4995 if (S_ISDIR(psbuf->st_mode)) {
4996 dosmode |= aDIR;
4997 } else {
4998 dosmode &= ~aDIR;
5002 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5004 /* check the mode isn't different, before changing it */
5005 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5007 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5008 fname, (unsigned int)dosmode ));
5010 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5011 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5012 fname, strerror(errno)));
5013 return map_nt_error_from_unix(errno);
5016 return NT_STATUS_OK;
5019 /****************************************************************************
5020 Deal with setting the size from any of the setfilepathinfo functions.
5021 ****************************************************************************/
5023 static NTSTATUS smb_set_file_size(connection_struct *conn,
5024 struct smb_request *req,
5025 files_struct *fsp,
5026 const char *fname,
5027 SMB_STRUCT_STAT *psbuf,
5028 SMB_OFF_T size)
5030 NTSTATUS status = NT_STATUS_OK;
5031 files_struct *new_fsp = NULL;
5033 if (!VALID_STAT(*psbuf)) {
5034 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5037 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5039 if (size == get_file_size_stat(psbuf)) {
5040 return NT_STATUS_OK;
5043 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5044 fname, (double)size ));
5046 if (fsp && fsp->fh->fd != -1) {
5047 /* Handle based call. */
5048 if (vfs_set_filelen(fsp, size) == -1) {
5049 return map_nt_error_from_unix(errno);
5051 trigger_write_time_update_immediate(fsp);
5052 return NT_STATUS_OK;
5055 status = SMB_VFS_CREATE_FILE(
5056 conn, /* conn */
5057 req, /* req */
5058 0, /* root_dir_fid */
5059 fname, /* fname */
5060 0, /* create_file_flags */
5061 FILE_WRITE_ATTRIBUTES, /* access_mask */
5062 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5063 FILE_SHARE_DELETE),
5064 FILE_OPEN, /* create_disposition*/
5065 0, /* create_options */
5066 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5067 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5068 0, /* allocation_size */
5069 NULL, /* sd */
5070 NULL, /* ea_list */
5071 &new_fsp, /* result */
5072 NULL, /* pinfo */
5073 psbuf); /* psbuf */
5075 if (!NT_STATUS_IS_OK(status)) {
5076 /* NB. We check for open_was_deferred in the caller. */
5077 return status;
5080 if (vfs_set_filelen(new_fsp, size) == -1) {
5081 status = map_nt_error_from_unix(errno);
5082 close_file(req, new_fsp,NORMAL_CLOSE);
5083 return status;
5086 trigger_write_time_update_immediate(new_fsp);
5087 close_file(req, new_fsp,NORMAL_CLOSE);
5088 return NT_STATUS_OK;
5091 /****************************************************************************
5092 Deal with SMB_INFO_SET_EA.
5093 ****************************************************************************/
5095 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5096 const char *pdata,
5097 int total_data,
5098 files_struct *fsp,
5099 const char *fname)
5101 struct ea_list *ea_list = NULL;
5102 TALLOC_CTX *ctx = NULL;
5103 NTSTATUS status = NT_STATUS_OK;
5105 if (total_data < 10) {
5107 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5108 length. They seem to have no effect. Bug #3212. JRA */
5110 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5111 /* We're done. We only get EA info in this call. */
5112 return NT_STATUS_OK;
5115 return NT_STATUS_INVALID_PARAMETER;
5118 if (IVAL(pdata,0) > total_data) {
5119 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5120 IVAL(pdata,0), (unsigned int)total_data));
5121 return NT_STATUS_INVALID_PARAMETER;
5124 ctx = talloc_tos();
5125 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5126 if (!ea_list) {
5127 return NT_STATUS_INVALID_PARAMETER;
5129 status = set_ea(conn, fsp, fname, ea_list);
5131 return status;
5134 /****************************************************************************
5135 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5136 ****************************************************************************/
5138 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5139 const char *pdata,
5140 int total_data,
5141 files_struct *fsp,
5142 const char *fname,
5143 SMB_STRUCT_STAT *psbuf)
5145 NTSTATUS status = NT_STATUS_OK;
5146 bool delete_on_close;
5147 uint32 dosmode = 0;
5149 if (total_data < 1) {
5150 return NT_STATUS_INVALID_PARAMETER;
5153 if (fsp == NULL) {
5154 return NT_STATUS_INVALID_HANDLE;
5157 delete_on_close = (CVAL(pdata,0) ? True : False);
5158 dosmode = dos_mode(conn, fname, psbuf);
5160 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5161 "delete_on_close = %u\n",
5162 fsp->fsp_name,
5163 (unsigned int)dosmode,
5164 (unsigned int)delete_on_close ));
5166 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 return status;
5172 /* The set is across all open files on this dev/inode pair. */
5173 if (!set_delete_on_close(fsp, delete_on_close,
5174 &conn->server_info->utok)) {
5175 return NT_STATUS_ACCESS_DENIED;
5177 return NT_STATUS_OK;
5180 /****************************************************************************
5181 Deal with SMB_FILE_POSITION_INFORMATION.
5182 ****************************************************************************/
5184 static NTSTATUS smb_file_position_information(connection_struct *conn,
5185 const char *pdata,
5186 int total_data,
5187 files_struct *fsp)
5189 uint64_t position_information;
5191 if (total_data < 8) {
5192 return NT_STATUS_INVALID_PARAMETER;
5195 if (fsp == NULL) {
5196 /* Ignore on pathname based set. */
5197 return NT_STATUS_OK;
5200 position_information = (uint64_t)IVAL(pdata,0);
5201 #ifdef LARGE_SMB_OFF_T
5202 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5203 #else /* LARGE_SMB_OFF_T */
5204 if (IVAL(pdata,4) != 0) {
5205 /* more than 32 bits? */
5206 return NT_STATUS_INVALID_PARAMETER;
5208 #endif /* LARGE_SMB_OFF_T */
5210 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5211 fsp->fsp_name, (double)position_information ));
5212 fsp->fh->position_information = position_information;
5213 return NT_STATUS_OK;
5216 /****************************************************************************
5217 Deal with SMB_FILE_MODE_INFORMATION.
5218 ****************************************************************************/
5220 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5221 const char *pdata,
5222 int total_data)
5224 uint32 mode;
5226 if (total_data < 4) {
5227 return NT_STATUS_INVALID_PARAMETER;
5229 mode = IVAL(pdata,0);
5230 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5231 return NT_STATUS_INVALID_PARAMETER;
5233 return NT_STATUS_OK;
5236 /****************************************************************************
5237 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5238 ****************************************************************************/
5240 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5241 struct smb_request *req,
5242 const char *pdata,
5243 int total_data,
5244 const char *fname)
5246 char *link_target = NULL;
5247 const char *newname = fname;
5248 NTSTATUS status = NT_STATUS_OK;
5249 TALLOC_CTX *ctx = talloc_tos();
5251 /* Set a symbolic link. */
5252 /* Don't allow this if follow links is false. */
5254 if (total_data == 0) {
5255 return NT_STATUS_INVALID_PARAMETER;
5258 if (!lp_symlinks(SNUM(conn))) {
5259 return NT_STATUS_ACCESS_DENIED;
5262 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5263 total_data, STR_TERMINATE);
5265 if (!link_target) {
5266 return NT_STATUS_INVALID_PARAMETER;
5269 /* !widelinks forces the target path to be within the share. */
5270 /* This means we can interpret the target as a pathname. */
5271 if (!lp_widelinks(SNUM(conn))) {
5272 char *rel_name = NULL;
5273 char *last_dirp = NULL;
5275 if (*link_target == '/') {
5276 /* No absolute paths allowed. */
5277 return NT_STATUS_ACCESS_DENIED;
5279 rel_name = talloc_strdup(ctx,newname);
5280 if (!rel_name) {
5281 return NT_STATUS_NO_MEMORY;
5283 last_dirp = strrchr_m(rel_name, '/');
5284 if (last_dirp) {
5285 last_dirp[1] = '\0';
5286 } else {
5287 rel_name = talloc_strdup(ctx,"./");
5288 if (!rel_name) {
5289 return NT_STATUS_NO_MEMORY;
5292 rel_name = talloc_asprintf_append(rel_name,
5293 "%s",
5294 link_target);
5295 if (!rel_name) {
5296 return NT_STATUS_NO_MEMORY;
5299 status = check_name(conn, rel_name);
5300 if (!NT_STATUS_IS_OK(status)) {
5301 return status;
5305 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5306 newname, link_target ));
5308 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5309 return map_nt_error_from_unix(errno);
5312 return NT_STATUS_OK;
5315 /****************************************************************************
5316 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5317 ****************************************************************************/
5319 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5320 struct smb_request *req,
5321 const char *pdata, int total_data,
5322 const char *fname)
5324 char *oldname = NULL;
5325 TALLOC_CTX *ctx = talloc_tos();
5326 NTSTATUS status = NT_STATUS_OK;
5328 /* Set a hard link. */
5329 if (total_data == 0) {
5330 return NT_STATUS_INVALID_PARAMETER;
5333 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5334 total_data, STR_TERMINATE, &status);
5335 if (!NT_STATUS_IS_OK(status)) {
5336 return status;
5339 status = resolve_dfspath(ctx, conn,
5340 req->flags2 & FLAGS2_DFS_PATHNAMES,
5341 oldname,
5342 &oldname);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 return status;
5347 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5348 fname, oldname));
5350 return hardlink_internals(ctx, conn, oldname, fname);
5353 /****************************************************************************
5354 Deal with SMB_FILE_RENAME_INFORMATION.
5355 ****************************************************************************/
5357 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5358 struct smb_request *req,
5359 const char *pdata,
5360 int total_data,
5361 files_struct *fsp,
5362 const char *fname)
5364 bool overwrite;
5365 uint32 root_fid;
5366 uint32 len;
5367 char *newname = NULL;
5368 char *base_name = NULL;
5369 bool dest_has_wcard = False;
5370 SMB_STRUCT_STAT sbuf;
5371 char *newname_last_component = NULL;
5372 NTSTATUS status = NT_STATUS_OK;
5373 char *p;
5374 TALLOC_CTX *ctx = talloc_tos();
5376 if (total_data < 13) {
5377 return NT_STATUS_INVALID_PARAMETER;
5380 ZERO_STRUCT(sbuf);
5382 overwrite = (CVAL(pdata,0) ? True : False);
5383 root_fid = IVAL(pdata,4);
5384 len = IVAL(pdata,8);
5386 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5387 return NT_STATUS_INVALID_PARAMETER;
5390 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5391 len, 0, &status,
5392 &dest_has_wcard);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 return status;
5397 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5398 newname));
5400 status = resolve_dfspath_wcard(ctx, conn,
5401 req->flags2 & FLAGS2_DFS_PATHNAMES,
5402 newname,
5403 &newname,
5404 &dest_has_wcard);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 return status;
5409 /* Check the new name has no '/' characters. */
5410 if (strchr_m(newname, '/')) {
5411 return NT_STATUS_NOT_SUPPORTED;
5414 if (fsp && fsp->base_fsp) {
5415 /* newname must be a stream name. */
5416 if (newname[0] != ':') {
5417 return NT_STATUS_NOT_SUPPORTED;
5419 base_name = talloc_asprintf(ctx, "%s%s",
5420 fsp->base_fsp->fsp_name,
5421 newname);
5422 if (!base_name) {
5423 return NT_STATUS_NO_MEMORY;
5425 } else {
5426 /* newname must *not* be a stream name. */
5427 if (is_ntfs_stream_name(newname)) {
5428 return NT_STATUS_NOT_SUPPORTED;
5431 /* Create the base directory. */
5432 base_name = talloc_strdup(ctx, fname);
5433 if (!base_name) {
5434 return NT_STATUS_NO_MEMORY;
5436 p = strrchr_m(base_name, '/');
5437 if (p) {
5438 p[1] = '\0';
5439 } else {
5440 base_name = talloc_strdup(ctx, "./");
5441 if (!base_name) {
5442 return NT_STATUS_NO_MEMORY;
5445 /* Append the new name. */
5446 base_name = talloc_asprintf_append(base_name,
5447 "%s",
5448 newname);
5449 if (!base_name) {
5450 return NT_STATUS_NO_MEMORY;
5453 status = unix_convert(ctx, conn, newname, False,
5454 &newname,
5455 &newname_last_component,
5456 &sbuf);
5458 /* If an error we expect this to be
5459 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5461 if (!NT_STATUS_IS_OK(status)
5462 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5463 status)) {
5464 return status;
5468 if (fsp) {
5469 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5470 fsp->fnum, fsp->fsp_name, base_name ));
5471 status = rename_internals_fsp(conn, fsp, base_name,
5472 newname_last_component, 0,
5473 overwrite);
5474 } else {
5475 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5476 fname, base_name ));
5477 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5478 overwrite, False, dest_has_wcard,
5479 FILE_WRITE_ATTRIBUTES);
5482 return status;
5485 /****************************************************************************
5486 Deal with SMB_SET_POSIX_ACL.
5487 ****************************************************************************/
5489 #if defined(HAVE_POSIX_ACLS)
5490 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5491 const char *pdata,
5492 int total_data,
5493 files_struct *fsp,
5494 const char *fname,
5495 SMB_STRUCT_STAT *psbuf)
5497 uint16 posix_acl_version;
5498 uint16 num_file_acls;
5499 uint16 num_def_acls;
5500 bool valid_file_acls = True;
5501 bool valid_def_acls = True;
5503 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5504 return NT_STATUS_INVALID_PARAMETER;
5506 posix_acl_version = SVAL(pdata,0);
5507 num_file_acls = SVAL(pdata,2);
5508 num_def_acls = SVAL(pdata,4);
5510 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5511 valid_file_acls = False;
5512 num_file_acls = 0;
5515 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5516 valid_def_acls = False;
5517 num_def_acls = 0;
5520 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5521 return NT_STATUS_INVALID_PARAMETER;
5524 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5525 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5526 return NT_STATUS_INVALID_PARAMETER;
5529 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5530 fname ? fname : fsp->fsp_name,
5531 (unsigned int)num_file_acls,
5532 (unsigned int)num_def_acls));
5534 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5535 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5536 return map_nt_error_from_unix(errno);
5539 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5540 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5541 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5542 return map_nt_error_from_unix(errno);
5544 return NT_STATUS_OK;
5546 #endif
5548 /****************************************************************************
5549 Deal with SMB_SET_POSIX_LOCK.
5550 ****************************************************************************/
5552 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5553 struct smb_request *req,
5554 const char *pdata,
5555 int total_data,
5556 files_struct *fsp)
5558 uint64_t count;
5559 uint64_t offset;
5560 uint32 lock_pid;
5561 bool blocking_lock = False;
5562 enum brl_type lock_type;
5564 NTSTATUS status = NT_STATUS_OK;
5566 if (fsp == NULL || fsp->fh->fd == -1) {
5567 return NT_STATUS_INVALID_HANDLE;
5570 if (total_data != POSIX_LOCK_DATA_SIZE) {
5571 return NT_STATUS_INVALID_PARAMETER;
5574 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5575 case POSIX_LOCK_TYPE_READ:
5576 lock_type = READ_LOCK;
5577 break;
5578 case POSIX_LOCK_TYPE_WRITE:
5579 /* Return the right POSIX-mappable error code for files opened read-only. */
5580 if (!fsp->can_write) {
5581 return NT_STATUS_INVALID_HANDLE;
5583 lock_type = WRITE_LOCK;
5584 break;
5585 case POSIX_LOCK_TYPE_UNLOCK:
5586 lock_type = UNLOCK_LOCK;
5587 break;
5588 default:
5589 return NT_STATUS_INVALID_PARAMETER;
5592 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5593 blocking_lock = False;
5594 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5595 blocking_lock = True;
5596 } else {
5597 return NT_STATUS_INVALID_PARAMETER;
5600 if (!lp_blocking_locks(SNUM(conn))) {
5601 blocking_lock = False;
5604 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5605 #if defined(HAVE_LONGLONG)
5606 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5607 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5608 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5609 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5610 #else /* HAVE_LONGLONG */
5611 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5612 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5613 #endif /* HAVE_LONGLONG */
5615 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5616 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5617 fsp->fsp_name,
5618 (unsigned int)lock_type,
5619 (unsigned int)lock_pid,
5620 (double)count,
5621 (double)offset ));
5623 if (lock_type == UNLOCK_LOCK) {
5624 status = do_unlock(smbd_messaging_context(),
5625 fsp,
5626 lock_pid,
5627 count,
5628 offset,
5629 POSIX_LOCK);
5630 } else {
5631 uint32 block_smbpid;
5633 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5634 fsp,
5635 lock_pid,
5636 count,
5637 offset,
5638 lock_type,
5639 POSIX_LOCK,
5640 blocking_lock,
5641 &status,
5642 &block_smbpid,
5643 NULL);
5645 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5647 * A blocking lock was requested. Package up
5648 * this smb into a queued request and push it
5649 * onto the blocking lock queue.
5651 if(push_blocking_lock_request(br_lck,
5652 req,
5653 fsp,
5654 -1, /* infinite timeout. */
5656 lock_pid,
5657 lock_type,
5658 POSIX_LOCK,
5659 offset,
5660 count,
5661 block_smbpid)) {
5662 TALLOC_FREE(br_lck);
5663 return status;
5666 TALLOC_FREE(br_lck);
5669 return status;
5672 /****************************************************************************
5673 Deal with SMB_INFO_STANDARD.
5674 ****************************************************************************/
5676 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5677 const char *pdata,
5678 int total_data,
5679 files_struct *fsp,
5680 const char *fname,
5681 const SMB_STRUCT_STAT *psbuf)
5683 struct smb_file_time ft;
5684 ZERO_STRUCT(ft);
5686 if (total_data < 12) {
5687 return NT_STATUS_INVALID_PARAMETER;
5690 /* create time */
5691 ft.create_time = interpret_long_date(pdata);
5693 /* access time */
5694 ft.atime = interpret_long_date(pdata + 8);
5696 /* write time */
5697 ft.mtime = interpret_long_date(pdata + 16);
5699 DEBUG(10,("smb_set_info_standard: file %s\n",
5700 fname ? fname : fsp->fsp_name ));
5702 return smb_set_file_time(conn,
5703 fsp,
5704 fname,
5705 psbuf,
5706 &ft,
5707 true);
5710 /****************************************************************************
5711 Deal with SMB_SET_FILE_BASIC_INFO.
5712 ****************************************************************************/
5714 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5715 const char *pdata,
5716 int total_data,
5717 files_struct *fsp,
5718 const char *fname,
5719 SMB_STRUCT_STAT *psbuf)
5721 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5722 struct timespec write_time;
5723 struct timespec changed_time;
5724 struct smb_file_time ft;
5725 uint32 dosmode = 0;
5726 NTSTATUS status = NT_STATUS_OK;
5727 bool setting_write_time = true;
5729 ZERO_STRUCT(ft);
5731 if (total_data < 36) {
5732 return NT_STATUS_INVALID_PARAMETER;
5735 /* Set the attributes */
5736 dosmode = IVAL(pdata,32);
5737 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5738 if (!NT_STATUS_IS_OK(status)) {
5739 return status;
5742 /* access time */
5743 ft.atime = interpret_long_date(pdata+8);
5745 write_time = interpret_long_date(pdata+16);
5746 changed_time = interpret_long_date(pdata+24);
5748 /* mtime */
5749 ft.mtime = timespec_min(&write_time, &changed_time);
5751 /* create time */
5752 ft.create_time = interpret_long_date(pdata);
5754 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5755 !null_timespec(write_time)) {
5756 ft.mtime = write_time;
5759 /* Prefer a defined time to an undefined one. */
5760 if (null_timespec(ft.mtime)) {
5761 if (null_timespec(write_time)) {
5762 ft.mtime = changed_time;
5763 setting_write_time = false;
5764 } else {
5765 ft.mtime = write_time;
5769 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5770 fname ? fname : fsp->fsp_name ));
5772 return smb_set_file_time(conn,
5773 fsp,
5774 fname,
5775 psbuf,
5776 &ft,
5777 setting_write_time);
5780 /****************************************************************************
5781 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5782 ****************************************************************************/
5784 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5785 struct smb_request *req,
5786 const char *pdata,
5787 int total_data,
5788 files_struct *fsp,
5789 const char *fname,
5790 SMB_STRUCT_STAT *psbuf)
5792 uint64_t allocation_size = 0;
5793 NTSTATUS status = NT_STATUS_OK;
5794 files_struct *new_fsp = NULL;
5796 if (!VALID_STAT(*psbuf)) {
5797 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5800 if (total_data < 8) {
5801 return NT_STATUS_INVALID_PARAMETER;
5804 allocation_size = (uint64_t)IVAL(pdata,0);
5805 #ifdef LARGE_SMB_OFF_T
5806 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5807 #else /* LARGE_SMB_OFF_T */
5808 if (IVAL(pdata,4) != 0) {
5809 /* more than 32 bits? */
5810 return NT_STATUS_INVALID_PARAMETER;
5812 #endif /* LARGE_SMB_OFF_T */
5814 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5815 fname, (double)allocation_size ));
5817 if (allocation_size) {
5818 allocation_size = smb_roundup(conn, allocation_size);
5821 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5822 fname, (double)allocation_size ));
5824 if (fsp && fsp->fh->fd != -1) {
5825 /* Open file handle. */
5826 /* Only change if needed. */
5827 if (allocation_size != get_file_size_stat(psbuf)) {
5828 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5829 return map_nt_error_from_unix(errno);
5832 /* But always update the time. */
5834 * This is equivalent to a write. Ensure it's seen immediately
5835 * if there are no pending writes.
5837 trigger_write_time_update_immediate(fsp);
5838 return NT_STATUS_OK;
5841 /* Pathname or stat or directory file. */
5843 status = SMB_VFS_CREATE_FILE(
5844 conn, /* conn */
5845 req, /* req */
5846 0, /* root_dir_fid */
5847 fname, /* fname */
5848 0, /* create_file_flags */
5849 FILE_WRITE_DATA, /* access_mask */
5850 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5851 FILE_SHARE_DELETE),
5852 FILE_OPEN, /* create_disposition*/
5853 0, /* create_options */
5854 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5855 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5856 0, /* allocation_size */
5857 NULL, /* sd */
5858 NULL, /* ea_list */
5859 &new_fsp, /* result */
5860 NULL, /* pinfo */
5861 psbuf); /* psbuf */
5863 if (!NT_STATUS_IS_OK(status)) {
5864 /* NB. We check for open_was_deferred in the caller. */
5865 return status;
5868 /* Only change if needed. */
5869 if (allocation_size != get_file_size_stat(psbuf)) {
5870 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5871 status = map_nt_error_from_unix(errno);
5872 close_file(req, new_fsp, NORMAL_CLOSE);
5873 return status;
5877 /* Changing the allocation size should set the last mod time. */
5879 * This is equivalent to a write. Ensure it's seen immediately
5880 * if there are no pending writes.
5882 trigger_write_time_update_immediate(new_fsp);
5884 close_file(req, new_fsp, NORMAL_CLOSE);
5885 return NT_STATUS_OK;
5888 /****************************************************************************
5889 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5890 ****************************************************************************/
5892 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5893 struct smb_request *req,
5894 const char *pdata,
5895 int total_data,
5896 files_struct *fsp,
5897 const char *fname,
5898 SMB_STRUCT_STAT *psbuf)
5900 SMB_OFF_T size;
5902 if (total_data < 8) {
5903 return NT_STATUS_INVALID_PARAMETER;
5906 size = IVAL(pdata,0);
5907 #ifdef LARGE_SMB_OFF_T
5908 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5909 #else /* LARGE_SMB_OFF_T */
5910 if (IVAL(pdata,4) != 0) {
5911 /* more than 32 bits? */
5912 return NT_STATUS_INVALID_PARAMETER;
5914 #endif /* LARGE_SMB_OFF_T */
5915 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5916 "file %s to %.0f\n", fname, (double)size ));
5918 return smb_set_file_size(conn, req,
5919 fsp,
5920 fname,
5921 psbuf,
5922 size);
5925 /****************************************************************************
5926 Allow a UNIX info mknod.
5927 ****************************************************************************/
5929 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5930 const char *pdata,
5931 int total_data,
5932 const char *fname,
5933 SMB_STRUCT_STAT *psbuf)
5935 uint32 file_type = IVAL(pdata,56);
5936 #if defined(HAVE_MAKEDEV)
5937 uint32 dev_major = IVAL(pdata,60);
5938 uint32 dev_minor = IVAL(pdata,68);
5939 #endif
5940 SMB_DEV_T dev = (SMB_DEV_T)0;
5941 uint32 raw_unixmode = IVAL(pdata,84);
5942 NTSTATUS status;
5943 mode_t unixmode;
5945 if (total_data < 100) {
5946 return NT_STATUS_INVALID_PARAMETER;
5949 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5950 if (!NT_STATUS_IS_OK(status)) {
5951 return status;
5954 #if defined(HAVE_MAKEDEV)
5955 dev = makedev(dev_major, dev_minor);
5956 #endif
5958 switch (file_type) {
5959 #if defined(S_IFIFO)
5960 case UNIX_TYPE_FIFO:
5961 unixmode |= S_IFIFO;
5962 break;
5963 #endif
5964 #if defined(S_IFSOCK)
5965 case UNIX_TYPE_SOCKET:
5966 unixmode |= S_IFSOCK;
5967 break;
5968 #endif
5969 #if defined(S_IFCHR)
5970 case UNIX_TYPE_CHARDEV:
5971 unixmode |= S_IFCHR;
5972 break;
5973 #endif
5974 #if defined(S_IFBLK)
5975 case UNIX_TYPE_BLKDEV:
5976 unixmode |= S_IFBLK;
5977 break;
5978 #endif
5979 default:
5980 return NT_STATUS_INVALID_PARAMETER;
5983 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5984 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5986 /* Ok - do the mknod. */
5987 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5988 return map_nt_error_from_unix(errno);
5991 /* If any of the other "set" calls fail we
5992 * don't want to end up with a half-constructed mknod.
5995 if (lp_inherit_perms(SNUM(conn))) {
5996 char *parent;
5997 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5998 return NT_STATUS_NO_MEMORY;
6000 inherit_access_posix_acl(conn, parent, fname, unixmode);
6001 TALLOC_FREE(parent);
6004 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6005 status = map_nt_error_from_unix(errno);
6006 SMB_VFS_UNLINK(conn,fname);
6007 return status;
6009 return NT_STATUS_OK;
6012 /****************************************************************************
6013 Deal with SMB_SET_FILE_UNIX_BASIC.
6014 ****************************************************************************/
6016 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6017 struct smb_request *req,
6018 const char *pdata,
6019 int total_data,
6020 files_struct *fsp,
6021 const char *fname,
6022 SMB_STRUCT_STAT *psbuf)
6024 struct smb_file_time ft;
6025 uint32 raw_unixmode;
6026 mode_t unixmode;
6027 SMB_OFF_T size = 0;
6028 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6029 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6030 NTSTATUS status = NT_STATUS_OK;
6031 bool delete_on_fail = False;
6032 enum perm_type ptype;
6034 ZERO_STRUCT(ft);
6036 if (total_data < 100) {
6037 return NT_STATUS_INVALID_PARAMETER;
6040 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6041 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6042 size=IVAL(pdata,0); /* first 8 Bytes are size */
6043 #ifdef LARGE_SMB_OFF_T
6044 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6045 #else /* LARGE_SMB_OFF_T */
6046 if (IVAL(pdata,4) != 0) {
6047 /* more than 32 bits? */
6048 return NT_STATUS_INVALID_PARAMETER;
6050 #endif /* LARGE_SMB_OFF_T */
6053 ft.atime = interpret_long_date(pdata+24); /* access_time */
6054 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6055 set_owner = (uid_t)IVAL(pdata,40);
6056 set_grp = (gid_t)IVAL(pdata,48);
6057 raw_unixmode = IVAL(pdata,84);
6059 if (VALID_STAT(*psbuf)) {
6060 if (S_ISDIR(psbuf->st_mode)) {
6061 ptype = PERM_EXISTING_DIR;
6062 } else {
6063 ptype = PERM_EXISTING_FILE;
6065 } else {
6066 ptype = PERM_NEW_FILE;
6069 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6070 if (!NT_STATUS_IS_OK(status)) {
6071 return status;
6074 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6075 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6076 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6078 if (!VALID_STAT(*psbuf)) {
6080 * The only valid use of this is to create character and block
6081 * devices, and named pipes. This is deprecated (IMHO) and
6082 * a new info level should be used for mknod. JRA.
6085 status = smb_unix_mknod(conn,
6086 pdata,
6087 total_data,
6088 fname,
6089 psbuf);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 return status;
6094 /* Ensure we don't try and change anything else. */
6095 raw_unixmode = SMB_MODE_NO_CHANGE;
6096 size = get_file_size_stat(psbuf);
6097 ft.atime = get_atimespec(psbuf);
6098 ft.mtime = get_mtimespec(psbuf);
6100 * We continue here as we might want to change the
6101 * owner uid/gid.
6103 delete_on_fail = True;
6106 #if 1
6107 /* Horrible backwards compatibility hack as an old server bug
6108 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6109 * */
6111 if (!size) {
6112 size = get_file_size_stat(psbuf);
6114 #endif
6117 * Deal with the UNIX specific mode set.
6120 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6121 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6122 (unsigned int)unixmode, fname ));
6123 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6124 return map_nt_error_from_unix(errno);
6129 * Deal with the UNIX specific uid set.
6132 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6133 int ret;
6135 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6136 (unsigned int)set_owner, fname ));
6138 if (S_ISLNK(psbuf->st_mode)) {
6139 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6140 } else {
6141 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6144 if (ret != 0) {
6145 status = map_nt_error_from_unix(errno);
6146 if (delete_on_fail) {
6147 SMB_VFS_UNLINK(conn,fname);
6149 return status;
6154 * Deal with the UNIX specific gid set.
6157 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6158 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6159 (unsigned int)set_owner, fname ));
6160 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6161 status = map_nt_error_from_unix(errno);
6162 if (delete_on_fail) {
6163 SMB_VFS_UNLINK(conn,fname);
6165 return status;
6169 /* Deal with any size changes. */
6171 status = smb_set_file_size(conn, req,
6172 fsp,
6173 fname,
6174 psbuf,
6175 size);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 return status;
6180 /* Deal with any time changes. */
6182 return smb_set_file_time(conn,
6183 fsp,
6184 fname,
6185 psbuf,
6186 &ft,
6187 true);
6190 /****************************************************************************
6191 Deal with SMB_SET_FILE_UNIX_INFO2.
6192 ****************************************************************************/
6194 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6195 struct smb_request *req,
6196 const char *pdata,
6197 int total_data,
6198 files_struct *fsp,
6199 const char *fname,
6200 SMB_STRUCT_STAT *psbuf)
6202 NTSTATUS status;
6203 uint32 smb_fflags;
6204 uint32 smb_fmask;
6206 if (total_data < 116) {
6207 return NT_STATUS_INVALID_PARAMETER;
6210 /* Start by setting all the fields that are common between UNIX_BASIC
6211 * and UNIX_INFO2.
6213 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6214 fsp, fname, psbuf);
6215 if (!NT_STATUS_IS_OK(status)) {
6216 return status;
6219 smb_fflags = IVAL(pdata, 108);
6220 smb_fmask = IVAL(pdata, 112);
6222 /* NB: We should only attempt to alter the file flags if the client
6223 * sends a non-zero mask.
6225 if (smb_fmask != 0) {
6226 int stat_fflags = 0;
6228 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6229 &stat_fflags)) {
6230 /* Client asked to alter a flag we don't understand. */
6231 return NT_STATUS_INVALID_PARAMETER;
6234 if (fsp && fsp->fh->fd != -1) {
6235 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6236 return NT_STATUS_NOT_SUPPORTED;
6237 } else {
6238 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6239 return map_nt_error_from_unix(errno);
6244 /* XXX: need to add support for changing the create_time here. You
6245 * can do this for paths on Darwin with setattrlist(2). The right way
6246 * to hook this up is probably by extending the VFS utimes interface.
6249 return NT_STATUS_OK;
6252 /****************************************************************************
6253 Create a directory with POSIX semantics.
6254 ****************************************************************************/
6256 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6257 struct smb_request *req,
6258 char **ppdata,
6259 int total_data,
6260 const char *fname,
6261 SMB_STRUCT_STAT *psbuf,
6262 int *pdata_return_size)
6264 NTSTATUS status = NT_STATUS_OK;
6265 uint32 raw_unixmode = 0;
6266 uint32 mod_unixmode = 0;
6267 mode_t unixmode = (mode_t)0;
6268 files_struct *fsp = NULL;
6269 uint16 info_level_return = 0;
6270 int info;
6271 char *pdata = *ppdata;
6273 if (total_data < 18) {
6274 return NT_STATUS_INVALID_PARAMETER;
6277 raw_unixmode = IVAL(pdata,8);
6278 /* Next 4 bytes are not yet defined. */
6280 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6281 if (!NT_STATUS_IS_OK(status)) {
6282 return status;
6285 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6287 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6288 fname, (unsigned int)unixmode ));
6290 status = SMB_VFS_CREATE_FILE(
6291 conn, /* conn */
6292 req, /* req */
6293 0, /* root_dir_fid */
6294 fname, /* fname */
6295 0, /* create_file_flags */
6296 FILE_READ_ATTRIBUTES, /* access_mask */
6297 FILE_SHARE_NONE, /* share_access */
6298 FILE_CREATE, /* create_disposition*/
6299 FILE_DIRECTORY_FILE, /* create_options */
6300 mod_unixmode, /* file_attributes */
6301 0, /* oplock_request */
6302 0, /* allocation_size */
6303 NULL, /* sd */
6304 NULL, /* ea_list */
6305 &fsp, /* result */
6306 &info, /* pinfo */
6307 psbuf); /* psbuf */
6309 if (NT_STATUS_IS_OK(status)) {
6310 close_file(req, fsp, NORMAL_CLOSE);
6313 info_level_return = SVAL(pdata,16);
6315 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6316 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6317 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6318 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6319 } else {
6320 *pdata_return_size = 12;
6323 /* Realloc the data size */
6324 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6325 if (*ppdata == NULL) {
6326 *pdata_return_size = 0;
6327 return NT_STATUS_NO_MEMORY;
6329 pdata = *ppdata;
6331 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6332 SSVAL(pdata,2,0); /* No fnum. */
6333 SIVAL(pdata,4,info); /* Was directory created. */
6335 switch (info_level_return) {
6336 case SMB_QUERY_FILE_UNIX_BASIC:
6337 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6338 SSVAL(pdata,10,0); /* Padding. */
6339 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6340 break;
6341 case SMB_QUERY_FILE_UNIX_INFO2:
6342 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6343 SSVAL(pdata,10,0); /* Padding. */
6344 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6345 break;
6346 default:
6347 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6348 SSVAL(pdata,10,0); /* Padding. */
6349 break;
6352 return status;
6355 /****************************************************************************
6356 Open/Create a file with POSIX semantics.
6357 ****************************************************************************/
6359 static NTSTATUS smb_posix_open(connection_struct *conn,
6360 struct smb_request *req,
6361 char **ppdata,
6362 int total_data,
6363 const char *fname,
6364 SMB_STRUCT_STAT *psbuf,
6365 int *pdata_return_size)
6367 bool extended_oplock_granted = False;
6368 char *pdata = *ppdata;
6369 uint32 flags = 0;
6370 uint32 wire_open_mode = 0;
6371 uint32 raw_unixmode = 0;
6372 uint32 mod_unixmode = 0;
6373 uint32 create_disp = 0;
6374 uint32 access_mask = 0;
6375 uint32 create_options = 0;
6376 NTSTATUS status = NT_STATUS_OK;
6377 mode_t unixmode = (mode_t)0;
6378 files_struct *fsp = NULL;
6379 int oplock_request = 0;
6380 int info = 0;
6381 uint16 info_level_return = 0;
6383 if (total_data < 18) {
6384 return NT_STATUS_INVALID_PARAMETER;
6387 flags = IVAL(pdata,0);
6388 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6389 if (oplock_request) {
6390 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6393 wire_open_mode = IVAL(pdata,4);
6395 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6396 return smb_posix_mkdir(conn, req,
6397 ppdata,
6398 total_data,
6399 fname,
6400 psbuf,
6401 pdata_return_size);
6404 switch (wire_open_mode & SMB_ACCMODE) {
6405 case SMB_O_RDONLY:
6406 access_mask = FILE_READ_DATA;
6407 break;
6408 case SMB_O_WRONLY:
6409 access_mask = FILE_WRITE_DATA;
6410 break;
6411 case SMB_O_RDWR:
6412 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6413 break;
6414 default:
6415 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6416 (unsigned int)wire_open_mode ));
6417 return NT_STATUS_INVALID_PARAMETER;
6420 wire_open_mode &= ~SMB_ACCMODE;
6422 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6423 create_disp = FILE_CREATE;
6424 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6425 create_disp = FILE_OVERWRITE_IF;
6426 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6427 create_disp = FILE_OPEN_IF;
6428 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6429 create_disp = FILE_OPEN;
6430 } else {
6431 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6432 (unsigned int)wire_open_mode ));
6433 return NT_STATUS_INVALID_PARAMETER;
6436 raw_unixmode = IVAL(pdata,8);
6437 /* Next 4 bytes are not yet defined. */
6439 status = unix_perms_from_wire(conn,
6440 psbuf,
6441 raw_unixmode,
6442 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6443 &unixmode);
6445 if (!NT_STATUS_IS_OK(status)) {
6446 return status;
6449 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6451 if (wire_open_mode & SMB_O_SYNC) {
6452 create_options |= FILE_WRITE_THROUGH;
6454 if (wire_open_mode & SMB_O_APPEND) {
6455 access_mask |= FILE_APPEND_DATA;
6457 if (wire_open_mode & SMB_O_DIRECT) {
6458 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6461 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6462 fname,
6463 (unsigned int)wire_open_mode,
6464 (unsigned int)unixmode ));
6466 status = SMB_VFS_CREATE_FILE(
6467 conn, /* conn */
6468 req, /* req */
6469 0, /* root_dir_fid */
6470 fname, /* fname */
6471 0, /* create_file_flags */
6472 access_mask, /* access_mask */
6473 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6474 FILE_SHARE_DELETE),
6475 create_disp, /* create_disposition*/
6476 0, /* create_options */
6477 mod_unixmode, /* file_attributes */
6478 oplock_request, /* oplock_request */
6479 0, /* allocation_size */
6480 NULL, /* sd */
6481 NULL, /* ea_list */
6482 &fsp, /* result */
6483 &info, /* pinfo */
6484 psbuf); /* psbuf */
6486 if (!NT_STATUS_IS_OK(status)) {
6487 return status;
6490 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6491 extended_oplock_granted = True;
6494 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6495 extended_oplock_granted = True;
6498 info_level_return = SVAL(pdata,16);
6500 /* Allocate the correct return size. */
6502 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6503 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6504 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6505 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6506 } else {
6507 *pdata_return_size = 12;
6510 /* Realloc the data size */
6511 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6512 if (*ppdata == NULL) {
6513 close_file(req, fsp, ERROR_CLOSE);
6514 *pdata_return_size = 0;
6515 return NT_STATUS_NO_MEMORY;
6517 pdata = *ppdata;
6519 if (extended_oplock_granted) {
6520 if (flags & REQUEST_BATCH_OPLOCK) {
6521 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6522 } else {
6523 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6525 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6526 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6527 } else {
6528 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6531 SSVAL(pdata,2,fsp->fnum);
6532 SIVAL(pdata,4,info); /* Was file created etc. */
6534 switch (info_level_return) {
6535 case SMB_QUERY_FILE_UNIX_BASIC:
6536 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6537 SSVAL(pdata,10,0); /* padding. */
6538 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6539 break;
6540 case SMB_QUERY_FILE_UNIX_INFO2:
6541 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6542 SSVAL(pdata,10,0); /* padding. */
6543 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6544 break;
6545 default:
6546 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6547 SSVAL(pdata,10,0); /* padding. */
6548 break;
6550 return NT_STATUS_OK;
6553 /****************************************************************************
6554 Delete a file with POSIX semantics.
6555 ****************************************************************************/
6557 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6558 struct smb_request *req,
6559 const char *pdata,
6560 int total_data,
6561 const char *fname,
6562 SMB_STRUCT_STAT *psbuf)
6564 NTSTATUS status = NT_STATUS_OK;
6565 files_struct *fsp = NULL;
6566 uint16 flags = 0;
6567 char del = 1;
6568 int info = 0;
6569 int create_options = 0;
6570 int i;
6571 struct share_mode_lock *lck = NULL;
6573 if (total_data < 2) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 flags = SVAL(pdata,0);
6579 if (!VALID_STAT(*psbuf)) {
6580 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6583 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6584 !VALID_STAT_OF_DIR(*psbuf)) {
6585 return NT_STATUS_NOT_A_DIRECTORY;
6588 DEBUG(10,("smb_posix_unlink: %s %s\n",
6589 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6590 fname));
6592 if (VALID_STAT_OF_DIR(*psbuf)) {
6593 create_options |= FILE_DIRECTORY_FILE;
6596 status = SMB_VFS_CREATE_FILE(
6597 conn, /* conn */
6598 req, /* req */
6599 0, /* root_dir_fid */
6600 fname, /* fname */
6601 0, /* create_file_flags */
6602 DELETE_ACCESS, /* access_mask */
6603 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6604 FILE_SHARE_DELETE),
6605 FILE_OPEN, /* create_disposition*/
6606 create_options, /* create_options */
6607 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6608 0, /* oplock_request */
6609 0, /* allocation_size */
6610 NULL, /* sd */
6611 NULL, /* ea_list */
6612 &fsp, /* result */
6613 &info, /* pinfo */
6614 psbuf); /* psbuf */
6616 if (!NT_STATUS_IS_OK(status)) {
6617 return status;
6621 * Don't lie to client. If we can't really delete due to
6622 * non-POSIX opens return SHARING_VIOLATION.
6625 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6626 NULL);
6627 if (lck == NULL) {
6628 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6629 "lock for file %s\n", fsp->fsp_name));
6630 close_file(req, fsp, NORMAL_CLOSE);
6631 return NT_STATUS_INVALID_PARAMETER;
6635 * See if others still have the file open. If this is the case, then
6636 * don't delete. If all opens are POSIX delete we can set the delete
6637 * on close disposition.
6639 for (i=0; i<lck->num_share_modes; i++) {
6640 struct share_mode_entry *e = &lck->share_modes[i];
6641 if (is_valid_share_mode_entry(e)) {
6642 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6643 continue;
6645 /* Fail with sharing violation. */
6646 close_file(req, fsp, NORMAL_CLOSE);
6647 TALLOC_FREE(lck);
6648 return NT_STATUS_SHARING_VIOLATION;
6653 * Set the delete on close.
6655 status = smb_set_file_disposition_info(conn,
6656 &del,
6658 fsp,
6659 fname,
6660 psbuf);
6662 if (!NT_STATUS_IS_OK(status)) {
6663 close_file(req, fsp, NORMAL_CLOSE);
6664 TALLOC_FREE(lck);
6665 return status;
6667 TALLOC_FREE(lck);
6668 return close_file(req, fsp, NORMAL_CLOSE);
6671 /****************************************************************************
6672 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6673 ****************************************************************************/
6675 static void call_trans2setfilepathinfo(connection_struct *conn,
6676 struct smb_request *req,
6677 unsigned int tran_call,
6678 char **pparams, int total_params,
6679 char **ppdata, int total_data,
6680 unsigned int max_data_bytes)
6682 char *params = *pparams;
6683 char *pdata = *ppdata;
6684 uint16 info_level;
6685 SMB_STRUCT_STAT sbuf;
6686 char *fname = NULL;
6687 files_struct *fsp = NULL;
6688 NTSTATUS status = NT_STATUS_OK;
6689 int data_return_size = 0;
6690 TALLOC_CTX *ctx = talloc_tos();
6692 if (!params) {
6693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6694 return;
6697 ZERO_STRUCT(sbuf);
6699 if (tran_call == TRANSACT2_SETFILEINFO) {
6700 if (total_params < 4) {
6701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6702 return;
6705 fsp = file_fsp(req, SVAL(params,0));
6706 /* Basic check for non-null fsp. */
6707 if (!check_fsp_open(conn, req, fsp)) {
6708 return;
6710 info_level = SVAL(params,2);
6712 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6713 if (!fname) {
6714 reply_nterror(req, NT_STATUS_NO_MEMORY);
6715 return;
6718 if(fsp->is_directory || fsp->fh->fd == -1) {
6720 * This is actually a SETFILEINFO on a directory
6721 * handle (returned from an NT SMB). NT5.0 seems
6722 * to do this call. JRA.
6724 if (INFO_LEVEL_IS_UNIX(info_level)) {
6725 /* Always do lstat for UNIX calls. */
6726 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6727 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6728 reply_unixerror(req,ERRDOS,ERRbadpath);
6729 return;
6731 } else {
6732 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6733 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6734 reply_unixerror(req,ERRDOS,ERRbadpath);
6735 return;
6738 } else if (fsp->print_file) {
6740 * Doing a DELETE_ON_CLOSE should cancel a print job.
6742 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6743 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6745 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6747 SSVAL(params,0,0);
6748 send_trans2_replies(conn, req, params, 2,
6749 *ppdata, 0,
6750 max_data_bytes);
6751 return;
6752 } else {
6753 reply_unixerror(req, ERRDOS, ERRbadpath);
6754 return;
6756 } else {
6758 * Original code - this is an open file.
6760 if (!check_fsp(conn, req, fsp)) {
6761 return;
6764 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6765 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6766 reply_unixerror(req, ERRDOS, ERRbadfid);
6767 return;
6770 } else {
6771 /* set path info */
6772 if (total_params < 7) {
6773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6774 return;
6777 info_level = SVAL(params,0);
6778 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6779 total_params - 6, STR_TERMINATE,
6780 &status);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 reply_nterror(req, status);
6783 return;
6786 status = resolve_dfspath(ctx, conn,
6787 req->flags2 & FLAGS2_DFS_PATHNAMES,
6788 fname,
6789 &fname);
6790 if (!NT_STATUS_IS_OK(status)) {
6791 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6792 reply_botherror(req,
6793 NT_STATUS_PATH_NOT_COVERED,
6794 ERRSRV, ERRbadpath);
6795 return;
6797 reply_nterror(req, status);
6798 return;
6801 status = unix_convert(ctx, conn, fname, False,
6802 &fname, NULL, &sbuf);
6803 if (!NT_STATUS_IS_OK(status)) {
6804 reply_nterror(req, status);
6805 return;
6808 status = check_name(conn, fname);
6809 if (!NT_STATUS_IS_OK(status)) {
6810 reply_nterror(req, status);
6811 return;
6814 if (INFO_LEVEL_IS_UNIX(info_level)) {
6816 * For CIFS UNIX extensions the target name may not exist.
6819 /* Always do lstat for UNIX calls. */
6820 SMB_VFS_LSTAT(conn,fname,&sbuf);
6822 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6823 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6824 reply_unixerror(req, ERRDOS, ERRbadpath);
6825 return;
6829 if (!CAN_WRITE(conn)) {
6830 reply_doserror(req, ERRSRV, ERRaccess);
6831 return;
6834 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6835 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6836 return;
6839 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6840 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6842 /* Realloc the parameter size */
6843 *pparams = (char *)SMB_REALLOC(*pparams,2);
6844 if (*pparams == NULL) {
6845 reply_nterror(req, NT_STATUS_NO_MEMORY);
6846 return;
6848 params = *pparams;
6850 SSVAL(params,0,0);
6852 switch (info_level) {
6854 case SMB_INFO_STANDARD:
6856 status = smb_set_info_standard(conn,
6857 pdata,
6858 total_data,
6859 fsp,
6860 fname,
6861 &sbuf);
6862 break;
6865 case SMB_INFO_SET_EA:
6867 status = smb_info_set_ea(conn,
6868 pdata,
6869 total_data,
6870 fsp,
6871 fname);
6872 break;
6875 case SMB_SET_FILE_BASIC_INFO:
6876 case SMB_FILE_BASIC_INFORMATION:
6878 status = smb_set_file_basic_info(conn,
6879 pdata,
6880 total_data,
6881 fsp,
6882 fname,
6883 &sbuf);
6884 break;
6887 case SMB_FILE_ALLOCATION_INFORMATION:
6888 case SMB_SET_FILE_ALLOCATION_INFO:
6890 status = smb_set_file_allocation_info(conn, req,
6891 pdata,
6892 total_data,
6893 fsp,
6894 fname,
6895 &sbuf);
6896 break;
6899 case SMB_FILE_END_OF_FILE_INFORMATION:
6900 case SMB_SET_FILE_END_OF_FILE_INFO:
6902 status = smb_set_file_end_of_file_info(conn, req,
6903 pdata,
6904 total_data,
6905 fsp,
6906 fname,
6907 &sbuf);
6908 break;
6911 case SMB_FILE_DISPOSITION_INFORMATION:
6912 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6914 #if 0
6915 /* JRA - We used to just ignore this on a path ?
6916 * Shouldn't this be invalid level on a pathname
6917 * based call ?
6919 if (tran_call != TRANSACT2_SETFILEINFO) {
6920 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6922 #endif
6923 status = smb_set_file_disposition_info(conn,
6924 pdata,
6925 total_data,
6926 fsp,
6927 fname,
6928 &sbuf);
6929 break;
6932 case SMB_FILE_POSITION_INFORMATION:
6934 status = smb_file_position_information(conn,
6935 pdata,
6936 total_data,
6937 fsp);
6938 break;
6941 /* From tridge Samba4 :
6942 * MODE_INFORMATION in setfileinfo (I have no
6943 * idea what "mode information" on a file is - it takes a value of 0,
6944 * 2, 4 or 6. What could it be?).
6947 case SMB_FILE_MODE_INFORMATION:
6949 status = smb_file_mode_information(conn,
6950 pdata,
6951 total_data);
6952 break;
6956 * CIFS UNIX extensions.
6959 case SMB_SET_FILE_UNIX_BASIC:
6961 status = smb_set_file_unix_basic(conn, req,
6962 pdata,
6963 total_data,
6964 fsp,
6965 fname,
6966 &sbuf);
6967 break;
6970 case SMB_SET_FILE_UNIX_INFO2:
6972 status = smb_set_file_unix_info2(conn, req,
6973 pdata,
6974 total_data,
6975 fsp,
6976 fname,
6977 &sbuf);
6978 break;
6981 case SMB_SET_FILE_UNIX_LINK:
6983 if (tran_call != TRANSACT2_SETPATHINFO) {
6984 /* We must have a pathname for this. */
6985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6986 return;
6988 status = smb_set_file_unix_link(conn, req, pdata,
6989 total_data, fname);
6990 break;
6993 case SMB_SET_FILE_UNIX_HLINK:
6995 if (tran_call != TRANSACT2_SETPATHINFO) {
6996 /* We must have a pathname for this. */
6997 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6998 return;
7000 status = smb_set_file_unix_hlink(conn, req,
7001 pdata, total_data,
7002 fname);
7003 break;
7006 case SMB_FILE_RENAME_INFORMATION:
7008 status = smb_file_rename_information(conn, req,
7009 pdata, total_data,
7010 fsp, fname);
7011 break;
7014 #if defined(HAVE_POSIX_ACLS)
7015 case SMB_SET_POSIX_ACL:
7017 status = smb_set_posix_acl(conn,
7018 pdata,
7019 total_data,
7020 fsp,
7021 fname,
7022 &sbuf);
7023 break;
7025 #endif
7027 case SMB_SET_POSIX_LOCK:
7029 if (tran_call != TRANSACT2_SETFILEINFO) {
7030 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7031 return;
7033 status = smb_set_posix_lock(conn, req,
7034 pdata, total_data, fsp);
7035 break;
7038 case SMB_POSIX_PATH_OPEN:
7040 if (tran_call != TRANSACT2_SETPATHINFO) {
7041 /* We must have a pathname for this. */
7042 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7043 return;
7046 status = smb_posix_open(conn, req,
7047 ppdata,
7048 total_data,
7049 fname,
7050 &sbuf,
7051 &data_return_size);
7052 break;
7055 case SMB_POSIX_PATH_UNLINK:
7057 if (tran_call != TRANSACT2_SETPATHINFO) {
7058 /* We must have a pathname for this. */
7059 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7060 return;
7063 status = smb_posix_unlink(conn, req,
7064 pdata,
7065 total_data,
7066 fname,
7067 &sbuf);
7068 break;
7071 default:
7072 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7073 return;
7077 if (!NT_STATUS_IS_OK(status)) {
7078 if (open_was_deferred(req->mid)) {
7079 /* We have re-scheduled this call. */
7080 return;
7082 if (blocking_lock_was_deferred(req->mid)) {
7083 /* We have re-scheduled this call. */
7084 return;
7086 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7087 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7088 ERRSRV, ERRbadpath);
7089 return;
7091 if (info_level == SMB_POSIX_PATH_OPEN) {
7092 reply_openerror(req, status);
7093 return;
7096 reply_nterror(req, status);
7097 return;
7100 SSVAL(params,0,0);
7101 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7102 max_data_bytes);
7104 return;
7107 /****************************************************************************
7108 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7109 ****************************************************************************/
7111 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7112 char **pparams, int total_params,
7113 char **ppdata, int total_data,
7114 unsigned int max_data_bytes)
7116 char *params = *pparams;
7117 char *pdata = *ppdata;
7118 char *directory = NULL;
7119 SMB_STRUCT_STAT sbuf;
7120 NTSTATUS status = NT_STATUS_OK;
7121 struct ea_list *ea_list = NULL;
7122 TALLOC_CTX *ctx = talloc_tos();
7124 if (!CAN_WRITE(conn)) {
7125 reply_doserror(req, ERRSRV, ERRaccess);
7126 return;
7129 if (total_params < 5) {
7130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7131 return;
7134 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7135 total_params - 4, STR_TERMINATE,
7136 &status);
7137 if (!NT_STATUS_IS_OK(status)) {
7138 reply_nterror(req, status);
7139 return;
7142 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7144 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7145 if (!NT_STATUS_IS_OK(status)) {
7146 reply_nterror(req, status);
7147 return;
7150 status = check_name(conn, directory);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7153 reply_nterror(req, status);
7154 return;
7157 /* Any data in this call is an EA list. */
7158 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7159 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7160 return;
7164 * OS/2 workplace shell seems to send SET_EA requests of "null"
7165 * length (4 bytes containing IVAL 4).
7166 * They seem to have no effect. Bug #3212. JRA.
7169 if (total_data != 4) {
7170 if (total_data < 10) {
7171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7172 return;
7175 if (IVAL(pdata,0) > total_data) {
7176 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7177 IVAL(pdata,0), (unsigned int)total_data));
7178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7179 return;
7182 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7183 total_data - 4);
7184 if (!ea_list) {
7185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7186 return;
7189 /* If total_data == 4 Windows doesn't care what values
7190 * are placed in that field, it just ignores them.
7191 * The System i QNTC IBM SMB client puts bad values here,
7192 * so ignore them. */
7194 status = create_directory(conn, req, directory);
7196 if (!NT_STATUS_IS_OK(status)) {
7197 reply_nterror(req, status);
7198 return;
7201 /* Try and set any given EA. */
7202 if (ea_list) {
7203 status = set_ea(conn, NULL, directory, ea_list);
7204 if (!NT_STATUS_IS_OK(status)) {
7205 reply_nterror(req, status);
7206 return;
7210 /* Realloc the parameter and data sizes */
7211 *pparams = (char *)SMB_REALLOC(*pparams,2);
7212 if(*pparams == NULL) {
7213 reply_nterror(req, NT_STATUS_NO_MEMORY);
7214 return;
7216 params = *pparams;
7218 SSVAL(params,0,0);
7220 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7222 return;
7225 /****************************************************************************
7226 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7227 We don't actually do this - we just send a null response.
7228 ****************************************************************************/
7230 static void call_trans2findnotifyfirst(connection_struct *conn,
7231 struct smb_request *req,
7232 char **pparams, int total_params,
7233 char **ppdata, int total_data,
7234 unsigned int max_data_bytes)
7236 char *params = *pparams;
7237 uint16 info_level;
7239 if (total_params < 6) {
7240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7241 return;
7244 info_level = SVAL(params,4);
7245 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7247 switch (info_level) {
7248 case 1:
7249 case 2:
7250 break;
7251 default:
7252 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7253 return;
7256 /* Realloc the parameter and data sizes */
7257 *pparams = (char *)SMB_REALLOC(*pparams,6);
7258 if (*pparams == NULL) {
7259 reply_nterror(req, NT_STATUS_NO_MEMORY);
7260 return;
7262 params = *pparams;
7264 SSVAL(params,0,fnf_handle);
7265 SSVAL(params,2,0); /* No changes */
7266 SSVAL(params,4,0); /* No EA errors */
7268 fnf_handle++;
7270 if(fnf_handle == 0)
7271 fnf_handle = 257;
7273 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7275 return;
7278 /****************************************************************************
7279 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7280 changes). Currently this does nothing.
7281 ****************************************************************************/
7283 static void call_trans2findnotifynext(connection_struct *conn,
7284 struct smb_request *req,
7285 char **pparams, int total_params,
7286 char **ppdata, int total_data,
7287 unsigned int max_data_bytes)
7289 char *params = *pparams;
7291 DEBUG(3,("call_trans2findnotifynext\n"));
7293 /* Realloc the parameter and data sizes */
7294 *pparams = (char *)SMB_REALLOC(*pparams,4);
7295 if (*pparams == NULL) {
7296 reply_nterror(req, NT_STATUS_NO_MEMORY);
7297 return;
7299 params = *pparams;
7301 SSVAL(params,0,0); /* No changes */
7302 SSVAL(params,2,0); /* No EA errors */
7304 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7306 return;
7309 /****************************************************************************
7310 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7311 ****************************************************************************/
7313 static void call_trans2getdfsreferral(connection_struct *conn,
7314 struct smb_request *req,
7315 char **pparams, int total_params,
7316 char **ppdata, int total_data,
7317 unsigned int max_data_bytes)
7319 char *params = *pparams;
7320 char *pathname = NULL;
7321 int reply_size = 0;
7322 int max_referral_level;
7323 NTSTATUS status = NT_STATUS_OK;
7324 TALLOC_CTX *ctx = talloc_tos();
7326 DEBUG(10,("call_trans2getdfsreferral\n"));
7328 if (total_params < 3) {
7329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7330 return;
7333 max_referral_level = SVAL(params,0);
7335 if(!lp_host_msdfs()) {
7336 reply_doserror(req, ERRDOS, ERRbadfunc);
7337 return;
7340 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7341 total_params - 2, STR_TERMINATE);
7342 if (!pathname) {
7343 reply_nterror(req, NT_STATUS_NOT_FOUND);
7344 return;
7346 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7347 ppdata,&status)) < 0) {
7348 reply_nterror(req, status);
7349 return;
7352 SSVAL(req->inbuf, smb_flg2,
7353 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7354 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7356 return;
7359 #define LMCAT_SPL 0x53
7360 #define LMFUNC_GETJOBID 0x60
7362 /****************************************************************************
7363 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7364 ****************************************************************************/
7366 static void call_trans2ioctl(connection_struct *conn,
7367 struct smb_request *req,
7368 char **pparams, int total_params,
7369 char **ppdata, int total_data,
7370 unsigned int max_data_bytes)
7372 char *pdata = *ppdata;
7373 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7375 /* check for an invalid fid before proceeding */
7377 if (!fsp) {
7378 reply_doserror(req, ERRDOS, ERRbadfid);
7379 return;
7382 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7383 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7384 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7385 if (*ppdata == NULL) {
7386 reply_nterror(req, NT_STATUS_NO_MEMORY);
7387 return;
7389 pdata = *ppdata;
7391 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7392 CAN ACCEPT THIS IN UNICODE. JRA. */
7394 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7395 srvstr_push(pdata, req->flags2, pdata + 2,
7396 global_myname(), 15,
7397 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7398 srvstr_push(pdata, req->flags2, pdata+18,
7399 lp_servicename(SNUM(conn)), 13,
7400 STR_ASCII|STR_TERMINATE); /* Service name */
7401 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7402 max_data_bytes);
7403 return;
7406 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7407 reply_doserror(req, ERRSRV, ERRerror);
7410 /****************************************************************************
7411 Reply to a SMBfindclose (stop trans2 directory search).
7412 ****************************************************************************/
7414 void reply_findclose(struct smb_request *req)
7416 int dptr_num;
7418 START_PROFILE(SMBfindclose);
7420 if (req->wct < 1) {
7421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7422 END_PROFILE(SMBfindclose);
7423 return;
7426 dptr_num = SVALS(req->vwv+0, 0);
7428 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7430 dptr_close(&dptr_num);
7432 reply_outbuf(req, 0, 0);
7434 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7436 END_PROFILE(SMBfindclose);
7437 return;
7440 /****************************************************************************
7441 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7442 ****************************************************************************/
7444 void reply_findnclose(struct smb_request *req)
7446 int dptr_num;
7448 START_PROFILE(SMBfindnclose);
7450 if (req->wct < 1) {
7451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7452 END_PROFILE(SMBfindnclose);
7453 return;
7456 dptr_num = SVAL(req->vwv+0, 0);
7458 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7460 /* We never give out valid handles for a
7461 findnotifyfirst - so any dptr_num is ok here.
7462 Just ignore it. */
7464 reply_outbuf(req, 0, 0);
7466 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7468 END_PROFILE(SMBfindnclose);
7469 return;
7472 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7473 struct trans_state *state)
7475 if (Protocol >= PROTOCOL_NT1) {
7476 req->flags2 |= 0x40; /* IS_LONG_NAME */
7477 SSVAL(req->inbuf,smb_flg2,req->flags2);
7480 if (conn->encrypt_level == Required && !req->encrypted) {
7481 if (state->call != TRANSACT2_QFSINFO &&
7482 state->call != TRANSACT2_SETFSINFO) {
7483 DEBUG(0,("handle_trans2: encryption required "
7484 "with call 0x%x\n",
7485 (unsigned int)state->call));
7486 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7487 return;
7491 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7493 /* Now we must call the relevant TRANS2 function */
7494 switch(state->call) {
7495 case TRANSACT2_OPEN:
7497 START_PROFILE(Trans2_open);
7498 call_trans2open(conn, req,
7499 &state->param, state->total_param,
7500 &state->data, state->total_data,
7501 state->max_data_return);
7502 END_PROFILE(Trans2_open);
7503 break;
7506 case TRANSACT2_FINDFIRST:
7508 START_PROFILE(Trans2_findfirst);
7509 call_trans2findfirst(conn, req,
7510 &state->param, state->total_param,
7511 &state->data, state->total_data,
7512 state->max_data_return);
7513 END_PROFILE(Trans2_findfirst);
7514 break;
7517 case TRANSACT2_FINDNEXT:
7519 START_PROFILE(Trans2_findnext);
7520 call_trans2findnext(conn, req,
7521 &state->param, state->total_param,
7522 &state->data, state->total_data,
7523 state->max_data_return);
7524 END_PROFILE(Trans2_findnext);
7525 break;
7528 case TRANSACT2_QFSINFO:
7530 START_PROFILE(Trans2_qfsinfo);
7531 call_trans2qfsinfo(conn, req,
7532 &state->param, state->total_param,
7533 &state->data, state->total_data,
7534 state->max_data_return);
7535 END_PROFILE(Trans2_qfsinfo);
7536 break;
7539 case TRANSACT2_SETFSINFO:
7541 START_PROFILE(Trans2_setfsinfo);
7542 call_trans2setfsinfo(conn, req,
7543 &state->param, state->total_param,
7544 &state->data, state->total_data,
7545 state->max_data_return);
7546 END_PROFILE(Trans2_setfsinfo);
7547 break;
7550 case TRANSACT2_QPATHINFO:
7551 case TRANSACT2_QFILEINFO:
7553 START_PROFILE(Trans2_qpathinfo);
7554 call_trans2qfilepathinfo(conn, req, state->call,
7555 &state->param, state->total_param,
7556 &state->data, state->total_data,
7557 state->max_data_return);
7558 END_PROFILE(Trans2_qpathinfo);
7559 break;
7562 case TRANSACT2_SETPATHINFO:
7563 case TRANSACT2_SETFILEINFO:
7565 START_PROFILE(Trans2_setpathinfo);
7566 call_trans2setfilepathinfo(conn, req, state->call,
7567 &state->param, state->total_param,
7568 &state->data, state->total_data,
7569 state->max_data_return);
7570 END_PROFILE(Trans2_setpathinfo);
7571 break;
7574 case TRANSACT2_FINDNOTIFYFIRST:
7576 START_PROFILE(Trans2_findnotifyfirst);
7577 call_trans2findnotifyfirst(conn, req,
7578 &state->param, state->total_param,
7579 &state->data, state->total_data,
7580 state->max_data_return);
7581 END_PROFILE(Trans2_findnotifyfirst);
7582 break;
7585 case TRANSACT2_FINDNOTIFYNEXT:
7587 START_PROFILE(Trans2_findnotifynext);
7588 call_trans2findnotifynext(conn, req,
7589 &state->param, state->total_param,
7590 &state->data, state->total_data,
7591 state->max_data_return);
7592 END_PROFILE(Trans2_findnotifynext);
7593 break;
7596 case TRANSACT2_MKDIR:
7598 START_PROFILE(Trans2_mkdir);
7599 call_trans2mkdir(conn, req,
7600 &state->param, state->total_param,
7601 &state->data, state->total_data,
7602 state->max_data_return);
7603 END_PROFILE(Trans2_mkdir);
7604 break;
7607 case TRANSACT2_GET_DFS_REFERRAL:
7609 START_PROFILE(Trans2_get_dfs_referral);
7610 call_trans2getdfsreferral(conn, req,
7611 &state->param, state->total_param,
7612 &state->data, state->total_data,
7613 state->max_data_return);
7614 END_PROFILE(Trans2_get_dfs_referral);
7615 break;
7618 case TRANSACT2_IOCTL:
7620 START_PROFILE(Trans2_ioctl);
7621 call_trans2ioctl(conn, req,
7622 &state->param, state->total_param,
7623 &state->data, state->total_data,
7624 state->max_data_return);
7625 END_PROFILE(Trans2_ioctl);
7626 break;
7629 default:
7630 /* Error in request */
7631 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7632 reply_doserror(req, ERRSRV,ERRerror);
7636 /****************************************************************************
7637 Reply to a SMBtrans2.
7638 ****************************************************************************/
7640 void reply_trans2(struct smb_request *req)
7642 connection_struct *conn = req->conn;
7643 unsigned int dsoff;
7644 unsigned int dscnt;
7645 unsigned int psoff;
7646 unsigned int pscnt;
7647 unsigned int tran_call;
7648 struct trans_state *state;
7649 NTSTATUS result;
7651 START_PROFILE(SMBtrans2);
7653 if (req->wct < 14) {
7654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7655 END_PROFILE(SMBtrans2);
7656 return;
7659 dsoff = SVAL(req->vwv+12, 0);
7660 dscnt = SVAL(req->vwv+11, 0);
7661 psoff = SVAL(req->vwv+10, 0);
7662 pscnt = SVAL(req->vwv+9, 0);
7663 tran_call = SVAL(req->vwv+14, 0);
7665 result = allow_new_trans(conn->pending_trans, req->mid);
7666 if (!NT_STATUS_IS_OK(result)) {
7667 DEBUG(2, ("Got invalid trans2 request: %s\n",
7668 nt_errstr(result)));
7669 reply_nterror(req, result);
7670 END_PROFILE(SMBtrans2);
7671 return;
7674 if (IS_IPC(conn)) {
7675 switch (tran_call) {
7676 /* List the allowed trans2 calls on IPC$ */
7677 case TRANSACT2_OPEN:
7678 case TRANSACT2_GET_DFS_REFERRAL:
7679 case TRANSACT2_QFILEINFO:
7680 case TRANSACT2_QFSINFO:
7681 case TRANSACT2_SETFSINFO:
7682 break;
7683 default:
7684 reply_doserror(req, ERRSRV, ERRaccess);
7685 END_PROFILE(SMBtrans2);
7686 return;
7690 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7691 DEBUG(0, ("talloc failed\n"));
7692 reply_nterror(req, NT_STATUS_NO_MEMORY);
7693 END_PROFILE(SMBtrans2);
7694 return;
7697 state->cmd = SMBtrans2;
7699 state->mid = req->mid;
7700 state->vuid = req->vuid;
7701 state->setup_count = SVAL(req->vwv+13, 0);
7702 state->setup = NULL;
7703 state->total_param = SVAL(req->vwv+0, 0);
7704 state->param = NULL;
7705 state->total_data = SVAL(req->vwv+1, 0);
7706 state->data = NULL;
7707 state->max_param_return = SVAL(req->vwv+2, 0);
7708 state->max_data_return = SVAL(req->vwv+3, 0);
7709 state->max_setup_return = SVAL(req->vwv+4, 0);
7710 state->close_on_completion = BITSETW(req->vwv+5, 0);
7711 state->one_way = BITSETW(req->vwv+5, 1);
7713 state->call = tran_call;
7715 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7716 is so as a sanity check */
7717 if (state->setup_count != 1) {
7719 * Need to have rc=0 for ioctl to get job id for OS/2.
7720 * Network printing will fail if function is not successful.
7721 * Similar function in reply.c will be used if protocol
7722 * is LANMAN1.0 instead of LM1.2X002.
7723 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7724 * outbuf doesn't have to be set(only job id is used).
7726 if ( (state->setup_count == 4)
7727 && (tran_call == TRANSACT2_IOCTL)
7728 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7729 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7730 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7731 } else {
7732 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7733 DEBUG(2,("Transaction is %d\n",tran_call));
7734 TALLOC_FREE(state);
7735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7736 END_PROFILE(SMBtrans2);
7737 return;
7741 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7742 goto bad_param;
7744 if (state->total_data) {
7746 if (trans_oob(state->total_data, 0, dscnt)
7747 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7748 goto bad_param;
7751 /* Can't use talloc here, the core routines do realloc on the
7752 * params and data. */
7753 state->data = (char *)SMB_MALLOC(state->total_data);
7754 if (state->data == NULL) {
7755 DEBUG(0,("reply_trans2: data malloc fail for %u "
7756 "bytes !\n", (unsigned int)state->total_data));
7757 TALLOC_FREE(state);
7758 reply_nterror(req, NT_STATUS_NO_MEMORY);
7759 END_PROFILE(SMBtrans2);
7760 return;
7763 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7766 if (state->total_param) {
7768 if (trans_oob(state->total_param, 0, pscnt)
7769 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7770 goto bad_param;
7773 /* Can't use talloc here, the core routines do realloc on the
7774 * params and data. */
7775 state->param = (char *)SMB_MALLOC(state->total_param);
7776 if (state->param == NULL) {
7777 DEBUG(0,("reply_trans: param malloc fail for %u "
7778 "bytes !\n", (unsigned int)state->total_param));
7779 SAFE_FREE(state->data);
7780 TALLOC_FREE(state);
7781 reply_nterror(req, NT_STATUS_NO_MEMORY);
7782 END_PROFILE(SMBtrans2);
7783 return;
7786 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7789 state->received_data = dscnt;
7790 state->received_param = pscnt;
7792 if ((state->received_param == state->total_param) &&
7793 (state->received_data == state->total_data)) {
7795 handle_trans2(conn, req, state);
7797 SAFE_FREE(state->data);
7798 SAFE_FREE(state->param);
7799 TALLOC_FREE(state);
7800 END_PROFILE(SMBtrans2);
7801 return;
7804 DLIST_ADD(conn->pending_trans, state);
7806 /* We need to send an interim response then receive the rest
7807 of the parameter/data bytes */
7808 reply_outbuf(req, 0, 0);
7809 show_msg((char *)req->outbuf);
7810 END_PROFILE(SMBtrans2);
7811 return;
7813 bad_param:
7815 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7816 SAFE_FREE(state->data);
7817 SAFE_FREE(state->param);
7818 TALLOC_FREE(state);
7819 END_PROFILE(SMBtrans2);
7820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7824 /****************************************************************************
7825 Reply to a SMBtranss2
7826 ****************************************************************************/
7828 void reply_transs2(struct smb_request *req)
7830 connection_struct *conn = req->conn;
7831 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7832 struct trans_state *state;
7834 START_PROFILE(SMBtranss2);
7836 show_msg((char *)req->inbuf);
7838 if (req->wct < 8) {
7839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7840 END_PROFILE(SMBtranss2);
7841 return;
7844 for (state = conn->pending_trans; state != NULL;
7845 state = state->next) {
7846 if (state->mid == req->mid) {
7847 break;
7851 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7853 END_PROFILE(SMBtranss2);
7854 return;
7857 /* Revise state->total_param and state->total_data in case they have
7858 changed downwards */
7860 if (SVAL(req->vwv+0, 0) < state->total_param)
7861 state->total_param = SVAL(req->vwv+0, 0);
7862 if (SVAL(req->vwv+1, 0) < state->total_data)
7863 state->total_data = SVAL(req->vwv+1, 0);
7865 pcnt = SVAL(req->vwv+2, 0);
7866 poff = SVAL(req->vwv+3, 0);
7867 pdisp = SVAL(req->vwv+4, 0);
7869 dcnt = SVAL(req->vwv+5, 0);
7870 doff = SVAL(req->vwv+6, 0);
7871 ddisp = SVAL(req->vwv+7, 0);
7873 state->received_param += pcnt;
7874 state->received_data += dcnt;
7876 if ((state->received_data > state->total_data) ||
7877 (state->received_param > state->total_param))
7878 goto bad_param;
7880 if (pcnt) {
7881 if (trans_oob(state->total_param, pdisp, pcnt)
7882 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7883 goto bad_param;
7885 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7888 if (dcnt) {
7889 if (trans_oob(state->total_data, ddisp, dcnt)
7890 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7891 goto bad_param;
7893 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7896 if ((state->received_param < state->total_param) ||
7897 (state->received_data < state->total_data)) {
7898 END_PROFILE(SMBtranss2);
7899 return;
7902 handle_trans2(conn, req, state);
7904 DLIST_REMOVE(conn->pending_trans, state);
7905 SAFE_FREE(state->data);
7906 SAFE_FREE(state->param);
7907 TALLOC_FREE(state);
7909 END_PROFILE(SMBtranss2);
7910 return;
7912 bad_param:
7914 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7915 DLIST_REMOVE(conn->pending_trans, state);
7916 SAFE_FREE(state->data);
7917 SAFE_FREE(state->param);
7918 TALLOC_FREE(state);
7919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7920 END_PROFILE(SMBtranss2);
7921 return;