Fix bug 6867 - trans2findnext returns reply_nterror(req, ntstatus) In a directory...
[Samba.git] / source3 / smbd / trans2.c
blobbf3808e70462370e3e90492f04d9cfc18fffa209
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 char *dname;
1240 bool found = False;
1241 SMB_STRUCT_STAT sbuf;
1242 const char *mask = NULL;
1243 char *pathreal = NULL;
1244 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 TALLOC_FREE(fname);
1321 continue; /* Error - couldn't mangle. */
1323 fname = talloc_strdup(ctx, mangled_name);
1324 if (!fname) {
1325 return False;
1329 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1330 got_match = mask_match(fname, mask, conn->case_sensitive);
1333 if(!got_match && check_mangled_names &&
1334 !mangle_is_8_3(fname, False, conn->params)) {
1336 * It turns out that NT matches wildcards against
1337 * both long *and* short names. This may explain some
1338 * of the wildcard wierdness from old DOS clients
1339 * that some people have been seeing.... JRA.
1341 /* Force the mangling into 8.3. */
1342 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1343 TALLOC_FREE(fname);
1344 continue; /* Error - couldn't mangle. */
1347 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1348 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1352 if (got_match) {
1353 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1355 if (dont_descend && !isdots) {
1356 TALLOC_FREE(fname);
1357 continue;
1360 if (needslash) {
1361 pathreal = NULL;
1362 pathreal = talloc_asprintf(ctx,
1363 "%s/%s",
1364 conn->dirpath,
1365 dname);
1366 } else {
1367 pathreal = talloc_asprintf(ctx,
1368 "%s%s",
1369 conn->dirpath,
1370 dname);
1373 if (!pathreal) {
1374 TALLOC_FREE(fname);
1375 return False;
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1383 TALLOC_FREE(fname);
1384 continue;
1386 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387 /* Needed to show the msdfs symlinks as
1388 * directories */
1390 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391 if (!ms_dfs_link) {
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal,strerror(errno)));
1394 TALLOC_FREE(pathreal);
1395 TALLOC_FREE(fname);
1396 continue;
1400 if (ms_dfs_link) {
1401 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1402 } else {
1403 mode = dos_mode(conn,pathreal,&sbuf);
1406 if (!dir_check_ftype(conn,mode,dirtype)) {
1407 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1408 TALLOC_FREE(pathreal);
1409 TALLOC_FREE(fname);
1410 continue;
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size_stat(&sbuf);
1416 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1418 mdate_ts = get_mtimespec(&sbuf);
1419 adate_ts = get_atimespec(&sbuf);
1420 create_date_ts = get_create_timespec(&sbuf,
1421 lp_fake_dir_create_times(SNUM(conn)));
1423 if (ask_sharemode) {
1424 struct timespec write_time_ts;
1425 struct file_id fileid;
1427 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1428 get_file_infos(fileid, NULL, &write_time_ts);
1429 if (!null_timespec(write_time_ts)) {
1430 mdate_ts = write_time_ts;
1434 if (lp_dos_filetime_resolution(SNUM(conn))) {
1435 dos_filetime_timespec(&create_date_ts);
1436 dos_filetime_timespec(&mdate_ts);
1437 dos_filetime_timespec(&adate_ts);
1440 create_date = convert_timespec_to_time_t(create_date_ts);
1441 mdate = convert_timespec_to_time_t(mdate_ts);
1442 adate = convert_timespec_to_time_t(adate_ts);
1444 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1445 pathreal,fname));
1447 found = True;
1449 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1452 if (!found)
1453 TALLOC_FREE(fname);
1456 p = pdata;
1457 last_entry_ptr = p;
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1465 SIVAL(p,0,reskey);
1466 p += 4;
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1473 SSVAL(p,20,mode);
1474 p += 23;
1475 nameptr = p;
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1481 STR_TERMINATE);
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483 if (len > 2) {
1484 SCVAL(nameptr, -1, len - 2);
1485 } else {
1486 SCVAL(nameptr, -1, 0);
1488 } else {
1489 if (len > 1) {
1490 SCVAL(nameptr, -1, len - 1);
1491 } else {
1492 SCVAL(nameptr, -1, 0);
1495 p += len;
1496 break;
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1501 SIVAL(p,0,reskey);
1502 p += 4;
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1509 SSVAL(p,20,mode);
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1514 p += 27;
1515 nameptr = p - 1;
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 if (len > 2) {
1521 len -= 2;
1522 } else {
1523 len = 0;
1525 } else {
1526 if (len > 1) {
1527 len -= 1;
1528 } else {
1529 len = 0;
1532 SCVAL(nameptr,0,len);
1533 p += len;
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535 break;
1537 case SMB_FIND_EA_LIST:
1539 struct ea_list *file_list = NULL;
1540 size_t ea_len = 0;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if (!name_list) {
1544 return False;
1546 if(requires_resume_key) {
1547 SIVAL(p,0,reskey);
1548 p += 4;
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1555 SSVAL(p,20,mode);
1556 p += 22; /* p now points to the EA area. */
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573 nameptr = p;
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 if (len > 2) {
1579 len -= 2;
1580 } else {
1581 len = 0;
1583 } else {
1584 if (len > 1) {
1585 len -= 1;
1586 } else {
1587 len = 0;
1590 SCVAL(nameptr,0,len);
1591 p += len + 1;
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 break;
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599 p += 4;
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1602 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1603 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1604 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1612 p += 4;
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1620 conn->params)) {
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1628 if (len < 24) {
1629 memset(p + 2 + len,'\0',24 - len);
1631 SSVAL(p, 0, len);
1632 } else {
1633 memset(p,'\0',26);
1635 p += 2 + 24;
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1639 SIVAL(q,0,len);
1640 p += len;
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1644 SIVAL(pdata,0,len);
1645 p = pdata + len;
1646 break;
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650 p += 4;
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1653 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1654 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1655 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,len);
1663 p += 4 + len;
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1667 SIVAL(pdata,0,len);
1668 p = pdata + len;
1669 break;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673 p += 4;
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1676 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1677 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1678 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1686 p +=4;
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1691 SIVAL(q, 0, len);
1692 p += len;
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len);
1698 p = pdata + len;
1699 break;
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703 p += 4;
1704 SIVAL(p,0,reskey); p += 4;
1705 p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1711 SIVAL(p, -4, len);
1712 p += len;
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len);
1717 p = pdata + len;
1718 break;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722 p += 4;
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1725 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1726 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1727 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p +=4;
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q, 0, len);
1744 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1760 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p +=4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 SSVAL(p, 0, len);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 26;
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(q,0,len);
1800 p += len;
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1804 SIVAL(pdata,0,len);
1805 p = pdata + len;
1806 break;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1812 p+= 4;
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1820 NULL, &sbuf);
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE);
1824 } else {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1827 NULL, &sbuf);
1828 nameptr = p;
1829 p += 4;
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1835 p += len;
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1841 p = pdata + len;
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1844 break;
1846 default:
1847 TALLOC_FREE(fname);
1848 return(False);
1851 TALLOC_FREE(fname);
1852 if (PTR_DIFF(p,pdata) > space_remaining) {
1853 /* Move the dirptr back to prev_dirpos */
1854 dptr_SeekDir(conn->dirptr, prev_dirpos);
1855 *out_of_space = True;
1856 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1857 return False; /* Not finished - just out of space */
1860 /* Setup the last entry pointer, as an offset from base_data */
1861 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1862 /* Advance the data pointer to the next slot */
1863 *ppdata = p;
1865 return(found);
1868 /****************************************************************************
1869 Reply to a TRANS2_FINDFIRST.
1870 ****************************************************************************/
1872 static void call_trans2findfirst(connection_struct *conn,
1873 struct smb_request *req,
1874 char **pparams, int total_params,
1875 char **ppdata, int total_data,
1876 unsigned int max_data_bytes)
1878 /* We must be careful here that we don't return more than the
1879 allowed number of data bytes. If this means returning fewer than
1880 maxentries then so be it. We assume that the redirector has
1881 enough room for the fixed number of parameter bytes it has
1882 requested. */
1883 char *params = *pparams;
1884 char *pdata = *ppdata;
1885 char *data_end;
1886 uint32 dirtype;
1887 int maxentries;
1888 uint16 findfirst_flags;
1889 bool close_after_first;
1890 bool close_if_end;
1891 bool requires_resume_key;
1892 int info_level;
1893 char *directory = NULL;
1894 char *mask = NULL;
1895 char *p;
1896 int last_entry_off=0;
1897 int dptr_num = -1;
1898 int numentries = 0;
1899 int i;
1900 bool finished = False;
1901 bool dont_descend = False;
1902 bool out_of_space = False;
1903 int space_remaining;
1904 bool mask_contains_wcard = False;
1905 SMB_STRUCT_STAT sbuf;
1906 struct ea_list *ea_list = NULL;
1907 NTSTATUS ntstatus = NT_STATUS_OK;
1908 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1909 TALLOC_CTX *ctx = talloc_tos();
1911 if (total_params < 13) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913 return;
1916 dirtype = SVAL(params,0);
1917 maxentries = SVAL(params,2);
1918 findfirst_flags = SVAL(params,4);
1919 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1920 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1921 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1922 info_level = SVAL(params,6);
1924 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1925 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1926 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1927 info_level, max_data_bytes));
1929 if (!maxentries) {
1930 /* W2K3 seems to treat zero as 1. */
1931 maxentries = 1;
1934 switch (info_level) {
1935 case SMB_FIND_INFO_STANDARD:
1936 case SMB_FIND_EA_SIZE:
1937 case SMB_FIND_EA_LIST:
1938 case SMB_FIND_FILE_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_NAMES_INFO:
1941 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1942 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1943 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1944 break;
1945 case SMB_FIND_FILE_UNIX:
1946 case SMB_FIND_FILE_UNIX_INFO2:
1947 /* Always use filesystem for UNIX mtime query. */
1948 ask_sharemode = false;
1949 if (!lp_unix_extensions()) {
1950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1951 return;
1953 break;
1954 default:
1955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1956 return;
1959 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1960 params+12, total_params - 12,
1961 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1962 if (!NT_STATUS_IS_OK(ntstatus)) {
1963 reply_nterror(req, ntstatus);
1964 return;
1967 ntstatus = resolve_dfspath_wcard(ctx, conn,
1968 req->flags2 & FLAGS2_DFS_PATHNAMES,
1969 directory,
1970 &directory,
1971 &mask_contains_wcard);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1974 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1975 ERRSRV, ERRbadpath);
1976 return;
1978 reply_nterror(req, ntstatus);
1979 return;
1982 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1985 return;
1988 ntstatus = check_name(conn, directory);
1989 if (!NT_STATUS_IS_OK(ntstatus)) {
1990 reply_nterror(req, ntstatus);
1991 return;
1994 p = strrchr_m(directory,'/');
1995 if(p == NULL) {
1996 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1997 if((directory[0] == '.') && (directory[1] == '\0')) {
1998 mask = talloc_strdup(ctx,"*");
1999 if (!mask) {
2000 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 return;
2003 mask_contains_wcard = True;
2005 directory = talloc_strdup(talloc_tos(), "./");
2006 if (!directory) {
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 return;
2010 } else {
2011 *p = 0;
2014 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2016 if (info_level == SMB_FIND_EA_LIST) {
2017 uint32 ea_size;
2019 if (total_data < 4) {
2020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2021 return;
2024 ea_size = IVAL(pdata,0);
2025 if (ea_size != total_data) {
2026 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2029 return;
2032 if (!lp_ea_support(SNUM(conn))) {
2033 reply_doserror(req, ERRDOS, ERReasnotsupported);
2034 return;
2037 /* Pull out the list of names. */
2038 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2039 if (!ea_list) {
2040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 return;
2045 *ppdata = (char *)SMB_REALLOC(
2046 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047 if(*ppdata == NULL ) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2049 return;
2051 pdata = *ppdata;
2052 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2054 /* Realloc the params space */
2055 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2056 if (*pparams == NULL) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2058 return;
2060 params = *pparams;
2062 /* Save the wildcard match and attribs we are using on this directory -
2063 needed as lanman2 assumes these are being saved between calls */
2065 ntstatus = dptr_create(conn,
2066 directory,
2067 False,
2068 True,
2069 req->smbpid,
2070 mask,
2071 mask_contains_wcard,
2072 dirtype,
2073 &conn->dirptr);
2075 if (!NT_STATUS_IS_OK(ntstatus)) {
2076 reply_nterror(req, ntstatus);
2077 return;
2080 dptr_num = dptr_dnum(conn->dirptr);
2081 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2083 /* Initialize per TRANS2_FIND_FIRST operation data */
2084 dptr_init_search_op(conn->dirptr);
2086 /* We don't need to check for VOL here as this is returned by
2087 a different TRANS2 call. */
2089 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2090 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2091 dont_descend = True;
2093 p = pdata;
2094 space_remaining = max_data_bytes;
2095 out_of_space = False;
2097 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2098 bool got_exact_match = False;
2100 /* this is a heuristic to avoid seeking the dirptr except when
2101 absolutely necessary. It allows for a filename of about 40 chars */
2102 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2103 out_of_space = True;
2104 finished = False;
2105 } else {
2106 finished = !get_lanman2_dir_entry(ctx,
2107 conn,
2108 req->flags2,
2109 mask,dirtype,info_level,
2110 requires_resume_key,dont_descend,
2111 ask_sharemode,
2112 &p,pdata,data_end,
2113 space_remaining, &out_of_space,
2114 &got_exact_match,
2115 &last_entry_off, ea_list);
2118 if (finished && out_of_space)
2119 finished = False;
2121 if (!finished && !out_of_space)
2122 numentries++;
2125 * As an optimisation if we know we aren't looking
2126 * for a wildcard name (ie. the name matches the wildcard exactly)
2127 * then we can finish on any (first) match.
2128 * This speeds up large directory searches. JRA.
2131 if(got_exact_match)
2132 finished = True;
2134 /* Ensure space_remaining never goes -ve. */
2135 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2136 space_remaining = 0;
2137 out_of_space = true;
2138 } else {
2139 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2143 /* Check if we can close the dirptr */
2144 if(close_after_first || (finished && close_if_end)) {
2145 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2146 dptr_close(&dptr_num);
2150 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2151 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2152 * the protocol level is less than NT1. Tested with smbclient. JRA.
2153 * This should fix the OS/2 client bug #2335.
2156 if(numentries == 0) {
2157 dptr_close(&dptr_num);
2158 if (Protocol < PROTOCOL_NT1) {
2159 reply_doserror(req, ERRDOS, ERRnofiles);
2160 return;
2161 } else {
2162 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2163 ERRDOS, ERRbadfile);
2164 return;
2168 /* At this point pdata points to numentries directory entries. */
2170 /* Set up the return parameter block */
2171 SSVAL(params,0,dptr_num);
2172 SSVAL(params,2,numentries);
2173 SSVAL(params,4,finished);
2174 SSVAL(params,6,0); /* Never an EA error */
2175 SSVAL(params,8,last_entry_off);
2177 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2178 max_data_bytes);
2180 if ((! *directory) && dptr_path(dptr_num)) {
2181 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2182 if (!directory) {
2183 reply_nterror(req, NT_STATUS_NO_MEMORY);
2187 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2188 smb_fn_name(req->cmd),
2189 mask, directory, dirtype, numentries ) );
2192 * Force a name mangle here to ensure that the
2193 * mask as an 8.3 name is top of the mangled cache.
2194 * The reasons for this are subtle. Don't remove
2195 * this code unless you know what you are doing
2196 * (see PR#13758). JRA.
2199 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2200 char mangled_name[13];
2201 name_to_8_3(mask, mangled_name, True, conn->params);
2204 return;
2207 /****************************************************************************
2208 Reply to a TRANS2_FINDNEXT.
2209 ****************************************************************************/
2211 static void call_trans2findnext(connection_struct *conn,
2212 struct smb_request *req,
2213 char **pparams, int total_params,
2214 char **ppdata, int total_data,
2215 unsigned int max_data_bytes)
2217 /* We must be careful here that we don't return more than the
2218 allowed number of data bytes. If this means returning fewer than
2219 maxentries then so be it. We assume that the redirector has
2220 enough room for the fixed number of parameter bytes it has
2221 requested. */
2222 char *params = *pparams;
2223 char *pdata = *ppdata;
2224 char *data_end;
2225 int dptr_num;
2226 int maxentries;
2227 uint16 info_level;
2228 uint32 resume_key;
2229 uint16 findnext_flags;
2230 bool close_after_request;
2231 bool close_if_end;
2232 bool requires_resume_key;
2233 bool continue_bit;
2234 bool mask_contains_wcard = False;
2235 char *resume_name = NULL;
2236 const char *mask = NULL;
2237 const char *directory = NULL;
2238 char *p = NULL;
2239 uint16 dirtype;
2240 int numentries = 0;
2241 int i, last_entry_off=0;
2242 bool finished = False;
2243 bool dont_descend = False;
2244 bool out_of_space = False;
2245 int space_remaining;
2246 struct ea_list *ea_list = NULL;
2247 NTSTATUS ntstatus = NT_STATUS_OK;
2248 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2249 TALLOC_CTX *ctx = talloc_tos();
2251 if (total_params < 13) {
2252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253 return;
2256 dptr_num = SVAL(params,0);
2257 maxentries = SVAL(params,2);
2258 info_level = SVAL(params,4);
2259 resume_key = IVAL(params,6);
2260 findnext_flags = SVAL(params,10);
2261 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2262 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2263 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2264 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2266 if (!continue_bit) {
2267 /* We only need resume_name if continue_bit is zero. */
2268 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2269 params+12,
2270 total_params - 12, STR_TERMINATE, &ntstatus,
2271 &mask_contains_wcard);
2272 if (!NT_STATUS_IS_OK(ntstatus)) {
2273 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2274 complain (it thinks we're asking for the directory above the shared
2275 path or an invalid name). Catch this as the resume name is only compared, never used in
2276 a file access. JRA. */
2277 srvstr_pull_talloc(ctx, params, req->flags2,
2278 &resume_name, params+12,
2279 total_params - 12,
2280 STR_TERMINATE);
2282 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2283 reply_nterror(req, ntstatus);
2284 return;
2289 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2290 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2291 resume_key = %d resume name = %s continue=%d level = %d\n",
2292 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2293 requires_resume_key, resume_key,
2294 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2296 if (!maxentries) {
2297 /* W2K3 seems to treat zero as 1. */
2298 maxentries = 1;
2301 switch (info_level) {
2302 case SMB_FIND_INFO_STANDARD:
2303 case SMB_FIND_EA_SIZE:
2304 case SMB_FIND_EA_LIST:
2305 case SMB_FIND_FILE_DIRECTORY_INFO:
2306 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_NAMES_INFO:
2308 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2309 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2310 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2311 break;
2312 case SMB_FIND_FILE_UNIX:
2313 case SMB_FIND_FILE_UNIX_INFO2:
2314 /* Always use filesystem for UNIX mtime query. */
2315 ask_sharemode = false;
2316 if (!lp_unix_extensions()) {
2317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 return;
2320 break;
2321 default:
2322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2323 return;
2326 if (info_level == SMB_FIND_EA_LIST) {
2327 uint32 ea_size;
2329 if (total_data < 4) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 return;
2334 ea_size = IVAL(pdata,0);
2335 if (ea_size != total_data) {
2336 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2337 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2339 return;
2342 if (!lp_ea_support(SNUM(conn))) {
2343 reply_doserror(req, ERRDOS, ERReasnotsupported);
2344 return;
2347 /* Pull out the list of names. */
2348 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2349 if (!ea_list) {
2350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2351 return;
2355 *ppdata = (char *)SMB_REALLOC(
2356 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2357 if(*ppdata == NULL) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 return;
2362 pdata = *ppdata;
2363 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2365 /* Realloc the params space */
2366 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2367 if(*pparams == NULL ) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 return;
2372 params = *pparams;
2374 /* Check that the dptr is valid */
2375 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2376 reply_doserror(req, ERRDOS, ERRnofiles);
2377 return;
2380 string_set(&conn->dirpath,dptr_path(dptr_num));
2382 /* Get the wildcard mask from the dptr */
2383 if((p = dptr_wcard(dptr_num))== NULL) {
2384 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2385 reply_doserror(req, ERRDOS, ERRnofiles);
2386 return;
2389 mask = p;
2390 directory = conn->dirpath;
2392 /* Get the attr mask from the dptr */
2393 dirtype = dptr_attr(dptr_num);
2395 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2396 dptr_num, mask, dirtype,
2397 (long)conn->dirptr,
2398 dptr_TellDir(conn->dirptr)));
2400 /* Initialize per TRANS2_FIND_NEXT operation data */
2401 dptr_init_search_op(conn->dirptr);
2403 /* We don't need to check for VOL here as this is returned by
2404 a different TRANS2 call. */
2406 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2407 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2408 dont_descend = True;
2410 p = pdata;
2411 space_remaining = max_data_bytes;
2412 out_of_space = False;
2415 * Seek to the correct position. We no longer use the resume key but
2416 * depend on the last file name instead.
2419 if(!continue_bit && resume_name && *resume_name) {
2420 SMB_STRUCT_STAT st;
2422 long current_pos = 0;
2424 * Remember, name_to_8_3 is called by
2425 * get_lanman2_dir_entry(), so the resume name
2426 * could be mangled. Ensure we check the unmangled name.
2429 if (mangle_is_mangled(resume_name, conn->params)) {
2430 char *new_resume_name = NULL;
2431 mangle_lookup_name_from_8_3(ctx,
2432 resume_name,
2433 &new_resume_name,
2434 conn->params);
2435 if (new_resume_name) {
2436 resume_name = new_resume_name;
2441 * Fix for NT redirector problem triggered by resume key indexes
2442 * changing between directory scans. We now return a resume key of 0
2443 * and instead look for the filename to continue from (also given
2444 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2445 * findfirst/findnext (as is usual) then the directory pointer
2446 * should already be at the correct place.
2449 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2450 } /* end if resume_name && !continue_bit */
2452 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2453 bool got_exact_match = False;
2455 /* this is a heuristic to avoid seeking the dirptr except when
2456 absolutely necessary. It allows for a filename of about 40 chars */
2457 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2458 out_of_space = True;
2459 finished = False;
2460 } else {
2461 finished = !get_lanman2_dir_entry(ctx,
2462 conn,
2463 req->flags2,
2464 mask,dirtype,info_level,
2465 requires_resume_key,dont_descend,
2466 ask_sharemode,
2467 &p,pdata,data_end,
2468 space_remaining, &out_of_space,
2469 &got_exact_match,
2470 &last_entry_off, ea_list);
2473 if (finished && out_of_space)
2474 finished = False;
2476 if (!finished && !out_of_space)
2477 numentries++;
2480 * As an optimisation if we know we aren't looking
2481 * for a wildcard name (ie. the name matches the wildcard exactly)
2482 * then we can finish on any (first) match.
2483 * This speeds up large directory searches. JRA.
2486 if(got_exact_match)
2487 finished = True;
2489 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2492 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2493 smb_fn_name(req->cmd),
2494 mask, directory, dirtype, numentries ) );
2496 /* Check if we can close the dirptr */
2497 if(close_after_request || (finished && close_if_end)) {
2498 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2499 dptr_close(&dptr_num); /* This frees up the saved mask */
2502 /* Set up the return parameter block */
2503 SSVAL(params,0,numentries);
2504 SSVAL(params,2,finished);
2505 SSVAL(params,4,0); /* Never an EA error */
2506 SSVAL(params,6,last_entry_off);
2508 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2509 max_data_bytes);
2511 return;
2514 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2516 E_md4hash(lp_servicename(SNUM(conn)),objid);
2517 return objid;
2520 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2522 SMB_ASSERT(extended_info != NULL);
2524 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2525 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2526 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2527 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2528 #ifdef SAMBA_VERSION_REVISION
2529 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2530 #endif
2531 extended_info->samba_subversion = 0;
2532 #ifdef SAMBA_VERSION_RC_RELEASE
2533 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2534 #else
2535 #ifdef SAMBA_VERSION_PRE_RELEASE
2536 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2537 #endif
2538 #endif
2539 #ifdef SAMBA_VERSION_VENDOR_PATCH
2540 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2541 #endif
2542 extended_info->samba_gitcommitdate = 0;
2543 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2544 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2545 #endif
2547 memset(extended_info->samba_version_string, 0,
2548 sizeof(extended_info->samba_version_string));
2550 snprintf (extended_info->samba_version_string,
2551 sizeof(extended_info->samba_version_string),
2552 "%s", samba_version_string());
2555 /****************************************************************************
2556 Reply to a TRANS2_QFSINFO (query filesystem info).
2557 ****************************************************************************/
2559 static void call_trans2qfsinfo(connection_struct *conn,
2560 struct smb_request *req,
2561 char **pparams, int total_params,
2562 char **ppdata, int total_data,
2563 unsigned int max_data_bytes)
2565 char *pdata, *end_data;
2566 char *params = *pparams;
2567 uint16 info_level;
2568 int data_len, len;
2569 SMB_STRUCT_STAT st;
2570 const char *vname = volume_label(SNUM(conn));
2571 int snum = SNUM(conn);
2572 char *fstype = lp_fstype(SNUM(conn));
2573 uint32 additional_flags = 0;
2575 if (total_params < 2) {
2576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2577 return;
2580 info_level = SVAL(params,0);
2582 if (IS_IPC(conn)) {
2583 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2584 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2585 "info level (0x%x) on IPC$.\n",
2586 (unsigned int)info_level));
2587 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2588 return;
2592 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2593 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2594 DEBUG(0,("call_trans2qfsinfo: encryption required "
2595 "and info level 0x%x sent.\n",
2596 (unsigned int)info_level));
2597 exit_server_cleanly("encryption required "
2598 "on connection");
2599 return;
2603 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2605 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2606 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2607 reply_doserror(req, ERRSRV, ERRinvdevice);
2608 return;
2611 *ppdata = (char *)SMB_REALLOC(
2612 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2613 if (*ppdata == NULL ) {
2614 reply_nterror(req, NT_STATUS_NO_MEMORY);
2615 return;
2618 pdata = *ppdata;
2619 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2620 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2622 switch (info_level) {
2623 case SMB_INFO_ALLOCATION:
2625 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2626 data_len = 18;
2627 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2628 reply_unixerror(req, ERRHRD, ERRgeneral);
2629 return;
2632 block_size = lp_block_size(snum);
2633 if (bsize < block_size) {
2634 uint64_t factor = block_size/bsize;
2635 bsize = block_size;
2636 dsize /= factor;
2637 dfree /= factor;
2639 if (bsize > block_size) {
2640 uint64_t factor = bsize/block_size;
2641 bsize = block_size;
2642 dsize *= factor;
2643 dfree *= factor;
2645 bytes_per_sector = 512;
2646 sectors_per_unit = bsize/bytes_per_sector;
2648 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2649 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2650 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2652 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2653 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2654 SIVAL(pdata,l1_cUnit,dsize);
2655 SIVAL(pdata,l1_cUnitAvail,dfree);
2656 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2657 break;
2660 case SMB_INFO_VOLUME:
2661 /* Return volume name */
2663 * Add volume serial number - hash of a combination of
2664 * the called hostname and the service name.
2666 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2668 * Win2k3 and previous mess this up by sending a name length
2669 * one byte short. I believe only older clients (OS/2 Win9x) use
2670 * this call so try fixing this by adding a terminating null to
2671 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2673 len = srvstr_push(
2674 pdata, req->flags2,
2675 pdata+l2_vol_szVolLabel, vname,
2676 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2677 STR_NOALIGN|STR_TERMINATE);
2678 SCVAL(pdata,l2_vol_cch,len);
2679 data_len = l2_vol_szVolLabel + len;
2680 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2681 (unsigned)st.st_ctime, len, vname));
2682 break;
2684 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2685 case SMB_FS_ATTRIBUTE_INFORMATION:
2687 additional_flags = 0;
2688 #if defined(HAVE_SYS_QUOTAS)
2689 additional_flags |= FILE_VOLUME_QUOTAS;
2690 #endif
2692 if(lp_nt_acl_support(SNUM(conn))) {
2693 additional_flags |= FILE_PERSISTENT_ACLS;
2696 /* Capabilities are filled in at connection time through STATVFS call */
2697 additional_flags |= conn->fs_capabilities;
2698 additional_flags |= lp_parm_int(conn->params->service,
2699 "share", "fake_fscaps",
2702 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2703 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2704 additional_flags); /* FS ATTRIBUTES */
2706 SIVAL(pdata,4,255); /* Max filename component length */
2707 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2708 and will think we can't do long filenames */
2709 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2710 PTR_DIFF(end_data, pdata+12),
2711 STR_UNICODE);
2712 SIVAL(pdata,8,len);
2713 data_len = 12 + len;
2714 break;
2716 case SMB_QUERY_FS_LABEL_INFO:
2717 case SMB_FS_LABEL_INFORMATION:
2718 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2719 PTR_DIFF(end_data, pdata+4), 0);
2720 data_len = 4 + len;
2721 SIVAL(pdata,0,len);
2722 break;
2724 case SMB_QUERY_FS_VOLUME_INFO:
2725 case SMB_FS_VOLUME_INFORMATION:
2728 * Add volume serial number - hash of a combination of
2729 * the called hostname and the service name.
2731 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2732 (str_checksum(get_local_machine_name())<<16));
2734 /* Max label len is 32 characters. */
2735 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2736 PTR_DIFF(end_data, pdata+18),
2737 STR_UNICODE);
2738 SIVAL(pdata,12,len);
2739 data_len = 18+len;
2741 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2742 (int)strlen(vname),vname, lp_servicename(snum)));
2743 break;
2745 case SMB_QUERY_FS_SIZE_INFO:
2746 case SMB_FS_SIZE_INFORMATION:
2748 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2749 data_len = 24;
2750 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2751 reply_unixerror(req, ERRHRD, ERRgeneral);
2752 return;
2754 block_size = lp_block_size(snum);
2755 if (bsize < block_size) {
2756 uint64_t factor = block_size/bsize;
2757 bsize = block_size;
2758 dsize /= factor;
2759 dfree /= factor;
2761 if (bsize > block_size) {
2762 uint64_t factor = bsize/block_size;
2763 bsize = block_size;
2764 dsize *= factor;
2765 dfree *= factor;
2767 bytes_per_sector = 512;
2768 sectors_per_unit = bsize/bytes_per_sector;
2769 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2770 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2771 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2772 SBIG_UINT(pdata,0,dsize);
2773 SBIG_UINT(pdata,8,dfree);
2774 SIVAL(pdata,16,sectors_per_unit);
2775 SIVAL(pdata,20,bytes_per_sector);
2776 break;
2779 case SMB_FS_FULL_SIZE_INFORMATION:
2781 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2782 data_len = 32;
2783 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2784 reply_unixerror(req, ERRHRD, ERRgeneral);
2785 return;
2787 block_size = lp_block_size(snum);
2788 if (bsize < block_size) {
2789 uint64_t factor = block_size/bsize;
2790 bsize = block_size;
2791 dsize /= factor;
2792 dfree /= factor;
2794 if (bsize > block_size) {
2795 uint64_t factor = bsize/block_size;
2796 bsize = block_size;
2797 dsize *= factor;
2798 dfree *= factor;
2800 bytes_per_sector = 512;
2801 sectors_per_unit = bsize/bytes_per_sector;
2802 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2803 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2804 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2805 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2806 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2807 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2808 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2809 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2810 break;
2813 case SMB_QUERY_FS_DEVICE_INFO:
2814 case SMB_FS_DEVICE_INFORMATION:
2815 data_len = 8;
2816 SIVAL(pdata,0,0); /* dev type */
2817 SIVAL(pdata,4,0); /* characteristics */
2818 break;
2820 #ifdef HAVE_SYS_QUOTAS
2821 case SMB_FS_QUOTA_INFORMATION:
2823 * what we have to send --metze:
2825 * Unknown1: 24 NULL bytes
2826 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2827 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2828 * Quota Flags: 2 byte :
2829 * Unknown3: 6 NULL bytes
2831 * 48 bytes total
2833 * details for Quota Flags:
2835 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2836 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2837 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2838 * 0x0001 Enable Quotas: enable quota for this fs
2842 /* we need to fake up a fsp here,
2843 * because its not send in this call
2845 files_struct fsp;
2846 SMB_NTQUOTA_STRUCT quotas;
2848 ZERO_STRUCT(fsp);
2849 ZERO_STRUCT(quotas);
2851 fsp.conn = conn;
2852 fsp.fnum = -1;
2854 /* access check */
2855 if (conn->server_info->utok.uid != 0) {
2856 DEBUG(0,("set_user_quota: access_denied "
2857 "service [%s] user [%s]\n",
2858 lp_servicename(SNUM(conn)),
2859 conn->server_info->unix_name));
2860 reply_doserror(req, ERRDOS, ERRnoaccess);
2861 return;
2864 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2865 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2866 reply_doserror(req, ERRSRV, ERRerror);
2867 return;
2870 data_len = 48;
2872 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2874 /* Unknown1 24 NULL bytes*/
2875 SBIG_UINT(pdata,0,(uint64_t)0);
2876 SBIG_UINT(pdata,8,(uint64_t)0);
2877 SBIG_UINT(pdata,16,(uint64_t)0);
2879 /* Default Soft Quota 8 bytes */
2880 SBIG_UINT(pdata,24,quotas.softlim);
2882 /* Default Hard Quota 8 bytes */
2883 SBIG_UINT(pdata,32,quotas.hardlim);
2885 /* Quota flag 2 bytes */
2886 SSVAL(pdata,40,quotas.qflags);
2888 /* Unknown3 6 NULL bytes */
2889 SSVAL(pdata,42,0);
2890 SIVAL(pdata,44,0);
2892 break;
2894 #endif /* HAVE_SYS_QUOTAS */
2895 case SMB_FS_OBJECTID_INFORMATION:
2897 unsigned char objid[16];
2898 struct smb_extended_info extended_info;
2899 memcpy(pdata,create_volume_objectid(conn, objid),16);
2900 samba_extended_info_version (&extended_info);
2901 SIVAL(pdata,16,extended_info.samba_magic);
2902 SIVAL(pdata,20,extended_info.samba_version);
2903 SIVAL(pdata,24,extended_info.samba_subversion);
2904 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2905 memcpy(pdata+36,extended_info.samba_version_string,28);
2906 data_len = 64;
2907 break;
2911 * Query the version and capabilities of the CIFS UNIX extensions
2912 * in use.
2915 case SMB_QUERY_CIFS_UNIX_INFO:
2917 bool large_write = lp_min_receive_file_size() &&
2918 !srv_is_signing_active();
2919 bool large_read = !srv_is_signing_active();
2920 int encrypt_caps = 0;
2922 if (!lp_unix_extensions()) {
2923 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2924 return;
2927 switch (conn->encrypt_level) {
2928 case 0:
2929 encrypt_caps = 0;
2930 break;
2931 case 1:
2932 case Auto:
2933 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2934 break;
2935 case Required:
2936 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2937 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2938 large_write = false;
2939 large_read = false;
2940 break;
2943 data_len = 12;
2944 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2945 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2947 /* We have POSIX ACLs, pathname, encryption,
2948 * large read/write, and locking capability. */
2950 SBIG_UINT(pdata,4,((uint64_t)(
2951 CIFS_UNIX_POSIX_ACLS_CAP|
2952 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2953 CIFS_UNIX_FCNTL_LOCKS_CAP|
2954 CIFS_UNIX_EXTATTR_CAP|
2955 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2956 encrypt_caps|
2957 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2958 (large_write ?
2959 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2960 break;
2963 case SMB_QUERY_POSIX_FS_INFO:
2965 int rc;
2966 vfs_statvfs_struct svfs;
2968 if (!lp_unix_extensions()) {
2969 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2970 return;
2973 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2975 if (!rc) {
2976 data_len = 56;
2977 SIVAL(pdata,0,svfs.OptimalTransferSize);
2978 SIVAL(pdata,4,svfs.BlockSize);
2979 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2980 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2981 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2982 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2983 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2984 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2985 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2986 #ifdef EOPNOTSUPP
2987 } else if (rc == EOPNOTSUPP) {
2988 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2989 return;
2990 #endif /* EOPNOTSUPP */
2991 } else {
2992 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2993 reply_doserror(req, ERRSRV, ERRerror);
2994 return;
2996 break;
2999 case SMB_QUERY_POSIX_WHOAMI:
3001 uint32_t flags = 0;
3002 uint32_t sid_bytes;
3003 int i;
3005 if (!lp_unix_extensions()) {
3006 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3007 return;
3010 if (max_data_bytes < 40) {
3011 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3012 return;
3015 /* We ARE guest if global_sid_Builtin_Guests is
3016 * in our list of SIDs.
3018 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3019 conn->server_info->ptok)) {
3020 flags |= SMB_WHOAMI_GUEST;
3023 /* We are NOT guest if global_sid_Authenticated_Users
3024 * is in our list of SIDs.
3026 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3027 conn->server_info->ptok)) {
3028 flags &= ~SMB_WHOAMI_GUEST;
3031 /* NOTE: 8 bytes for UID/GID, irrespective of native
3032 * platform size. This matches
3033 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3035 data_len = 4 /* flags */
3036 + 4 /* flag mask */
3037 + 8 /* uid */
3038 + 8 /* gid */
3039 + 4 /* ngroups */
3040 + 4 /* num_sids */
3041 + 4 /* SID bytes */
3042 + 4 /* pad/reserved */
3043 + (conn->server_info->utok.ngroups * 8)
3044 /* groups list */
3045 + (conn->server_info->ptok->num_sids *
3046 SID_MAX_SIZE)
3047 /* SID list */;
3049 SIVAL(pdata, 0, flags);
3050 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3051 SBIG_UINT(pdata, 8,
3052 (uint64_t)conn->server_info->utok.uid);
3053 SBIG_UINT(pdata, 16,
3054 (uint64_t)conn->server_info->utok.gid);
3057 if (data_len >= max_data_bytes) {
3058 /* Potential overflow, skip the GIDs and SIDs. */
3060 SIVAL(pdata, 24, 0); /* num_groups */
3061 SIVAL(pdata, 28, 0); /* num_sids */
3062 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3063 SIVAL(pdata, 36, 0); /* reserved */
3065 data_len = 40;
3066 break;
3069 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3070 SIVAL(pdata, 28, conn->server_info->num_sids);
3072 /* We walk the SID list twice, but this call is fairly
3073 * infrequent, and I don't expect that it's performance
3074 * sensitive -- jpeach
3076 for (i = 0, sid_bytes = 0;
3077 i < conn->server_info->ptok->num_sids; ++i) {
3078 sid_bytes += ndr_size_dom_sid(
3079 &conn->server_info->ptok->user_sids[i],
3080 NULL,
3084 /* SID list byte count */
3085 SIVAL(pdata, 32, sid_bytes);
3087 /* 4 bytes pad/reserved - must be zero */
3088 SIVAL(pdata, 36, 0);
3089 data_len = 40;
3091 /* GID list */
3092 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3093 SBIG_UINT(pdata, data_len,
3094 (uint64_t)conn->server_info->utok.groups[i]);
3095 data_len += 8;
3098 /* SID list */
3099 for (i = 0;
3100 i < conn->server_info->ptok->num_sids; ++i) {
3101 int sid_len = ndr_size_dom_sid(
3102 &conn->server_info->ptok->user_sids[i],
3103 NULL,
3106 sid_linearize(pdata + data_len, sid_len,
3107 &conn->server_info->ptok->user_sids[i]);
3108 data_len += sid_len;
3111 break;
3114 case SMB_MAC_QUERY_FS_INFO:
3116 * Thursby MAC extension... ONLY on NTFS filesystems
3117 * once we do streams then we don't need this
3119 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3120 data_len = 88;
3121 SIVAL(pdata,84,0x100); /* Don't support mac... */
3122 break;
3124 /* drop through */
3125 default:
3126 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3127 return;
3131 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3132 max_data_bytes);
3134 DEBUG( 4, ( "%s info_level = %d\n",
3135 smb_fn_name(req->cmd), info_level) );
3137 return;
3140 /****************************************************************************
3141 Reply to a TRANS2_SETFSINFO (set filesystem info).
3142 ****************************************************************************/
3144 static void call_trans2setfsinfo(connection_struct *conn,
3145 struct smb_request *req,
3146 char **pparams, int total_params,
3147 char **ppdata, int total_data,
3148 unsigned int max_data_bytes)
3150 char *pdata = *ppdata;
3151 char *params = *pparams;
3152 uint16 info_level;
3154 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3156 /* */
3157 if (total_params < 4) {
3158 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3159 total_params));
3160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3161 return;
3164 info_level = SVAL(params,2);
3166 if (IS_IPC(conn)) {
3167 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3168 info_level != SMB_SET_CIFS_UNIX_INFO) {
3169 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3170 "info level (0x%x) on IPC$.\n",
3171 (unsigned int)info_level));
3172 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3173 return;
3177 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3178 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3179 DEBUG(0,("call_trans2setfsinfo: encryption required "
3180 "and info level 0x%x sent.\n",
3181 (unsigned int)info_level));
3182 exit_server_cleanly("encryption required "
3183 "on connection");
3184 return;
3188 switch(info_level) {
3189 case SMB_SET_CIFS_UNIX_INFO:
3191 uint16 client_unix_major;
3192 uint16 client_unix_minor;
3193 uint32 client_unix_cap_low;
3194 uint32 client_unix_cap_high;
3196 if (!lp_unix_extensions()) {
3197 reply_nterror(req,
3198 NT_STATUS_INVALID_LEVEL);
3199 return;
3202 /* There should be 12 bytes of capabilities set. */
3203 if (total_data < 8) {
3204 reply_nterror(
3205 req,
3206 NT_STATUS_INVALID_PARAMETER);
3207 return;
3209 client_unix_major = SVAL(pdata,0);
3210 client_unix_minor = SVAL(pdata,2);
3211 client_unix_cap_low = IVAL(pdata,4);
3212 client_unix_cap_high = IVAL(pdata,8);
3213 /* Just print these values for now. */
3214 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3215 cap_low = 0x%x, cap_high = 0x%x\n",
3216 (unsigned int)client_unix_major,
3217 (unsigned int)client_unix_minor,
3218 (unsigned int)client_unix_cap_low,
3219 (unsigned int)client_unix_cap_high ));
3221 /* Here is where we must switch to posix pathname processing... */
3222 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3223 lp_set_posix_pathnames();
3224 mangle_change_to_posix();
3227 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3228 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3229 /* Client that knows how to do posix locks,
3230 * but not posix open/mkdir operations. Set a
3231 * default type for read/write checks. */
3233 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3236 break;
3239 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3241 NTSTATUS status;
3242 size_t param_len = 0;
3243 size_t data_len = total_data;
3245 if (!lp_unix_extensions()) {
3246 reply_nterror(
3247 req,
3248 NT_STATUS_INVALID_LEVEL);
3249 return;
3252 if (lp_smb_encrypt(SNUM(conn)) == false) {
3253 reply_nterror(
3254 req,
3255 NT_STATUS_NOT_SUPPORTED);
3256 return;
3259 DEBUG( 4,("call_trans2setfsinfo: "
3260 "request transport encryption.\n"));
3262 status = srv_request_encryption_setup(conn,
3263 (unsigned char **)ppdata,
3264 &data_len,
3265 (unsigned char **)pparams,
3266 &param_len);
3268 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3269 !NT_STATUS_IS_OK(status)) {
3270 reply_nterror(req, status);
3271 return;
3274 send_trans2_replies(conn, req,
3275 *pparams,
3276 param_len,
3277 *ppdata,
3278 data_len,
3279 max_data_bytes);
3281 if (NT_STATUS_IS_OK(status)) {
3282 /* Server-side transport
3283 * encryption is now *on*. */
3284 status = srv_encryption_start(conn);
3285 if (!NT_STATUS_IS_OK(status)) {
3286 exit_server_cleanly(
3287 "Failure in setting "
3288 "up encrypted transport");
3291 return;
3294 case SMB_FS_QUOTA_INFORMATION:
3296 files_struct *fsp = NULL;
3297 SMB_NTQUOTA_STRUCT quotas;
3299 ZERO_STRUCT(quotas);
3301 /* access check */
3302 if ((conn->server_info->utok.uid != 0)
3303 ||!CAN_WRITE(conn)) {
3304 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3305 lp_servicename(SNUM(conn)),
3306 conn->server_info->unix_name));
3307 reply_doserror(req, ERRSRV, ERRaccess);
3308 return;
3311 /* note: normaly there're 48 bytes,
3312 * but we didn't use the last 6 bytes for now
3313 * --metze
3315 fsp = file_fsp(req, SVAL(params,0));
3317 if (!check_fsp_ntquota_handle(conn, req,
3318 fsp)) {
3319 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3320 reply_nterror(
3321 req, NT_STATUS_INVALID_HANDLE);
3322 return;
3325 if (total_data < 42) {
3326 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3327 total_data));
3328 reply_nterror(
3329 req,
3330 NT_STATUS_INVALID_PARAMETER);
3331 return;
3334 /* unknown_1 24 NULL bytes in pdata*/
3336 /* the soft quotas 8 bytes (uint64_t)*/
3337 quotas.softlim = (uint64_t)IVAL(pdata,24);
3338 #ifdef LARGE_SMB_OFF_T
3339 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3340 #else /* LARGE_SMB_OFF_T */
3341 if ((IVAL(pdata,28) != 0)&&
3342 ((quotas.softlim != 0xFFFFFFFF)||
3343 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3344 /* more than 32 bits? */
3345 reply_nterror(
3346 req,
3347 NT_STATUS_INVALID_PARAMETER);
3348 return;
3350 #endif /* LARGE_SMB_OFF_T */
3352 /* the hard quotas 8 bytes (uint64_t)*/
3353 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3354 #ifdef LARGE_SMB_OFF_T
3355 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3356 #else /* LARGE_SMB_OFF_T */
3357 if ((IVAL(pdata,36) != 0)&&
3358 ((quotas.hardlim != 0xFFFFFFFF)||
3359 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3360 /* more than 32 bits? */
3361 reply_nterror(
3362 req,
3363 NT_STATUS_INVALID_PARAMETER);
3364 return;
3366 #endif /* LARGE_SMB_OFF_T */
3368 /* quota_flags 2 bytes **/
3369 quotas.qflags = SVAL(pdata,40);
3371 /* unknown_2 6 NULL bytes follow*/
3373 /* now set the quotas */
3374 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3375 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3376 reply_doserror(req, ERRSRV, ERRerror);
3377 return;
3380 break;
3382 default:
3383 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3384 info_level));
3385 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3386 return;
3387 break;
3391 * sending this reply works fine,
3392 * but I'm not sure it's the same
3393 * like windows do...
3394 * --metze
3396 reply_outbuf(req, 10, 0);
3399 #if defined(HAVE_POSIX_ACLS)
3400 /****************************************************************************
3401 Utility function to count the number of entries in a POSIX acl.
3402 ****************************************************************************/
3404 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3406 unsigned int ace_count = 0;
3407 int entry_id = SMB_ACL_FIRST_ENTRY;
3408 SMB_ACL_ENTRY_T entry;
3410 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3411 /* get_next... */
3412 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3413 entry_id = SMB_ACL_NEXT_ENTRY;
3415 ace_count++;
3417 return ace_count;
3420 /****************************************************************************
3421 Utility function to marshall a POSIX acl into wire format.
3422 ****************************************************************************/
3424 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3426 int entry_id = SMB_ACL_FIRST_ENTRY;
3427 SMB_ACL_ENTRY_T entry;
3429 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3430 SMB_ACL_TAG_T tagtype;
3431 SMB_ACL_PERMSET_T permset;
3432 unsigned char perms = 0;
3433 unsigned int own_grp;
3435 /* get_next... */
3436 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3437 entry_id = SMB_ACL_NEXT_ENTRY;
3440 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3441 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3442 return False;
3445 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3446 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3447 return False;
3450 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3451 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3452 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3454 SCVAL(pdata,1,perms);
3456 switch (tagtype) {
3457 case SMB_ACL_USER_OBJ:
3458 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3459 own_grp = (unsigned int)pst->st_uid;
3460 SIVAL(pdata,2,own_grp);
3461 SIVAL(pdata,6,0);
3462 break;
3463 case SMB_ACL_USER:
3465 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3466 if (!puid) {
3467 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3468 return False;
3470 own_grp = (unsigned int)*puid;
3471 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3472 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3473 SIVAL(pdata,2,own_grp);
3474 SIVAL(pdata,6,0);
3475 break;
3477 case SMB_ACL_GROUP_OBJ:
3478 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3479 own_grp = (unsigned int)pst->st_gid;
3480 SIVAL(pdata,2,own_grp);
3481 SIVAL(pdata,6,0);
3482 break;
3483 case SMB_ACL_GROUP:
3485 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3486 if (!pgid) {
3487 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3488 return False;
3490 own_grp = (unsigned int)*pgid;
3491 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3492 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3493 SIVAL(pdata,2,own_grp);
3494 SIVAL(pdata,6,0);
3495 break;
3497 case SMB_ACL_MASK:
3498 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3499 SIVAL(pdata,2,0xFFFFFFFF);
3500 SIVAL(pdata,6,0xFFFFFFFF);
3501 break;
3502 case SMB_ACL_OTHER:
3503 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3504 SIVAL(pdata,2,0xFFFFFFFF);
3505 SIVAL(pdata,6,0xFFFFFFFF);
3506 break;
3507 default:
3508 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3509 return False;
3511 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3514 return True;
3516 #endif
3518 /****************************************************************************
3519 Store the FILE_UNIX_BASIC info.
3520 ****************************************************************************/
3522 static char *store_file_unix_basic(connection_struct *conn,
3523 char *pdata,
3524 files_struct *fsp,
3525 const SMB_STRUCT_STAT *psbuf)
3527 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3528 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3530 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3531 pdata += 8;
3533 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3534 pdata += 8;
3536 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3537 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3538 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3539 pdata += 24;
3541 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3542 SIVAL(pdata,4,0);
3543 pdata += 8;
3545 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3546 SIVAL(pdata,4,0);
3547 pdata += 8;
3549 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3550 pdata += 4;
3552 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3553 SIVAL(pdata,4,0);
3554 pdata += 8;
3556 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3557 SIVAL(pdata,4,0);
3558 pdata += 8;
3560 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3561 pdata += 8;
3563 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3564 SIVAL(pdata,4,0);
3565 pdata += 8;
3567 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3568 SIVAL(pdata,4,0);
3569 pdata += 8;
3571 return pdata;
3574 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3575 * the chflags(2) (or equivalent) flags.
3577 * XXX: this really should be behind the VFS interface. To do this, we would
3578 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3579 * Each VFS module could then implement its own mapping as appropriate for the
3580 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3582 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3583 info2_flags_map[] =
3585 #ifdef UF_NODUMP
3586 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3587 #endif
3589 #ifdef UF_IMMUTABLE
3590 { UF_IMMUTABLE, EXT_IMMUTABLE },
3591 #endif
3593 #ifdef UF_APPEND
3594 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3595 #endif
3597 #ifdef UF_HIDDEN
3598 { UF_HIDDEN, EXT_HIDDEN },
3599 #endif
3601 /* Do not remove. We need to guarantee that this array has at least one
3602 * entry to build on HP-UX.
3604 { 0, 0 }
3608 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3609 uint32 *smb_fflags, uint32 *smb_fmask)
3611 #ifdef HAVE_STAT_ST_FLAGS
3612 int i;
3614 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3615 *smb_fmask |= info2_flags_map[i].smb_fflag;
3616 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3617 *smb_fflags |= info2_flags_map[i].smb_fflag;
3620 #endif /* HAVE_STAT_ST_FLAGS */
3623 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3624 const uint32 smb_fflags,
3625 const uint32 smb_fmask,
3626 int *stat_fflags)
3628 #ifdef HAVE_STAT_ST_FLAGS
3629 uint32 max_fmask = 0;
3630 int i;
3632 *stat_fflags = psbuf->st_flags;
3634 /* For each flags requested in smb_fmask, check the state of the
3635 * corresponding flag in smb_fflags and set or clear the matching
3636 * stat flag.
3639 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3640 max_fmask |= info2_flags_map[i].smb_fflag;
3641 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3642 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3643 *stat_fflags |= info2_flags_map[i].stat_fflag;
3644 } else {
3645 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3650 /* If smb_fmask is asking to set any bits that are not supported by
3651 * our flag mappings, we should fail.
3653 if ((smb_fmask & max_fmask) != smb_fmask) {
3654 return False;
3657 return True;
3658 #else
3659 return False;
3660 #endif /* HAVE_STAT_ST_FLAGS */
3664 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3665 * of file flags and birth (create) time.
3667 static char *store_file_unix_basic_info2(connection_struct *conn,
3668 char *pdata,
3669 files_struct *fsp,
3670 const SMB_STRUCT_STAT *psbuf)
3672 uint32 file_flags = 0;
3673 uint32 flags_mask = 0;
3675 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3677 /* Create (birth) time 64 bit */
3678 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, get_create_timespec(psbuf, False));
3679 pdata += 8;
3681 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3682 SIVAL(pdata, 0, file_flags); /* flags */
3683 SIVAL(pdata, 4, flags_mask); /* mask */
3684 pdata += 8;
3686 return pdata;
3689 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3690 const struct stream_struct *streams,
3691 char *data,
3692 unsigned int max_data_bytes,
3693 unsigned int *data_size)
3695 unsigned int i;
3696 unsigned int ofs = 0;
3698 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3699 unsigned int next_offset;
3700 size_t namelen;
3701 smb_ucs2_t *namebuf;
3703 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3704 streams[i].name, &namelen) ||
3705 namelen <= 2)
3707 return NT_STATUS_INVALID_PARAMETER;
3711 * name_buf is now null-terminated, we need to marshall as not
3712 * terminated
3715 namelen -= 2;
3717 SIVAL(data, ofs+4, namelen);
3718 SOFF_T(data, ofs+8, streams[i].size);
3719 SOFF_T(data, ofs+16, streams[i].alloc_size);
3720 memcpy(data+ofs+24, namebuf, namelen);
3721 TALLOC_FREE(namebuf);
3723 next_offset = ofs + 24 + namelen;
3725 if (i == num_streams-1) {
3726 SIVAL(data, ofs, 0);
3728 else {
3729 unsigned int align = ndr_align_size(next_offset, 8);
3731 memset(data+next_offset, 0, align);
3732 next_offset += align;
3734 SIVAL(data, ofs, next_offset - ofs);
3735 ofs = next_offset;
3738 ofs = next_offset;
3741 *data_size = ofs;
3743 return NT_STATUS_OK;
3746 /****************************************************************************
3747 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3748 ****************************************************************************/
3750 static void call_trans2qpipeinfo(connection_struct *conn,
3751 struct smb_request *req,
3752 unsigned int tran_call,
3753 char **pparams, int total_params,
3754 char **ppdata, int total_data,
3755 unsigned int max_data_bytes)
3757 char *params = *pparams;
3758 char *pdata = *ppdata;
3759 unsigned int data_size = 0;
3760 unsigned int param_size = 2;
3761 uint16 info_level;
3762 files_struct *fsp;
3764 if (!params) {
3765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3766 return;
3769 if (total_params < 4) {
3770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3771 return;
3774 fsp = file_fsp(req, SVAL(params,0));
3775 if (!fsp_is_np(fsp)) {
3776 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3777 return;
3780 info_level = SVAL(params,2);
3782 *pparams = (char *)SMB_REALLOC(*pparams,2);
3783 if (*pparams == NULL) {
3784 reply_nterror(req, NT_STATUS_NO_MEMORY);
3785 return;
3787 params = *pparams;
3788 SSVAL(params,0,0);
3789 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3790 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3791 if (*ppdata == NULL ) {
3792 reply_nterror(req, NT_STATUS_NO_MEMORY);
3793 return;
3795 pdata = *ppdata;
3797 switch (info_level) {
3798 case SMB_FILE_STANDARD_INFORMATION:
3799 memset(pdata,0,24);
3800 SOFF_T(pdata,0,4096LL);
3801 SIVAL(pdata,16,1);
3802 SIVAL(pdata,20,1);
3803 data_size = 24;
3804 break;
3806 default:
3807 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3808 return;
3811 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3812 max_data_bytes);
3814 return;
3817 /****************************************************************************
3818 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3819 file name or file id).
3820 ****************************************************************************/
3822 static void call_trans2qfilepathinfo(connection_struct *conn,
3823 struct smb_request *req,
3824 unsigned int tran_call,
3825 char **pparams, int total_params,
3826 char **ppdata, int total_data,
3827 unsigned int max_data_bytes)
3829 char *params = *pparams;
3830 char *pdata = *ppdata;
3831 char *dstart, *dend;
3832 uint16 info_level;
3833 int mode=0;
3834 int nlink;
3835 SMB_OFF_T file_size=0;
3836 uint64_t allocation_size=0;
3837 unsigned int data_size = 0;
3838 unsigned int param_size = 2;
3839 SMB_STRUCT_STAT sbuf;
3840 char *dos_fname = NULL;
3841 char *fname = NULL;
3842 char *fullpathname;
3843 char *base_name;
3844 char *p;
3845 SMB_OFF_T pos = 0;
3846 bool delete_pending = False;
3847 int len;
3848 time_t create_time, mtime, atime;
3849 struct timespec create_time_ts, mtime_ts, atime_ts;
3850 struct timespec write_time_ts;
3851 files_struct *fsp = NULL;
3852 struct file_id fileid;
3853 struct ea_list *ea_list = NULL;
3854 char *lock_data = NULL;
3855 bool ms_dfs_link = false;
3856 TALLOC_CTX *ctx = talloc_tos();
3858 if (!params) {
3859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3860 return;
3863 ZERO_STRUCT(sbuf);
3864 ZERO_STRUCT(write_time_ts);
3866 if (tran_call == TRANSACT2_QFILEINFO) {
3867 if (total_params < 4) {
3868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3869 return;
3872 if (IS_IPC(conn)) {
3873 call_trans2qpipeinfo(conn, req, tran_call,
3874 pparams, total_params,
3875 ppdata, total_data,
3876 max_data_bytes);
3877 return;
3880 fsp = file_fsp(req, SVAL(params,0));
3881 info_level = SVAL(params,2);
3883 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3885 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3886 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3887 return;
3890 /* Initial check for valid fsp ptr. */
3891 if (!check_fsp_open(conn, req, fsp)) {
3892 return;
3895 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3896 if (!fname) {
3897 reply_nterror(req, NT_STATUS_NO_MEMORY);
3898 return;
3901 if(fsp->fake_file_handle) {
3903 * This is actually for the QUOTA_FAKE_FILE --metze
3906 /* We know this name is ok, it's already passed the checks. */
3908 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3910 * This is actually a QFILEINFO on a directory
3911 * handle (returned from an NT SMB). NT5.0 seems
3912 * to do this call. JRA.
3915 if (INFO_LEVEL_IS_UNIX(info_level)) {
3916 /* Always do lstat for UNIX calls. */
3917 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3918 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3919 reply_unixerror(req,ERRDOS,ERRbadpath);
3920 return;
3922 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3923 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3924 reply_unixerror(req, ERRDOS, ERRbadpath);
3925 return;
3928 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3929 get_file_infos(fileid, &delete_pending, &write_time_ts);
3930 } else {
3932 * Original code - this is an open file.
3934 if (!check_fsp(conn, req, fsp)) {
3935 return;
3938 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3939 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3940 reply_unixerror(req, ERRDOS, ERRbadfid);
3941 return;
3943 pos = fsp->fh->position_information;
3944 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3945 get_file_infos(fileid, &delete_pending, &write_time_ts);
3948 } else {
3949 NTSTATUS status = NT_STATUS_OK;
3951 /* qpathinfo */
3952 if (total_params < 7) {
3953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3954 return;
3957 info_level = SVAL(params,0);
3959 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3961 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3963 return;
3966 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3967 total_params - 6,
3968 STR_TERMINATE, &status);
3969 if (!NT_STATUS_IS_OK(status)) {
3970 reply_nterror(req, status);
3971 return;
3974 status = resolve_dfspath(ctx,
3975 conn,
3976 req->flags2 & FLAGS2_DFS_PATHNAMES,
3977 fname,
3978 &fname);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3981 reply_botherror(req,
3982 NT_STATUS_PATH_NOT_COVERED,
3983 ERRSRV, ERRbadpath);
3985 reply_nterror(req, status);
3986 return;
3989 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 reply_nterror(req, status);
3992 return;
3994 status = check_name(conn, fname);
3995 if (!NT_STATUS_IS_OK(status)) {
3996 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3997 reply_nterror(req, status);
3998 return;
4001 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4002 && is_ntfs_stream_name(fname)) {
4003 char *base;
4004 SMB_STRUCT_STAT bsbuf;
4006 status = split_ntfs_stream_name(talloc_tos(), fname,
4007 &base, NULL);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 DEBUG(10, ("create_file_unixpath: "
4010 "split_ntfs_stream_name failed: %s\n",
4011 nt_errstr(status)));
4012 reply_nterror(req, status);
4013 return;
4016 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4018 if (INFO_LEVEL_IS_UNIX(info_level)) {
4019 /* Always do lstat for UNIX calls. */
4020 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4021 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4022 reply_unixerror(req,ERRDOS,ERRbadpath);
4023 return;
4025 } else {
4026 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4027 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4028 reply_unixerror(req,ERRDOS,ERRbadpath);
4029 return;
4033 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4034 get_file_infos(fileid, &delete_pending, NULL);
4035 if (delete_pending) {
4036 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4037 return;
4041 if (INFO_LEVEL_IS_UNIX(info_level)) {
4042 /* Always do lstat for UNIX calls. */
4043 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4044 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4045 reply_unixerror(req, ERRDOS, ERRbadpath);
4046 return;
4049 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4050 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4052 if (!ms_dfs_link) {
4053 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4054 reply_unixerror(req, ERRDOS, ERRbadpath);
4055 return;
4059 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4060 get_file_infos(fileid, &delete_pending, &write_time_ts);
4061 if (delete_pending) {
4062 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4063 return;
4067 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4068 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4069 return;
4072 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4073 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4075 p = strrchr_m(fname,'/');
4076 if (!p)
4077 base_name = fname;
4078 else
4079 base_name = p+1;
4081 if (ms_dfs_link) {
4082 mode = dos_mode_msdfs(conn,fname,&sbuf);
4083 } else {
4084 mode = dos_mode(conn,fname,&sbuf);
4086 if (!mode)
4087 mode = FILE_ATTRIBUTE_NORMAL;
4089 nlink = sbuf.st_nlink;
4091 if (nlink && (mode&aDIR)) {
4092 nlink = 1;
4095 if ((nlink > 0) && delete_pending) {
4096 nlink -= 1;
4099 fullpathname = fname;
4100 if (!(mode & aDIR))
4101 file_size = get_file_size_stat(&sbuf);
4103 /* Pull out any data sent here before we realloc. */
4104 switch (info_level) {
4105 case SMB_INFO_QUERY_EAS_FROM_LIST:
4107 /* Pull any EA list from the data portion. */
4108 uint32 ea_size;
4110 if (total_data < 4) {
4111 reply_nterror(
4112 req, NT_STATUS_INVALID_PARAMETER);
4113 return;
4115 ea_size = IVAL(pdata,0);
4117 if (total_data > 0 && ea_size != total_data) {
4118 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4119 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4120 reply_nterror(
4121 req, NT_STATUS_INVALID_PARAMETER);
4122 return;
4125 if (!lp_ea_support(SNUM(conn))) {
4126 reply_doserror(req, ERRDOS,
4127 ERReasnotsupported);
4128 return;
4131 /* Pull out the list of names. */
4132 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4133 if (!ea_list) {
4134 reply_nterror(
4135 req, NT_STATUS_INVALID_PARAMETER);
4136 return;
4138 break;
4141 case SMB_QUERY_POSIX_LOCK:
4143 if (fsp == NULL || fsp->fh->fd == -1) {
4144 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4145 return;
4148 if (total_data != POSIX_LOCK_DATA_SIZE) {
4149 reply_nterror(
4150 req, NT_STATUS_INVALID_PARAMETER);
4151 return;
4154 /* Copy the lock range data. */
4155 lock_data = (char *)TALLOC_MEMDUP(
4156 ctx, pdata, total_data);
4157 if (!lock_data) {
4158 reply_nterror(req, NT_STATUS_NO_MEMORY);
4159 return;
4162 default:
4163 break;
4166 *pparams = (char *)SMB_REALLOC(*pparams,2);
4167 if (*pparams == NULL) {
4168 reply_nterror(req, NT_STATUS_NO_MEMORY);
4169 return;
4171 params = *pparams;
4172 SSVAL(params,0,0);
4173 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4174 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4175 if (*ppdata == NULL ) {
4176 reply_nterror(req, NT_STATUS_NO_MEMORY);
4177 return;
4179 pdata = *ppdata;
4180 dstart = pdata;
4181 dend = dstart + data_size - 1;
4183 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4184 mtime_ts = get_mtimespec(&sbuf);
4185 atime_ts = get_atimespec(&sbuf);
4187 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4189 if (!fsp) {
4190 /* Do we have this path open ? */
4191 files_struct *fsp1;
4192 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4193 fsp1 = file_find_di_first(fileid);
4194 if (fsp1 && fsp1->initial_allocation_size) {
4195 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4199 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4200 mtime_ts = write_time_ts;
4203 if (lp_dos_filetime_resolution(SNUM(conn))) {
4204 dos_filetime_timespec(&create_time_ts);
4205 dos_filetime_timespec(&mtime_ts);
4206 dos_filetime_timespec(&atime_ts);
4209 create_time = convert_timespec_to_time_t(create_time_ts);
4210 mtime = convert_timespec_to_time_t(mtime_ts);
4211 atime = convert_timespec_to_time_t(atime_ts);
4213 /* NT expects the name to be in an exact form of the *full*
4214 filename. See the trans2 torture test */
4215 if (ISDOT(base_name)) {
4216 dos_fname = talloc_strdup(ctx, "\\");
4217 if (!dos_fname) {
4218 reply_nterror(req, NT_STATUS_NO_MEMORY);
4219 return;
4221 } else {
4222 dos_fname = talloc_asprintf(ctx,
4223 "\\%s",
4224 fname);
4225 if (!dos_fname) {
4226 reply_nterror(req, NT_STATUS_NO_MEMORY);
4227 return;
4229 string_replace(dos_fname, '/', '\\');
4232 switch (info_level) {
4233 case SMB_INFO_STANDARD:
4234 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4235 data_size = 22;
4236 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4237 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4238 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4239 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4240 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4241 SSVAL(pdata,l1_attrFile,mode);
4242 break;
4244 case SMB_INFO_QUERY_EA_SIZE:
4246 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4247 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4248 data_size = 26;
4249 srv_put_dos_date2(pdata,0,create_time);
4250 srv_put_dos_date2(pdata,4,atime);
4251 srv_put_dos_date2(pdata,8,mtime); /* write time */
4252 SIVAL(pdata,12,(uint32)file_size);
4253 SIVAL(pdata,16,(uint32)allocation_size);
4254 SSVAL(pdata,20,mode);
4255 SIVAL(pdata,22,ea_size);
4256 break;
4259 case SMB_INFO_IS_NAME_VALID:
4260 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4261 if (tran_call == TRANSACT2_QFILEINFO) {
4262 /* os/2 needs this ? really ?*/
4263 reply_doserror(req, ERRDOS, ERRbadfunc);
4264 return;
4266 data_size = 0;
4267 param_size = 0;
4268 break;
4270 case SMB_INFO_QUERY_EAS_FROM_LIST:
4272 size_t total_ea_len = 0;
4273 struct ea_list *ea_file_list = NULL;
4275 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4277 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4278 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4280 if (!ea_list || (total_ea_len > data_size)) {
4281 data_size = 4;
4282 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4283 break;
4286 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4287 break;
4290 case SMB_INFO_QUERY_ALL_EAS:
4292 /* We have data_size bytes to put EA's into. */
4293 size_t total_ea_len = 0;
4295 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4297 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4298 if (!ea_list || (total_ea_len > data_size)) {
4299 data_size = 4;
4300 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4301 break;
4304 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4305 break;
4308 case SMB_FILE_BASIC_INFORMATION:
4309 case SMB_QUERY_FILE_BASIC_INFO:
4311 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4312 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4313 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4314 } else {
4315 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4316 data_size = 40;
4317 SIVAL(pdata,36,0);
4319 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4320 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4321 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4322 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4323 SIVAL(pdata,32,mode);
4325 DEBUG(5,("SMB_QFBI - "));
4326 DEBUG(5,("create: %s ", ctime(&create_time)));
4327 DEBUG(5,("access: %s ", ctime(&atime)));
4328 DEBUG(5,("write: %s ", ctime(&mtime)));
4329 DEBUG(5,("change: %s ", ctime(&mtime)));
4330 DEBUG(5,("mode: %x\n", mode));
4331 break;
4333 case SMB_FILE_STANDARD_INFORMATION:
4334 case SMB_QUERY_FILE_STANDARD_INFO:
4336 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4337 data_size = 24;
4338 SOFF_T(pdata,0,allocation_size);
4339 SOFF_T(pdata,8,file_size);
4340 SIVAL(pdata,16,nlink);
4341 SCVAL(pdata,20,delete_pending?1:0);
4342 SCVAL(pdata,21,(mode&aDIR)?1:0);
4343 SSVAL(pdata,22,0); /* Padding. */
4344 break;
4346 case SMB_FILE_EA_INFORMATION:
4347 case SMB_QUERY_FILE_EA_INFO:
4349 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4350 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4351 data_size = 4;
4352 SIVAL(pdata,0,ea_size);
4353 break;
4356 /* Get the 8.3 name - used if NT SMB was negotiated. */
4357 case SMB_QUERY_FILE_ALT_NAME_INFO:
4358 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4360 char mangled_name[13];
4361 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4362 if (!name_to_8_3(base_name,mangled_name,
4363 True,conn->params)) {
4364 reply_nterror(
4365 req,
4366 NT_STATUS_NO_MEMORY);
4368 len = srvstr_push(dstart, req->flags2,
4369 pdata+4, mangled_name,
4370 PTR_DIFF(dend, pdata+4),
4371 STR_UNICODE);
4372 data_size = 4 + len;
4373 SIVAL(pdata,0,len);
4374 break;
4377 case SMB_QUERY_FILE_NAME_INFO:
4379 this must be *exactly* right for ACLs on mapped drives to work
4381 len = srvstr_push(dstart, req->flags2,
4382 pdata+4, dos_fname,
4383 PTR_DIFF(dend, pdata+4),
4384 STR_UNICODE);
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4386 data_size = 4 + len;
4387 SIVAL(pdata,0,len);
4388 break;
4390 case SMB_FILE_ALLOCATION_INFORMATION:
4391 case SMB_QUERY_FILE_ALLOCATION_INFO:
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4393 data_size = 8;
4394 SOFF_T(pdata,0,allocation_size);
4395 break;
4397 case SMB_FILE_END_OF_FILE_INFORMATION:
4398 case SMB_QUERY_FILE_END_OF_FILEINFO:
4399 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4400 data_size = 8;
4401 SOFF_T(pdata,0,file_size);
4402 break;
4404 case SMB_QUERY_FILE_ALL_INFO:
4405 case SMB_FILE_ALL_INFORMATION:
4407 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4408 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4409 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4410 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4411 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4412 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4413 SIVAL(pdata,32,mode);
4414 SIVAL(pdata,36,0); /* padding. */
4415 pdata += 40;
4416 SOFF_T(pdata,0,allocation_size);
4417 SOFF_T(pdata,8,file_size);
4418 SIVAL(pdata,16,nlink);
4419 SCVAL(pdata,20,delete_pending);
4420 SCVAL(pdata,21,(mode&aDIR)?1:0);
4421 SSVAL(pdata,22,0);
4422 pdata += 24;
4423 SIVAL(pdata,0,ea_size);
4424 pdata += 4; /* EA info */
4425 len = srvstr_push(dstart, req->flags2,
4426 pdata+4, dos_fname,
4427 PTR_DIFF(dend, pdata+4),
4428 STR_UNICODE);
4429 SIVAL(pdata,0,len);
4430 pdata += 4 + len;
4431 data_size = PTR_DIFF(pdata,(*ppdata));
4432 break;
4434 case SMB_FILE_INTERNAL_INFORMATION:
4435 /* This should be an index number - looks like
4436 dev/ino to me :-)
4438 I think this causes us to fail the IFSKIT
4439 BasicFileInformationTest. -tpot */
4441 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4442 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4443 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4444 data_size = 8;
4445 break;
4447 case SMB_FILE_ACCESS_INFORMATION:
4448 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4449 if (fsp) {
4450 SIVAL(pdata,0,fsp->access_mask);
4451 } else {
4452 /* GENERIC_EXECUTE mapping from Windows */
4453 SIVAL(pdata,0,0x12019F);
4455 data_size = 4;
4456 break;
4458 case SMB_FILE_NAME_INFORMATION:
4459 /* Pathname with leading '\'. */
4461 size_t byte_len;
4462 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4464 SIVAL(pdata,0,byte_len);
4465 data_size = 4 + byte_len;
4466 break;
4469 case SMB_FILE_DISPOSITION_INFORMATION:
4470 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4471 data_size = 1;
4472 SCVAL(pdata,0,delete_pending);
4473 break;
4475 case SMB_FILE_POSITION_INFORMATION:
4476 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4477 data_size = 8;
4478 SOFF_T(pdata,0,pos);
4479 break;
4481 case SMB_FILE_MODE_INFORMATION:
4482 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4483 SIVAL(pdata,0,mode);
4484 data_size = 4;
4485 break;
4487 case SMB_FILE_ALIGNMENT_INFORMATION:
4488 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4489 SIVAL(pdata,0,0); /* No alignment needed. */
4490 data_size = 4;
4491 break;
4494 * NT4 server just returns "invalid query" to this - if we try
4495 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4496 * want this. JRA.
4498 /* The first statement above is false - verified using Thursby
4499 * client against NT4 -- gcolley.
4501 case SMB_QUERY_FILE_STREAM_INFO:
4502 case SMB_FILE_STREAM_INFORMATION: {
4503 unsigned int num_streams;
4504 struct stream_struct *streams;
4505 NTSTATUS status;
4507 DEBUG(10,("call_trans2qfilepathinfo: "
4508 "SMB_FILE_STREAM_INFORMATION\n"));
4510 status = SMB_VFS_STREAMINFO(
4511 conn, fsp, fname, talloc_tos(),
4512 &num_streams, &streams);
4514 if (!NT_STATUS_IS_OK(status)) {
4515 DEBUG(10, ("could not get stream info: %s\n",
4516 nt_errstr(status)));
4517 reply_nterror(req, status);
4518 return;
4521 status = marshall_stream_info(num_streams, streams,
4522 pdata, max_data_bytes,
4523 &data_size);
4525 if (!NT_STATUS_IS_OK(status)) {
4526 DEBUG(10, ("marshall_stream_info failed: %s\n",
4527 nt_errstr(status)));
4528 reply_nterror(req, status);
4529 return;
4532 TALLOC_FREE(streams);
4534 break;
4536 case SMB_QUERY_COMPRESSION_INFO:
4537 case SMB_FILE_COMPRESSION_INFORMATION:
4538 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4539 SOFF_T(pdata,0,file_size);
4540 SIVAL(pdata,8,0); /* ??? */
4541 SIVAL(pdata,12,0); /* ??? */
4542 data_size = 16;
4543 break;
4545 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4546 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4547 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4548 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4549 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4550 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4551 SOFF_T(pdata,32,allocation_size);
4552 SOFF_T(pdata,40,file_size);
4553 SIVAL(pdata,48,mode);
4554 SIVAL(pdata,52,0); /* ??? */
4555 data_size = 56;
4556 break;
4558 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4559 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4560 SIVAL(pdata,0,mode);
4561 SIVAL(pdata,4,0);
4562 data_size = 8;
4563 break;
4566 * CIFS UNIX Extensions.
4569 case SMB_QUERY_FILE_UNIX_BASIC:
4571 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4572 data_size = PTR_DIFF(pdata,(*ppdata));
4575 int i;
4576 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4578 for (i=0; i<100; i++)
4579 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4580 DEBUG(4,("\n"));
4583 break;
4585 case SMB_QUERY_FILE_UNIX_INFO2:
4587 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4588 data_size = PTR_DIFF(pdata,(*ppdata));
4591 int i;
4592 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4594 for (i=0; i<100; i++)
4595 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4596 DEBUG(4,("\n"));
4599 break;
4601 case SMB_QUERY_FILE_UNIX_LINK:
4603 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4605 if (!buffer) {
4606 reply_nterror(req, NT_STATUS_NO_MEMORY);
4607 return;
4610 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4611 #ifdef S_ISLNK
4612 if(!S_ISLNK(sbuf.st_mode)) {
4613 reply_unixerror(req, ERRSRV,
4614 ERRbadlink);
4615 return;
4617 #else
4618 reply_unixerror(req, ERRDOS, ERRbadlink);
4619 return;
4620 #endif
4621 len = SMB_VFS_READLINK(conn,fullpathname,
4622 buffer, PATH_MAX);
4623 if (len == -1) {
4624 reply_unixerror(req, ERRDOS,
4625 ERRnoaccess);
4626 return;
4628 buffer[len] = 0;
4629 len = srvstr_push(dstart, req->flags2,
4630 pdata, buffer,
4631 PTR_DIFF(dend, pdata),
4632 STR_TERMINATE);
4633 pdata += len;
4634 data_size = PTR_DIFF(pdata,(*ppdata));
4636 break;
4639 #if defined(HAVE_POSIX_ACLS)
4640 case SMB_QUERY_POSIX_ACL:
4642 SMB_ACL_T file_acl = NULL;
4643 SMB_ACL_T def_acl = NULL;
4644 uint16 num_file_acls = 0;
4645 uint16 num_def_acls = 0;
4647 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4648 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4649 } else {
4650 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4653 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4654 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4655 fname ));
4656 reply_nterror(
4657 req,
4658 NT_STATUS_NOT_IMPLEMENTED);
4659 return;
4662 if (S_ISDIR(sbuf.st_mode)) {
4663 if (fsp && fsp->is_directory) {
4664 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4665 } else {
4666 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4668 def_acl = free_empty_sys_acl(conn, def_acl);
4671 num_file_acls = count_acl_entries(conn, file_acl);
4672 num_def_acls = count_acl_entries(conn, def_acl);
4674 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4675 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4676 data_size,
4677 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4678 SMB_POSIX_ACL_HEADER_SIZE) ));
4679 if (file_acl) {
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4682 if (def_acl) {
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4685 reply_nterror(
4686 req,
4687 NT_STATUS_BUFFER_TOO_SMALL);
4688 return;
4691 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4692 SSVAL(pdata,2,num_file_acls);
4693 SSVAL(pdata,4,num_def_acls);
4694 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4695 if (file_acl) {
4696 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4698 if (def_acl) {
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4701 reply_nterror(
4702 req, NT_STATUS_INTERNAL_ERROR);
4703 return;
4705 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4706 if (file_acl) {
4707 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4709 if (def_acl) {
4710 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4712 reply_nterror(
4713 req,
4714 NT_STATUS_INTERNAL_ERROR);
4715 return;
4718 if (file_acl) {
4719 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4721 if (def_acl) {
4722 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4724 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4725 break;
4727 #endif
4730 case SMB_QUERY_POSIX_LOCK:
4732 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4733 uint64_t count;
4734 uint64_t offset;
4735 uint32 lock_pid;
4736 enum brl_type lock_type;
4738 if (total_data != POSIX_LOCK_DATA_SIZE) {
4739 reply_nterror(
4740 req, NT_STATUS_INVALID_PARAMETER);
4741 return;
4744 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4745 case POSIX_LOCK_TYPE_READ:
4746 lock_type = READ_LOCK;
4747 break;
4748 case POSIX_LOCK_TYPE_WRITE:
4749 lock_type = WRITE_LOCK;
4750 break;
4751 case POSIX_LOCK_TYPE_UNLOCK:
4752 default:
4753 /* There's no point in asking for an unlock... */
4754 reply_nterror(
4755 req,
4756 NT_STATUS_INVALID_PARAMETER);
4757 return;
4760 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4761 #if defined(HAVE_LONGLONG)
4762 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4763 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4764 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4765 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4766 #else /* HAVE_LONGLONG */
4767 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4768 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4769 #endif /* HAVE_LONGLONG */
4771 status = query_lock(fsp,
4772 &lock_pid,
4773 &count,
4774 &offset,
4775 &lock_type,
4776 POSIX_LOCK);
4778 if (ERROR_WAS_LOCK_DENIED(status)) {
4779 /* Here we need to report who has it locked... */
4780 data_size = POSIX_LOCK_DATA_SIZE;
4782 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4783 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4784 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4785 #if defined(HAVE_LONGLONG)
4786 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4787 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4788 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4789 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4790 #else /* HAVE_LONGLONG */
4791 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4792 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4793 #endif /* HAVE_LONGLONG */
4795 } else if (NT_STATUS_IS_OK(status)) {
4796 /* For success we just return a copy of what we sent
4797 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4798 data_size = POSIX_LOCK_DATA_SIZE;
4799 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4800 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4801 } else {
4802 reply_nterror(req, status);
4803 return;
4805 break;
4808 default:
4809 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4810 return;
4813 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4814 max_data_bytes);
4816 return;
4819 /****************************************************************************
4820 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4821 code.
4822 ****************************************************************************/
4824 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4825 connection_struct *conn,
4826 const char *oldname_in,
4827 const char *newname_in)
4829 SMB_STRUCT_STAT sbuf1, sbuf2;
4830 char *last_component_oldname = NULL;
4831 char *last_component_newname = NULL;
4832 char *oldname = NULL;
4833 char *newname = NULL;
4834 NTSTATUS status = NT_STATUS_OK;
4836 ZERO_STRUCT(sbuf1);
4837 ZERO_STRUCT(sbuf2);
4839 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4840 &last_component_oldname, &sbuf1);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 return status;
4845 status = check_name(conn, oldname);
4846 if (!NT_STATUS_IS_OK(status)) {
4847 return status;
4850 /* source must already exist. */
4851 if (!VALID_STAT(sbuf1)) {
4852 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4855 status = unix_convert(ctx, conn, newname_in, False, &newname,
4856 &last_component_newname, &sbuf2);
4857 if (!NT_STATUS_IS_OK(status)) {
4858 return status;
4861 status = check_name(conn, newname);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 return status;
4866 /* Disallow if newname already exists. */
4867 if (VALID_STAT(sbuf2)) {
4868 return NT_STATUS_OBJECT_NAME_COLLISION;
4871 /* No links from a directory. */
4872 if (S_ISDIR(sbuf1.st_mode)) {
4873 return NT_STATUS_FILE_IS_A_DIRECTORY;
4876 /* Ensure this is within the share. */
4877 status = check_reduced_name(conn, oldname);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 return status;
4882 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4884 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4885 status = map_nt_error_from_unix(errno);
4886 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4887 nt_errstr(status), newname, oldname));
4890 return status;
4893 /****************************************************************************
4894 Deal with setting the time from any of the setfilepathinfo functions.
4895 ****************************************************************************/
4897 NTSTATUS smb_set_file_time(connection_struct *conn,
4898 files_struct *fsp,
4899 const char *fname,
4900 const SMB_STRUCT_STAT *psbuf,
4901 struct smb_file_time *ft,
4902 bool setting_write_time)
4904 struct smb_file_time ft_stat;
4905 uint32 action =
4906 FILE_NOTIFY_CHANGE_LAST_ACCESS
4907 |FILE_NOTIFY_CHANGE_LAST_WRITE
4908 |FILE_NOTIFY_CHANGE_CREATION;
4910 if (!VALID_STAT(*psbuf)) {
4911 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4914 /* get some defaults (no modifications) if any info is zero or -1. */
4915 if (null_timespec(ft->create_time)) {
4916 ft->create_time = get_create_timespec(psbuf, lp_fake_dir_create_times(SNUM(conn)));
4917 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4920 if (null_timespec(ft->atime)) {
4921 ft->atime= get_atimespec(psbuf);
4922 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4925 if (null_timespec(ft->mtime)) {
4926 ft->mtime = get_mtimespec(psbuf);
4927 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4930 if (!setting_write_time) {
4931 /* ft->mtime comes from change time, not write time. */
4932 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4935 /* Ensure the resolution is the correct for
4936 * what we can store on this filesystem. */
4938 round_timespec(conn->ts_res, &ft->create_time);
4939 round_timespec(conn->ts_res, &ft->atime);
4940 round_timespec(conn->ts_res, &ft->mtime);
4942 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4943 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4944 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4945 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4946 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4947 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4949 if (setting_write_time) {
4951 * This was a Windows setfileinfo on an open file.
4952 * NT does this a lot. We also need to
4953 * set the time here, as it can be read by
4954 * FindFirst/FindNext and with the patch for bug #2045
4955 * in smbd/fileio.c it ensures that this timestamp is
4956 * kept sticky even after a write. We save the request
4957 * away and will set it on file close and after a write. JRA.
4960 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4961 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4963 if (fsp != NULL) {
4964 if (fsp->base_fsp) {
4965 set_sticky_write_time_fsp(fsp->base_fsp,
4966 ft->mtime);
4967 } else {
4968 set_sticky_write_time_fsp(fsp, ft->mtime);
4970 } else {
4971 set_sticky_write_time_path(conn, fname,
4972 vfs_file_id_from_sbuf(conn, psbuf),
4973 ft->mtime);
4977 ft_stat.create_time = get_create_timespec(psbuf,
4978 lp_fake_dir_create_times(SNUM(conn)));
4979 ft_stat.atime= get_atimespec(psbuf);
4980 ft_stat.mtime = get_mtimespec(psbuf);
4982 round_timespec(conn->ts_res, &ft_stat.create_time);
4983 round_timespec(conn->ts_res, &ft_stat.atime);
4984 round_timespec(conn->ts_res, &ft_stat.mtime);
4986 if (fsp && fsp->base_fsp) {
4987 fname = fsp->base_fsp->fsp_name;
4990 if (timespec_compare(&ft_stat.create_time, &ft->create_time) ||
4991 timespec_compare(&ft_stat.atime, &ft->atime) ||
4992 timespec_compare(&ft_stat.mtime, &ft->mtime)) {
4993 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4994 if(file_ntimes(conn, fname, ft)!=0) {
4995 return map_nt_error_from_unix(errno);
4998 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5000 return NT_STATUS_OK;
5003 /****************************************************************************
5004 Deal with setting the dosmode from any of the setfilepathinfo functions.
5005 ****************************************************************************/
5007 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5008 files_struct *fsp,
5009 const char *fname,
5010 SMB_STRUCT_STAT *psbuf,
5011 uint32 dosmode)
5013 if (!VALID_STAT(*psbuf)) {
5014 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5017 if (fsp) {
5018 if (fsp->base_fsp) {
5019 fname = fsp->base_fsp->fsp_name;
5020 } else {
5021 fname = fsp->fsp_name;
5025 if (dosmode) {
5026 if (S_ISDIR(psbuf->st_mode)) {
5027 dosmode |= aDIR;
5028 } else {
5029 dosmode &= ~aDIR;
5033 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5035 /* check the mode isn't different, before changing it */
5036 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5038 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5039 fname, (unsigned int)dosmode ));
5041 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5042 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5043 fname, strerror(errno)));
5044 return map_nt_error_from_unix(errno);
5047 return NT_STATUS_OK;
5050 /****************************************************************************
5051 Deal with setting the size from any of the setfilepathinfo functions.
5052 ****************************************************************************/
5054 static NTSTATUS smb_set_file_size(connection_struct *conn,
5055 struct smb_request *req,
5056 files_struct *fsp,
5057 const char *fname,
5058 SMB_STRUCT_STAT *psbuf,
5059 SMB_OFF_T size)
5061 NTSTATUS status = NT_STATUS_OK;
5062 files_struct *new_fsp = NULL;
5064 if (!VALID_STAT(*psbuf)) {
5065 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5068 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5070 if (size == get_file_size_stat(psbuf)) {
5071 return NT_STATUS_OK;
5074 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5075 fname, (double)size ));
5077 if (fsp && fsp->fh->fd != -1) {
5078 /* Handle based call. */
5079 if (vfs_set_filelen(fsp, size) == -1) {
5080 return map_nt_error_from_unix(errno);
5082 trigger_write_time_update_immediate(fsp);
5083 return NT_STATUS_OK;
5086 status = SMB_VFS_CREATE_FILE(
5087 conn, /* conn */
5088 req, /* req */
5089 0, /* root_dir_fid */
5090 fname, /* fname */
5091 0, /* create_file_flags */
5092 FILE_WRITE_ATTRIBUTES, /* access_mask */
5093 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5094 FILE_SHARE_DELETE),
5095 FILE_OPEN, /* create_disposition*/
5096 0, /* create_options */
5097 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5098 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5099 0, /* allocation_size */
5100 NULL, /* sd */
5101 NULL, /* ea_list */
5102 &new_fsp, /* result */
5103 NULL, /* pinfo */
5104 psbuf); /* psbuf */
5106 if (!NT_STATUS_IS_OK(status)) {
5107 /* NB. We check for open_was_deferred in the caller. */
5108 return status;
5111 if (vfs_set_filelen(new_fsp, size) == -1) {
5112 status = map_nt_error_from_unix(errno);
5113 close_file(req, new_fsp,NORMAL_CLOSE);
5114 return status;
5117 trigger_write_time_update_immediate(new_fsp);
5118 close_file(req, new_fsp,NORMAL_CLOSE);
5119 return NT_STATUS_OK;
5122 /****************************************************************************
5123 Deal with SMB_INFO_SET_EA.
5124 ****************************************************************************/
5126 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5127 const char *pdata,
5128 int total_data,
5129 files_struct *fsp,
5130 const char *fname)
5132 struct ea_list *ea_list = NULL;
5133 TALLOC_CTX *ctx = NULL;
5134 NTSTATUS status = NT_STATUS_OK;
5136 if (total_data < 10) {
5138 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5139 length. They seem to have no effect. Bug #3212. JRA */
5141 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5142 /* We're done. We only get EA info in this call. */
5143 return NT_STATUS_OK;
5146 return NT_STATUS_INVALID_PARAMETER;
5149 if (IVAL(pdata,0) > total_data) {
5150 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5151 IVAL(pdata,0), (unsigned int)total_data));
5152 return NT_STATUS_INVALID_PARAMETER;
5155 ctx = talloc_tos();
5156 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5157 if (!ea_list) {
5158 return NT_STATUS_INVALID_PARAMETER;
5160 status = set_ea(conn, fsp, fname, ea_list);
5162 return status;
5165 /****************************************************************************
5166 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5167 ****************************************************************************/
5169 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5170 const char *pdata,
5171 int total_data,
5172 files_struct *fsp,
5173 const char *fname,
5174 SMB_STRUCT_STAT *psbuf)
5176 NTSTATUS status = NT_STATUS_OK;
5177 bool delete_on_close;
5178 uint32 dosmode = 0;
5180 if (total_data < 1) {
5181 return NT_STATUS_INVALID_PARAMETER;
5184 if (fsp == NULL) {
5185 return NT_STATUS_INVALID_HANDLE;
5188 delete_on_close = (CVAL(pdata,0) ? True : False);
5189 dosmode = dos_mode(conn, fname, psbuf);
5191 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5192 "delete_on_close = %u\n",
5193 fsp->fsp_name,
5194 (unsigned int)dosmode,
5195 (unsigned int)delete_on_close ));
5197 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5199 if (!NT_STATUS_IS_OK(status)) {
5200 return status;
5203 /* The set is across all open files on this dev/inode pair. */
5204 if (!set_delete_on_close(fsp, delete_on_close,
5205 &conn->server_info->utok)) {
5206 return NT_STATUS_ACCESS_DENIED;
5208 return NT_STATUS_OK;
5211 /****************************************************************************
5212 Deal with SMB_FILE_POSITION_INFORMATION.
5213 ****************************************************************************/
5215 static NTSTATUS smb_file_position_information(connection_struct *conn,
5216 const char *pdata,
5217 int total_data,
5218 files_struct *fsp)
5220 uint64_t position_information;
5222 if (total_data < 8) {
5223 return NT_STATUS_INVALID_PARAMETER;
5226 if (fsp == NULL) {
5227 /* Ignore on pathname based set. */
5228 return NT_STATUS_OK;
5231 position_information = (uint64_t)IVAL(pdata,0);
5232 #ifdef LARGE_SMB_OFF_T
5233 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5234 #else /* LARGE_SMB_OFF_T */
5235 if (IVAL(pdata,4) != 0) {
5236 /* more than 32 bits? */
5237 return NT_STATUS_INVALID_PARAMETER;
5239 #endif /* LARGE_SMB_OFF_T */
5241 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5242 fsp->fsp_name, (double)position_information ));
5243 fsp->fh->position_information = position_information;
5244 return NT_STATUS_OK;
5247 /****************************************************************************
5248 Deal with SMB_FILE_MODE_INFORMATION.
5249 ****************************************************************************/
5251 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5252 const char *pdata,
5253 int total_data)
5255 uint32 mode;
5257 if (total_data < 4) {
5258 return NT_STATUS_INVALID_PARAMETER;
5260 mode = IVAL(pdata,0);
5261 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5262 return NT_STATUS_INVALID_PARAMETER;
5264 return NT_STATUS_OK;
5267 /****************************************************************************
5268 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5269 ****************************************************************************/
5271 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5272 struct smb_request *req,
5273 const char *pdata,
5274 int total_data,
5275 const char *fname)
5277 char *link_target = NULL;
5278 const char *newname = fname;
5279 NTSTATUS status = NT_STATUS_OK;
5280 TALLOC_CTX *ctx = talloc_tos();
5282 /* Set a symbolic link. */
5283 /* Don't allow this if follow links is false. */
5285 if (total_data == 0) {
5286 return NT_STATUS_INVALID_PARAMETER;
5289 if (!lp_symlinks(SNUM(conn))) {
5290 return NT_STATUS_ACCESS_DENIED;
5293 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5294 total_data, STR_TERMINATE);
5296 if (!link_target) {
5297 return NT_STATUS_INVALID_PARAMETER;
5300 /* !widelinks forces the target path to be within the share. */
5301 /* This means we can interpret the target as a pathname. */
5302 if (!lp_widelinks(SNUM(conn))) {
5303 char *rel_name = NULL;
5304 char *last_dirp = NULL;
5306 if (*link_target == '/') {
5307 /* No absolute paths allowed. */
5308 return NT_STATUS_ACCESS_DENIED;
5310 rel_name = talloc_strdup(ctx,newname);
5311 if (!rel_name) {
5312 return NT_STATUS_NO_MEMORY;
5314 last_dirp = strrchr_m(rel_name, '/');
5315 if (last_dirp) {
5316 last_dirp[1] = '\0';
5317 } else {
5318 rel_name = talloc_strdup(ctx,"./");
5319 if (!rel_name) {
5320 return NT_STATUS_NO_MEMORY;
5323 rel_name = talloc_asprintf_append(rel_name,
5324 "%s",
5325 link_target);
5326 if (!rel_name) {
5327 return NT_STATUS_NO_MEMORY;
5330 status = check_name(conn, rel_name);
5331 if (!NT_STATUS_IS_OK(status)) {
5332 return status;
5336 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5337 newname, link_target ));
5339 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5340 return map_nt_error_from_unix(errno);
5343 return NT_STATUS_OK;
5346 /****************************************************************************
5347 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5348 ****************************************************************************/
5350 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5351 struct smb_request *req,
5352 const char *pdata, int total_data,
5353 const char *fname)
5355 char *oldname = NULL;
5356 TALLOC_CTX *ctx = talloc_tos();
5357 NTSTATUS status = NT_STATUS_OK;
5359 /* Set a hard link. */
5360 if (total_data == 0) {
5361 return NT_STATUS_INVALID_PARAMETER;
5364 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5365 total_data, STR_TERMINATE, &status);
5366 if (!NT_STATUS_IS_OK(status)) {
5367 return status;
5370 status = resolve_dfspath(ctx, conn,
5371 req->flags2 & FLAGS2_DFS_PATHNAMES,
5372 oldname,
5373 &oldname);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 return status;
5378 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5379 fname, oldname));
5381 return hardlink_internals(ctx, conn, oldname, fname);
5384 /****************************************************************************
5385 Deal with SMB_FILE_RENAME_INFORMATION.
5386 ****************************************************************************/
5388 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5389 struct smb_request *req,
5390 const char *pdata,
5391 int total_data,
5392 files_struct *fsp,
5393 const char *fname)
5395 bool overwrite;
5396 uint32 root_fid;
5397 uint32 len;
5398 char *newname = NULL;
5399 char *base_name = NULL;
5400 bool dest_has_wcard = False;
5401 SMB_STRUCT_STAT sbuf;
5402 char *newname_last_component = NULL;
5403 NTSTATUS status = NT_STATUS_OK;
5404 char *p;
5405 TALLOC_CTX *ctx = talloc_tos();
5407 if (total_data < 13) {
5408 return NT_STATUS_INVALID_PARAMETER;
5411 ZERO_STRUCT(sbuf);
5413 overwrite = (CVAL(pdata,0) ? True : False);
5414 root_fid = IVAL(pdata,4);
5415 len = IVAL(pdata,8);
5417 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5418 return NT_STATUS_INVALID_PARAMETER;
5421 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5422 len, 0, &status,
5423 &dest_has_wcard);
5424 if (!NT_STATUS_IS_OK(status)) {
5425 return status;
5428 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5429 newname));
5431 status = resolve_dfspath_wcard(ctx, conn,
5432 req->flags2 & FLAGS2_DFS_PATHNAMES,
5433 newname,
5434 &newname,
5435 &dest_has_wcard);
5436 if (!NT_STATUS_IS_OK(status)) {
5437 return status;
5440 /* Check the new name has no '/' characters. */
5441 if (strchr_m(newname, '/')) {
5442 return NT_STATUS_NOT_SUPPORTED;
5445 if (fsp && fsp->base_fsp) {
5446 /* newname must be a stream name. */
5447 if (newname[0] != ':') {
5448 return NT_STATUS_NOT_SUPPORTED;
5450 base_name = talloc_asprintf(ctx, "%s%s",
5451 fsp->base_fsp->fsp_name,
5452 newname);
5453 if (!base_name) {
5454 return NT_STATUS_NO_MEMORY;
5456 } else {
5457 /* newname must *not* be a stream name. */
5458 if (is_ntfs_stream_name(newname)) {
5459 return NT_STATUS_NOT_SUPPORTED;
5462 /* Create the base directory. */
5463 base_name = talloc_strdup(ctx, fname);
5464 if (!base_name) {
5465 return NT_STATUS_NO_MEMORY;
5467 p = strrchr_m(base_name, '/');
5468 if (p) {
5469 p[1] = '\0';
5470 } else {
5471 base_name = talloc_strdup(ctx, "./");
5472 if (!base_name) {
5473 return NT_STATUS_NO_MEMORY;
5476 /* Append the new name. */
5477 base_name = talloc_asprintf_append(base_name,
5478 "%s",
5479 newname);
5480 if (!base_name) {
5481 return NT_STATUS_NO_MEMORY;
5484 status = unix_convert(ctx, conn, newname, False,
5485 &newname,
5486 &newname_last_component,
5487 &sbuf);
5489 /* If an error we expect this to be
5490 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5492 if (!NT_STATUS_IS_OK(status)
5493 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5494 status)) {
5495 return status;
5499 if (fsp) {
5500 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5501 fsp->fnum, fsp->fsp_name, base_name ));
5502 status = rename_internals_fsp(conn, fsp, base_name,
5503 newname_last_component, 0,
5504 overwrite);
5505 } else {
5506 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5507 fname, base_name ));
5508 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5509 overwrite, False, dest_has_wcard,
5510 FILE_WRITE_ATTRIBUTES);
5513 return status;
5516 /****************************************************************************
5517 Deal with SMB_SET_POSIX_ACL.
5518 ****************************************************************************/
5520 #if defined(HAVE_POSIX_ACLS)
5521 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5522 const char *pdata,
5523 int total_data,
5524 files_struct *fsp,
5525 const char *fname,
5526 SMB_STRUCT_STAT *psbuf)
5528 uint16 posix_acl_version;
5529 uint16 num_file_acls;
5530 uint16 num_def_acls;
5531 bool valid_file_acls = True;
5532 bool valid_def_acls = True;
5534 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5535 return NT_STATUS_INVALID_PARAMETER;
5537 posix_acl_version = SVAL(pdata,0);
5538 num_file_acls = SVAL(pdata,2);
5539 num_def_acls = SVAL(pdata,4);
5541 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5542 valid_file_acls = False;
5543 num_file_acls = 0;
5546 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5547 valid_def_acls = False;
5548 num_def_acls = 0;
5551 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5552 return NT_STATUS_INVALID_PARAMETER;
5555 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5556 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5557 return NT_STATUS_INVALID_PARAMETER;
5560 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5561 fname ? fname : fsp->fsp_name,
5562 (unsigned int)num_file_acls,
5563 (unsigned int)num_def_acls));
5565 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5566 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5567 return map_nt_error_from_unix(errno);
5570 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5571 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5572 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5573 return map_nt_error_from_unix(errno);
5575 return NT_STATUS_OK;
5577 #endif
5579 /****************************************************************************
5580 Deal with SMB_SET_POSIX_LOCK.
5581 ****************************************************************************/
5583 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5584 struct smb_request *req,
5585 const char *pdata,
5586 int total_data,
5587 files_struct *fsp)
5589 uint64_t count;
5590 uint64_t offset;
5591 uint32 lock_pid;
5592 bool blocking_lock = False;
5593 enum brl_type lock_type;
5595 NTSTATUS status = NT_STATUS_OK;
5597 if (fsp == NULL || fsp->fh->fd == -1) {
5598 return NT_STATUS_INVALID_HANDLE;
5601 if (total_data != POSIX_LOCK_DATA_SIZE) {
5602 return NT_STATUS_INVALID_PARAMETER;
5605 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5606 case POSIX_LOCK_TYPE_READ:
5607 lock_type = READ_LOCK;
5608 break;
5609 case POSIX_LOCK_TYPE_WRITE:
5610 /* Return the right POSIX-mappable error code for files opened read-only. */
5611 if (!fsp->can_write) {
5612 return NT_STATUS_INVALID_HANDLE;
5614 lock_type = WRITE_LOCK;
5615 break;
5616 case POSIX_LOCK_TYPE_UNLOCK:
5617 lock_type = UNLOCK_LOCK;
5618 break;
5619 default:
5620 return NT_STATUS_INVALID_PARAMETER;
5623 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5624 blocking_lock = False;
5625 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5626 blocking_lock = True;
5627 } else {
5628 return NT_STATUS_INVALID_PARAMETER;
5631 if (!lp_blocking_locks(SNUM(conn))) {
5632 blocking_lock = False;
5635 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5636 #if defined(HAVE_LONGLONG)
5637 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5638 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5639 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5640 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5641 #else /* HAVE_LONGLONG */
5642 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5643 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5644 #endif /* HAVE_LONGLONG */
5646 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5647 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5648 fsp->fsp_name,
5649 (unsigned int)lock_type,
5650 (unsigned int)lock_pid,
5651 (double)count,
5652 (double)offset ));
5654 if (lock_type == UNLOCK_LOCK) {
5655 status = do_unlock(smbd_messaging_context(),
5656 fsp,
5657 lock_pid,
5658 count,
5659 offset,
5660 POSIX_LOCK);
5661 } else {
5662 uint32 block_smbpid;
5664 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5665 fsp,
5666 lock_pid,
5667 count,
5668 offset,
5669 lock_type,
5670 POSIX_LOCK,
5671 blocking_lock,
5672 &status,
5673 &block_smbpid,
5674 NULL);
5676 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5678 * A blocking lock was requested. Package up
5679 * this smb into a queued request and push it
5680 * onto the blocking lock queue.
5682 if(push_blocking_lock_request(br_lck,
5683 req,
5684 fsp,
5685 -1, /* infinite timeout. */
5687 lock_pid,
5688 lock_type,
5689 POSIX_LOCK,
5690 offset,
5691 count,
5692 block_smbpid)) {
5693 TALLOC_FREE(br_lck);
5694 return status;
5697 TALLOC_FREE(br_lck);
5700 return status;
5703 /****************************************************************************
5704 Deal with SMB_INFO_STANDARD.
5705 ****************************************************************************/
5707 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5708 const char *pdata,
5709 int total_data,
5710 files_struct *fsp,
5711 const char *fname,
5712 const SMB_STRUCT_STAT *psbuf)
5714 struct smb_file_time ft;
5715 ZERO_STRUCT(ft);
5717 if (total_data < 12) {
5718 return NT_STATUS_INVALID_PARAMETER;
5721 /* create time */
5722 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
5724 /* access time */
5725 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
5727 /* write time */
5728 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
5730 DEBUG(10,("smb_set_info_standard: file %s\n",
5731 fname ? fname : fsp->fsp_name ));
5733 return smb_set_file_time(conn,
5734 fsp,
5735 fname,
5736 psbuf,
5737 &ft,
5738 true);
5741 /****************************************************************************
5742 Deal with SMB_SET_FILE_BASIC_INFO.
5743 ****************************************************************************/
5745 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5746 const char *pdata,
5747 int total_data,
5748 files_struct *fsp,
5749 const char *fname,
5750 SMB_STRUCT_STAT *psbuf)
5752 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5753 struct timespec write_time;
5754 struct timespec changed_time;
5755 struct smb_file_time ft;
5756 uint32 dosmode = 0;
5757 NTSTATUS status = NT_STATUS_OK;
5758 bool setting_write_time = true;
5760 ZERO_STRUCT(ft);
5762 if (total_data < 36) {
5763 return NT_STATUS_INVALID_PARAMETER;
5766 /* Set the attributes */
5767 dosmode = IVAL(pdata,32);
5768 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 return status;
5773 /* access time */
5774 ft.atime = interpret_long_date(pdata+8);
5776 write_time = interpret_long_date(pdata+16);
5777 changed_time = interpret_long_date(pdata+24);
5779 /* mtime */
5780 ft.mtime = timespec_min(&write_time, &changed_time);
5782 /* create time */
5783 ft.create_time = interpret_long_date(pdata);
5785 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5786 !null_timespec(write_time)) {
5787 ft.mtime = write_time;
5790 /* Prefer a defined time to an undefined one. */
5791 if (null_timespec(ft.mtime)) {
5792 if (null_timespec(write_time)) {
5793 ft.mtime = changed_time;
5794 setting_write_time = false;
5795 } else {
5796 ft.mtime = write_time;
5800 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5801 fname ? fname : fsp->fsp_name ));
5803 return smb_set_file_time(conn,
5804 fsp,
5805 fname,
5806 psbuf,
5807 &ft,
5808 setting_write_time);
5811 /****************************************************************************
5812 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5813 ****************************************************************************/
5815 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5816 struct smb_request *req,
5817 const char *pdata,
5818 int total_data,
5819 files_struct *fsp,
5820 const char *fname,
5821 SMB_STRUCT_STAT *psbuf)
5823 uint64_t allocation_size = 0;
5824 NTSTATUS status = NT_STATUS_OK;
5825 files_struct *new_fsp = NULL;
5827 if (!VALID_STAT(*psbuf)) {
5828 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5831 if (total_data < 8) {
5832 return NT_STATUS_INVALID_PARAMETER;
5835 allocation_size = (uint64_t)IVAL(pdata,0);
5836 #ifdef LARGE_SMB_OFF_T
5837 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5838 #else /* LARGE_SMB_OFF_T */
5839 if (IVAL(pdata,4) != 0) {
5840 /* more than 32 bits? */
5841 return NT_STATUS_INVALID_PARAMETER;
5843 #endif /* LARGE_SMB_OFF_T */
5845 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5846 fname, (double)allocation_size ));
5848 if (allocation_size) {
5849 allocation_size = smb_roundup(conn, allocation_size);
5852 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5853 fname, (double)allocation_size ));
5855 if (fsp && fsp->fh->fd != -1) {
5856 /* Open file handle. */
5857 /* Only change if needed. */
5858 if (allocation_size != get_file_size_stat(psbuf)) {
5859 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5860 return map_nt_error_from_unix(errno);
5863 /* But always update the time. */
5865 * This is equivalent to a write. Ensure it's seen immediately
5866 * if there are no pending writes.
5868 trigger_write_time_update_immediate(fsp);
5869 return NT_STATUS_OK;
5872 /* Pathname or stat or directory file. */
5874 status = SMB_VFS_CREATE_FILE(
5875 conn, /* conn */
5876 req, /* req */
5877 0, /* root_dir_fid */
5878 fname, /* fname */
5879 0, /* create_file_flags */
5880 FILE_WRITE_DATA, /* access_mask */
5881 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5882 FILE_SHARE_DELETE),
5883 FILE_OPEN, /* create_disposition*/
5884 0, /* create_options */
5885 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5886 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5887 0, /* allocation_size */
5888 NULL, /* sd */
5889 NULL, /* ea_list */
5890 &new_fsp, /* result */
5891 NULL, /* pinfo */
5892 psbuf); /* psbuf */
5894 if (!NT_STATUS_IS_OK(status)) {
5895 /* NB. We check for open_was_deferred in the caller. */
5896 return status;
5899 /* Only change if needed. */
5900 if (allocation_size != get_file_size_stat(psbuf)) {
5901 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5902 status = map_nt_error_from_unix(errno);
5903 close_file(req, new_fsp, NORMAL_CLOSE);
5904 return status;
5908 /* Changing the allocation size should set the last mod time. */
5910 * This is equivalent to a write. Ensure it's seen immediately
5911 * if there are no pending writes.
5913 trigger_write_time_update_immediate(new_fsp);
5915 close_file(req, new_fsp, NORMAL_CLOSE);
5916 return NT_STATUS_OK;
5919 /****************************************************************************
5920 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5921 ****************************************************************************/
5923 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5924 struct smb_request *req,
5925 const char *pdata,
5926 int total_data,
5927 files_struct *fsp,
5928 const char *fname,
5929 SMB_STRUCT_STAT *psbuf)
5931 SMB_OFF_T size;
5933 if (total_data < 8) {
5934 return NT_STATUS_INVALID_PARAMETER;
5937 size = IVAL(pdata,0);
5938 #ifdef LARGE_SMB_OFF_T
5939 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5940 #else /* LARGE_SMB_OFF_T */
5941 if (IVAL(pdata,4) != 0) {
5942 /* more than 32 bits? */
5943 return NT_STATUS_INVALID_PARAMETER;
5945 #endif /* LARGE_SMB_OFF_T */
5946 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5947 "file %s to %.0f\n", fname, (double)size ));
5949 return smb_set_file_size(conn, req,
5950 fsp,
5951 fname,
5952 psbuf,
5953 size);
5956 /****************************************************************************
5957 Allow a UNIX info mknod.
5958 ****************************************************************************/
5960 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5961 const char *pdata,
5962 int total_data,
5963 const char *fname,
5964 SMB_STRUCT_STAT *psbuf)
5966 uint32 file_type = IVAL(pdata,56);
5967 #if defined(HAVE_MAKEDEV)
5968 uint32 dev_major = IVAL(pdata,60);
5969 uint32 dev_minor = IVAL(pdata,68);
5970 #endif
5971 SMB_DEV_T dev = (SMB_DEV_T)0;
5972 uint32 raw_unixmode = IVAL(pdata,84);
5973 NTSTATUS status;
5974 mode_t unixmode;
5976 if (total_data < 100) {
5977 return NT_STATUS_INVALID_PARAMETER;
5980 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 return status;
5985 #if defined(HAVE_MAKEDEV)
5986 dev = makedev(dev_major, dev_minor);
5987 #endif
5989 switch (file_type) {
5990 #if defined(S_IFIFO)
5991 case UNIX_TYPE_FIFO:
5992 unixmode |= S_IFIFO;
5993 break;
5994 #endif
5995 #if defined(S_IFSOCK)
5996 case UNIX_TYPE_SOCKET:
5997 unixmode |= S_IFSOCK;
5998 break;
5999 #endif
6000 #if defined(S_IFCHR)
6001 case UNIX_TYPE_CHARDEV:
6002 unixmode |= S_IFCHR;
6003 break;
6004 #endif
6005 #if defined(S_IFBLK)
6006 case UNIX_TYPE_BLKDEV:
6007 unixmode |= S_IFBLK;
6008 break;
6009 #endif
6010 default:
6011 return NT_STATUS_INVALID_PARAMETER;
6014 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6015 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6017 /* Ok - do the mknod. */
6018 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6019 return map_nt_error_from_unix(errno);
6022 /* If any of the other "set" calls fail we
6023 * don't want to end up with a half-constructed mknod.
6026 if (lp_inherit_perms(SNUM(conn))) {
6027 char *parent;
6028 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6029 return NT_STATUS_NO_MEMORY;
6031 inherit_access_posix_acl(conn, parent, fname, unixmode);
6032 TALLOC_FREE(parent);
6035 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6036 status = map_nt_error_from_unix(errno);
6037 SMB_VFS_UNLINK(conn,fname);
6038 return status;
6040 return NT_STATUS_OK;
6043 /****************************************************************************
6044 Deal with SMB_SET_FILE_UNIX_BASIC.
6045 ****************************************************************************/
6047 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6048 struct smb_request *req,
6049 const char *pdata,
6050 int total_data,
6051 files_struct *fsp,
6052 const char *fname,
6053 SMB_STRUCT_STAT *psbuf)
6055 struct smb_file_time ft;
6056 uint32 raw_unixmode;
6057 mode_t unixmode;
6058 SMB_OFF_T size = 0;
6059 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6060 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6061 NTSTATUS status = NT_STATUS_OK;
6062 bool delete_on_fail = False;
6063 enum perm_type ptype;
6064 files_struct *all_fsps = NULL;
6065 bool modify_mtime = true;
6066 struct file_id id;
6068 ZERO_STRUCT(ft);
6070 if (total_data < 100) {
6071 return NT_STATUS_INVALID_PARAMETER;
6074 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6075 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6076 size=IVAL(pdata,0); /* first 8 Bytes are size */
6077 #ifdef LARGE_SMB_OFF_T
6078 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6079 #else /* LARGE_SMB_OFF_T */
6080 if (IVAL(pdata,4) != 0) {
6081 /* more than 32 bits? */
6082 return NT_STATUS_INVALID_PARAMETER;
6084 #endif /* LARGE_SMB_OFF_T */
6087 ft.atime = interpret_long_date(pdata+24); /* access_time */
6088 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6089 set_owner = (uid_t)IVAL(pdata,40);
6090 set_grp = (gid_t)IVAL(pdata,48);
6091 raw_unixmode = IVAL(pdata,84);
6093 if (VALID_STAT(*psbuf)) {
6094 if (S_ISDIR(psbuf->st_mode)) {
6095 ptype = PERM_EXISTING_DIR;
6096 } else {
6097 ptype = PERM_EXISTING_FILE;
6099 } else {
6100 ptype = PERM_NEW_FILE;
6103 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 return status;
6108 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6109 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6110 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6112 if (!VALID_STAT(*psbuf)) {
6114 * The only valid use of this is to create character and block
6115 * devices, and named pipes. This is deprecated (IMHO) and
6116 * a new info level should be used for mknod. JRA.
6119 status = smb_unix_mknod(conn,
6120 pdata,
6121 total_data,
6122 fname,
6123 psbuf);
6124 if (!NT_STATUS_IS_OK(status)) {
6125 return status;
6128 /* Ensure we don't try and change anything else. */
6129 raw_unixmode = SMB_MODE_NO_CHANGE;
6130 size = get_file_size_stat(psbuf);
6131 ft.atime = get_atimespec(psbuf);
6132 ft.mtime = get_mtimespec(psbuf);
6134 * We continue here as we might want to change the
6135 * owner uid/gid.
6137 delete_on_fail = True;
6140 #if 1
6141 /* Horrible backwards compatibility hack as an old server bug
6142 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6143 * */
6145 if (!size) {
6146 size = get_file_size_stat(psbuf);
6148 #endif
6151 * Deal with the UNIX specific mode set.
6154 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6155 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6156 (unsigned int)unixmode, fname ));
6157 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6158 return map_nt_error_from_unix(errno);
6163 * Deal with the UNIX specific uid set.
6166 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6167 int ret;
6169 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6170 (unsigned int)set_owner, fname ));
6172 if (S_ISLNK(psbuf->st_mode)) {
6173 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6174 } else {
6175 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6178 if (ret != 0) {
6179 status = map_nt_error_from_unix(errno);
6180 if (delete_on_fail) {
6181 SMB_VFS_UNLINK(conn,fname);
6183 return status;
6188 * Deal with the UNIX specific gid set.
6191 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6192 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6193 (unsigned int)set_owner, fname ));
6194 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6195 status = map_nt_error_from_unix(errno);
6196 if (delete_on_fail) {
6197 SMB_VFS_UNLINK(conn,fname);
6199 return status;
6203 /* Deal with any size changes. */
6205 status = smb_set_file_size(conn, req,
6206 fsp,
6207 fname,
6208 psbuf,
6209 size);
6210 if (!NT_STATUS_IS_OK(status)) {
6211 return status;
6214 /* Deal with any time changes. */
6215 id = vfs_file_id_from_sbuf(conn, psbuf);
6216 for(all_fsps = file_find_di_first(id); all_fsps;
6217 all_fsps = file_find_di_next(all_fsps)) {
6219 * We're setting the time explicitly for UNIX.
6220 * Cancel any pending changes over all handles.
6222 all_fsps->update_write_time_on_close = false;
6223 TALLOC_FREE(all_fsps->update_write_time_event);
6227 * Override the "setting_write_time"
6228 * parameter here as it almost does what
6229 * we need. Just remember if we modified
6230 * mtime and send the notify ourselves.
6232 if (null_timespec(ft.mtime)) {
6233 modify_mtime = false;
6236 status = smb_set_file_time(conn,
6237 fsp,
6238 fname,
6239 psbuf,
6240 &ft,
6241 false);
6242 if (modify_mtime) {
6243 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6244 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6246 return status;
6249 /****************************************************************************
6250 Deal with SMB_SET_FILE_UNIX_INFO2.
6251 ****************************************************************************/
6253 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6254 struct smb_request *req,
6255 const char *pdata,
6256 int total_data,
6257 files_struct *fsp,
6258 const char *fname,
6259 SMB_STRUCT_STAT *psbuf)
6261 NTSTATUS status;
6262 uint32 smb_fflags;
6263 uint32 smb_fmask;
6265 if (total_data < 116) {
6266 return NT_STATUS_INVALID_PARAMETER;
6269 /* Start by setting all the fields that are common between UNIX_BASIC
6270 * and UNIX_INFO2.
6272 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6273 fsp, fname, psbuf);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 return status;
6278 smb_fflags = IVAL(pdata, 108);
6279 smb_fmask = IVAL(pdata, 112);
6281 /* NB: We should only attempt to alter the file flags if the client
6282 * sends a non-zero mask.
6284 if (smb_fmask != 0) {
6285 int stat_fflags = 0;
6287 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6288 &stat_fflags)) {
6289 /* Client asked to alter a flag we don't understand. */
6290 return NT_STATUS_INVALID_PARAMETER;
6293 if (fsp && fsp->fh->fd != -1) {
6294 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6295 return NT_STATUS_NOT_SUPPORTED;
6296 } else {
6297 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6298 return map_nt_error_from_unix(errno);
6303 /* XXX: need to add support for changing the create_time here. You
6304 * can do this for paths on Darwin with setattrlist(2). The right way
6305 * to hook this up is probably by extending the VFS utimes interface.
6308 return NT_STATUS_OK;
6311 /****************************************************************************
6312 Create a directory with POSIX semantics.
6313 ****************************************************************************/
6315 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6316 struct smb_request *req,
6317 char **ppdata,
6318 int total_data,
6319 const char *fname,
6320 SMB_STRUCT_STAT *psbuf,
6321 int *pdata_return_size)
6323 NTSTATUS status = NT_STATUS_OK;
6324 uint32 raw_unixmode = 0;
6325 uint32 mod_unixmode = 0;
6326 mode_t unixmode = (mode_t)0;
6327 files_struct *fsp = NULL;
6328 uint16 info_level_return = 0;
6329 int info;
6330 char *pdata = *ppdata;
6332 if (total_data < 18) {
6333 return NT_STATUS_INVALID_PARAMETER;
6336 raw_unixmode = IVAL(pdata,8);
6337 /* Next 4 bytes are not yet defined. */
6339 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 return status;
6344 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6346 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6347 fname, (unsigned int)unixmode ));
6349 status = SMB_VFS_CREATE_FILE(
6350 conn, /* conn */
6351 req, /* req */
6352 0, /* root_dir_fid */
6353 fname, /* fname */
6354 0, /* create_file_flags */
6355 FILE_READ_ATTRIBUTES, /* access_mask */
6356 FILE_SHARE_NONE, /* share_access */
6357 FILE_CREATE, /* create_disposition*/
6358 FILE_DIRECTORY_FILE, /* create_options */
6359 mod_unixmode, /* file_attributes */
6360 0, /* oplock_request */
6361 0, /* allocation_size */
6362 NULL, /* sd */
6363 NULL, /* ea_list */
6364 &fsp, /* result */
6365 &info, /* pinfo */
6366 psbuf); /* psbuf */
6368 if (NT_STATUS_IS_OK(status)) {
6369 close_file(req, fsp, NORMAL_CLOSE);
6372 info_level_return = SVAL(pdata,16);
6374 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6375 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6376 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6377 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6378 } else {
6379 *pdata_return_size = 12;
6382 /* Realloc the data size */
6383 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6384 if (*ppdata == NULL) {
6385 *pdata_return_size = 0;
6386 return NT_STATUS_NO_MEMORY;
6388 pdata = *ppdata;
6390 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6391 SSVAL(pdata,2,0); /* No fnum. */
6392 SIVAL(pdata,4,info); /* Was directory created. */
6394 switch (info_level_return) {
6395 case SMB_QUERY_FILE_UNIX_BASIC:
6396 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6397 SSVAL(pdata,10,0); /* Padding. */
6398 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6399 break;
6400 case SMB_QUERY_FILE_UNIX_INFO2:
6401 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6402 SSVAL(pdata,10,0); /* Padding. */
6403 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6404 break;
6405 default:
6406 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6407 SSVAL(pdata,10,0); /* Padding. */
6408 break;
6411 return status;
6414 /****************************************************************************
6415 Open/Create a file with POSIX semantics.
6416 ****************************************************************************/
6418 static NTSTATUS smb_posix_open(connection_struct *conn,
6419 struct smb_request *req,
6420 char **ppdata,
6421 int total_data,
6422 const char *fname,
6423 SMB_STRUCT_STAT *psbuf,
6424 int *pdata_return_size)
6426 bool extended_oplock_granted = False;
6427 char *pdata = *ppdata;
6428 uint32 flags = 0;
6429 uint32 wire_open_mode = 0;
6430 uint32 raw_unixmode = 0;
6431 uint32 mod_unixmode = 0;
6432 uint32 create_disp = 0;
6433 uint32 access_mask = 0;
6434 uint32 create_options = 0;
6435 NTSTATUS status = NT_STATUS_OK;
6436 mode_t unixmode = (mode_t)0;
6437 files_struct *fsp = NULL;
6438 int oplock_request = 0;
6439 int info = 0;
6440 uint16 info_level_return = 0;
6442 if (total_data < 18) {
6443 return NT_STATUS_INVALID_PARAMETER;
6446 flags = IVAL(pdata,0);
6447 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6448 if (oplock_request) {
6449 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6452 wire_open_mode = IVAL(pdata,4);
6454 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6455 return smb_posix_mkdir(conn, req,
6456 ppdata,
6457 total_data,
6458 fname,
6459 psbuf,
6460 pdata_return_size);
6463 switch (wire_open_mode & SMB_ACCMODE) {
6464 case SMB_O_RDONLY:
6465 access_mask = FILE_READ_DATA;
6466 break;
6467 case SMB_O_WRONLY:
6468 access_mask = FILE_WRITE_DATA;
6469 break;
6470 case SMB_O_RDWR:
6471 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6472 break;
6473 default:
6474 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6475 (unsigned int)wire_open_mode ));
6476 return NT_STATUS_INVALID_PARAMETER;
6479 wire_open_mode &= ~SMB_ACCMODE;
6481 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6482 create_disp = FILE_CREATE;
6483 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6484 create_disp = FILE_OVERWRITE_IF;
6485 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6486 create_disp = FILE_OPEN_IF;
6487 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6488 create_disp = FILE_OPEN;
6489 } else {
6490 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6491 (unsigned int)wire_open_mode ));
6492 return NT_STATUS_INVALID_PARAMETER;
6495 raw_unixmode = IVAL(pdata,8);
6496 /* Next 4 bytes are not yet defined. */
6498 status = unix_perms_from_wire(conn,
6499 psbuf,
6500 raw_unixmode,
6501 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6502 &unixmode);
6504 if (!NT_STATUS_IS_OK(status)) {
6505 return status;
6508 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6510 if (wire_open_mode & SMB_O_SYNC) {
6511 create_options |= FILE_WRITE_THROUGH;
6513 if (wire_open_mode & SMB_O_APPEND) {
6514 access_mask |= FILE_APPEND_DATA;
6516 if (wire_open_mode & SMB_O_DIRECT) {
6517 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6520 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6521 fname,
6522 (unsigned int)wire_open_mode,
6523 (unsigned int)unixmode ));
6525 status = SMB_VFS_CREATE_FILE(
6526 conn, /* conn */
6527 req, /* req */
6528 0, /* root_dir_fid */
6529 fname, /* fname */
6530 0, /* create_file_flags */
6531 access_mask, /* access_mask */
6532 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6533 FILE_SHARE_DELETE),
6534 create_disp, /* create_disposition*/
6535 FILE_NON_DIRECTORY_FILE, /* create_options */
6536 mod_unixmode, /* file_attributes */
6537 oplock_request, /* oplock_request */
6538 0, /* allocation_size */
6539 NULL, /* sd */
6540 NULL, /* ea_list */
6541 &fsp, /* result */
6542 &info, /* pinfo */
6543 psbuf); /* psbuf */
6545 if (!NT_STATUS_IS_OK(status)) {
6546 return status;
6549 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6550 extended_oplock_granted = True;
6553 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6554 extended_oplock_granted = True;
6557 info_level_return = SVAL(pdata,16);
6559 /* Allocate the correct return size. */
6561 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6562 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6563 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6564 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6565 } else {
6566 *pdata_return_size = 12;
6569 /* Realloc the data size */
6570 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6571 if (*ppdata == NULL) {
6572 close_file(req, fsp, ERROR_CLOSE);
6573 *pdata_return_size = 0;
6574 return NT_STATUS_NO_MEMORY;
6576 pdata = *ppdata;
6578 if (extended_oplock_granted) {
6579 if (flags & REQUEST_BATCH_OPLOCK) {
6580 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6581 } else {
6582 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6584 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6585 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6586 } else {
6587 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6590 SSVAL(pdata,2,fsp->fnum);
6591 SIVAL(pdata,4,info); /* Was file created etc. */
6593 switch (info_level_return) {
6594 case SMB_QUERY_FILE_UNIX_BASIC:
6595 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6596 SSVAL(pdata,10,0); /* padding. */
6597 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6598 break;
6599 case SMB_QUERY_FILE_UNIX_INFO2:
6600 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6601 SSVAL(pdata,10,0); /* padding. */
6602 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6603 break;
6604 default:
6605 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6606 SSVAL(pdata,10,0); /* padding. */
6607 break;
6609 return NT_STATUS_OK;
6612 /****************************************************************************
6613 Delete a file with POSIX semantics.
6614 ****************************************************************************/
6616 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6617 struct smb_request *req,
6618 const char *pdata,
6619 int total_data,
6620 const char *fname,
6621 SMB_STRUCT_STAT *psbuf)
6623 NTSTATUS status = NT_STATUS_OK;
6624 files_struct *fsp = NULL;
6625 uint16 flags = 0;
6626 char del = 1;
6627 int info = 0;
6628 int create_options = 0;
6629 int i;
6630 struct share_mode_lock *lck = NULL;
6632 if (total_data < 2) {
6633 return NT_STATUS_INVALID_PARAMETER;
6636 flags = SVAL(pdata,0);
6638 if (!VALID_STAT(*psbuf)) {
6639 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6642 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6643 !VALID_STAT_OF_DIR(*psbuf)) {
6644 return NT_STATUS_NOT_A_DIRECTORY;
6647 DEBUG(10,("smb_posix_unlink: %s %s\n",
6648 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6649 fname));
6651 if (VALID_STAT_OF_DIR(*psbuf)) {
6652 create_options |= FILE_DIRECTORY_FILE;
6655 status = SMB_VFS_CREATE_FILE(
6656 conn, /* conn */
6657 req, /* req */
6658 0, /* root_dir_fid */
6659 fname, /* fname */
6660 0, /* create_file_flags */
6661 DELETE_ACCESS, /* access_mask */
6662 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6663 FILE_SHARE_DELETE),
6664 FILE_OPEN, /* create_disposition*/
6665 create_options, /* create_options */
6666 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6667 0, /* oplock_request */
6668 0, /* allocation_size */
6669 NULL, /* sd */
6670 NULL, /* ea_list */
6671 &fsp, /* result */
6672 &info, /* pinfo */
6673 psbuf); /* psbuf */
6675 if (!NT_STATUS_IS_OK(status)) {
6676 return status;
6680 * Don't lie to client. If we can't really delete due to
6681 * non-POSIX opens return SHARING_VIOLATION.
6684 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6685 NULL);
6686 if (lck == NULL) {
6687 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6688 "lock for file %s\n", fsp->fsp_name));
6689 close_file(req, fsp, NORMAL_CLOSE);
6690 return NT_STATUS_INVALID_PARAMETER;
6694 * See if others still have the file open. If this is the case, then
6695 * don't delete. If all opens are POSIX delete we can set the delete
6696 * on close disposition.
6698 for (i=0; i<lck->num_share_modes; i++) {
6699 struct share_mode_entry *e = &lck->share_modes[i];
6700 if (is_valid_share_mode_entry(e)) {
6701 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6702 continue;
6704 /* Fail with sharing violation. */
6705 close_file(req, fsp, NORMAL_CLOSE);
6706 TALLOC_FREE(lck);
6707 return NT_STATUS_SHARING_VIOLATION;
6712 * Set the delete on close.
6714 status = smb_set_file_disposition_info(conn,
6715 &del,
6717 fsp,
6718 fname,
6719 psbuf);
6721 if (!NT_STATUS_IS_OK(status)) {
6722 close_file(req, fsp, NORMAL_CLOSE);
6723 TALLOC_FREE(lck);
6724 return status;
6726 TALLOC_FREE(lck);
6727 return close_file(req, fsp, NORMAL_CLOSE);
6730 /****************************************************************************
6731 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6732 ****************************************************************************/
6734 static void call_trans2setfilepathinfo(connection_struct *conn,
6735 struct smb_request *req,
6736 unsigned int tran_call,
6737 char **pparams, int total_params,
6738 char **ppdata, int total_data,
6739 unsigned int max_data_bytes)
6741 char *params = *pparams;
6742 char *pdata = *ppdata;
6743 uint16 info_level;
6744 SMB_STRUCT_STAT sbuf;
6745 char *fname = NULL;
6746 files_struct *fsp = NULL;
6747 NTSTATUS status = NT_STATUS_OK;
6748 int data_return_size = 0;
6749 TALLOC_CTX *ctx = talloc_tos();
6751 if (!params) {
6752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6753 return;
6756 ZERO_STRUCT(sbuf);
6758 if (tran_call == TRANSACT2_SETFILEINFO) {
6759 if (total_params < 4) {
6760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6761 return;
6764 fsp = file_fsp(req, SVAL(params,0));
6765 /* Basic check for non-null fsp. */
6766 if (!check_fsp_open(conn, req, fsp)) {
6767 return;
6769 info_level = SVAL(params,2);
6771 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6772 if (!fname) {
6773 reply_nterror(req, NT_STATUS_NO_MEMORY);
6774 return;
6777 if(fsp->is_directory || fsp->fh->fd == -1) {
6779 * This is actually a SETFILEINFO on a directory
6780 * handle (returned from an NT SMB). NT5.0 seems
6781 * to do this call. JRA.
6783 if (INFO_LEVEL_IS_UNIX(info_level)) {
6784 /* Always do lstat for UNIX calls. */
6785 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6786 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6787 reply_unixerror(req,ERRDOS,ERRbadpath);
6788 return;
6790 } else {
6791 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6792 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6793 reply_unixerror(req,ERRDOS,ERRbadpath);
6794 return;
6797 } else if (fsp->print_file) {
6799 * Doing a DELETE_ON_CLOSE should cancel a print job.
6801 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6802 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6804 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6806 SSVAL(params,0,0);
6807 send_trans2_replies(conn, req, params, 2,
6808 *ppdata, 0,
6809 max_data_bytes);
6810 return;
6811 } else {
6812 reply_unixerror(req, ERRDOS, ERRbadpath);
6813 return;
6815 } else {
6817 * Original code - this is an open file.
6819 if (!check_fsp(conn, req, fsp)) {
6820 return;
6823 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6824 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6825 reply_unixerror(req, ERRDOS, ERRbadfid);
6826 return;
6829 } else {
6830 /* set path info */
6831 if (total_params < 7) {
6832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6833 return;
6836 info_level = SVAL(params,0);
6837 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6838 total_params - 6, STR_TERMINATE,
6839 &status);
6840 if (!NT_STATUS_IS_OK(status)) {
6841 reply_nterror(req, status);
6842 return;
6845 status = resolve_dfspath(ctx, conn,
6846 req->flags2 & FLAGS2_DFS_PATHNAMES,
6847 fname,
6848 &fname);
6849 if (!NT_STATUS_IS_OK(status)) {
6850 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6851 reply_botherror(req,
6852 NT_STATUS_PATH_NOT_COVERED,
6853 ERRSRV, ERRbadpath);
6854 return;
6856 reply_nterror(req, status);
6857 return;
6860 status = unix_convert(ctx, conn, fname, False,
6861 &fname, NULL, &sbuf);
6862 if (!NT_STATUS_IS_OK(status)) {
6863 reply_nterror(req, status);
6864 return;
6867 status = check_name(conn, fname);
6868 if (!NT_STATUS_IS_OK(status)) {
6869 reply_nterror(req, status);
6870 return;
6873 if (INFO_LEVEL_IS_UNIX(info_level)) {
6875 * For CIFS UNIX extensions the target name may not exist.
6878 /* Always do lstat for UNIX calls. */
6879 SMB_VFS_LSTAT(conn,fname,&sbuf);
6881 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6882 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6883 reply_unixerror(req, ERRDOS, ERRbadpath);
6884 return;
6888 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6889 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6890 return;
6893 if (!CAN_WRITE(conn)) {
6894 /* Allow POSIX opens. The open path will deny
6895 * any non-readonly opens. */
6896 if (info_level != SMB_POSIX_PATH_OPEN) {
6897 reply_doserror(req, ERRSRV, ERRaccess);
6898 return;
6902 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6903 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6905 /* Realloc the parameter size */
6906 *pparams = (char *)SMB_REALLOC(*pparams,2);
6907 if (*pparams == NULL) {
6908 reply_nterror(req, NT_STATUS_NO_MEMORY);
6909 return;
6911 params = *pparams;
6913 SSVAL(params,0,0);
6915 switch (info_level) {
6917 case SMB_INFO_STANDARD:
6919 status = smb_set_info_standard(conn,
6920 pdata,
6921 total_data,
6922 fsp,
6923 fname,
6924 &sbuf);
6925 break;
6928 case SMB_INFO_SET_EA:
6930 status = smb_info_set_ea(conn,
6931 pdata,
6932 total_data,
6933 fsp,
6934 fname);
6935 break;
6938 case SMB_SET_FILE_BASIC_INFO:
6939 case SMB_FILE_BASIC_INFORMATION:
6941 status = smb_set_file_basic_info(conn,
6942 pdata,
6943 total_data,
6944 fsp,
6945 fname,
6946 &sbuf);
6947 break;
6950 case SMB_FILE_ALLOCATION_INFORMATION:
6951 case SMB_SET_FILE_ALLOCATION_INFO:
6953 status = smb_set_file_allocation_info(conn, req,
6954 pdata,
6955 total_data,
6956 fsp,
6957 fname,
6958 &sbuf);
6959 break;
6962 case SMB_FILE_END_OF_FILE_INFORMATION:
6963 case SMB_SET_FILE_END_OF_FILE_INFO:
6965 status = smb_set_file_end_of_file_info(conn, req,
6966 pdata,
6967 total_data,
6968 fsp,
6969 fname,
6970 &sbuf);
6971 break;
6974 case SMB_FILE_DISPOSITION_INFORMATION:
6975 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6977 #if 0
6978 /* JRA - We used to just ignore this on a path ?
6979 * Shouldn't this be invalid level on a pathname
6980 * based call ?
6982 if (tran_call != TRANSACT2_SETFILEINFO) {
6983 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6985 #endif
6986 status = smb_set_file_disposition_info(conn,
6987 pdata,
6988 total_data,
6989 fsp,
6990 fname,
6991 &sbuf);
6992 break;
6995 case SMB_FILE_POSITION_INFORMATION:
6997 status = smb_file_position_information(conn,
6998 pdata,
6999 total_data,
7000 fsp);
7001 break;
7004 /* From tridge Samba4 :
7005 * MODE_INFORMATION in setfileinfo (I have no
7006 * idea what "mode information" on a file is - it takes a value of 0,
7007 * 2, 4 or 6. What could it be?).
7010 case SMB_FILE_MODE_INFORMATION:
7012 status = smb_file_mode_information(conn,
7013 pdata,
7014 total_data);
7015 break;
7019 * CIFS UNIX extensions.
7022 case SMB_SET_FILE_UNIX_BASIC:
7024 status = smb_set_file_unix_basic(conn, req,
7025 pdata,
7026 total_data,
7027 fsp,
7028 fname,
7029 &sbuf);
7030 break;
7033 case SMB_SET_FILE_UNIX_INFO2:
7035 status = smb_set_file_unix_info2(conn, req,
7036 pdata,
7037 total_data,
7038 fsp,
7039 fname,
7040 &sbuf);
7041 break;
7044 case SMB_SET_FILE_UNIX_LINK:
7046 if (tran_call != TRANSACT2_SETPATHINFO) {
7047 /* We must have a pathname for this. */
7048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7049 return;
7051 status = smb_set_file_unix_link(conn, req, pdata,
7052 total_data, fname);
7053 break;
7056 case SMB_SET_FILE_UNIX_HLINK:
7058 if (tran_call != TRANSACT2_SETPATHINFO) {
7059 /* We must have a pathname for this. */
7060 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7061 return;
7063 status = smb_set_file_unix_hlink(conn, req,
7064 pdata, total_data,
7065 fname);
7066 break;
7069 case SMB_FILE_RENAME_INFORMATION:
7071 status = smb_file_rename_information(conn, req,
7072 pdata, total_data,
7073 fsp, fname);
7074 break;
7077 #if defined(HAVE_POSIX_ACLS)
7078 case SMB_SET_POSIX_ACL:
7080 status = smb_set_posix_acl(conn,
7081 pdata,
7082 total_data,
7083 fsp,
7084 fname,
7085 &sbuf);
7086 break;
7088 #endif
7090 case SMB_SET_POSIX_LOCK:
7092 if (tran_call != TRANSACT2_SETFILEINFO) {
7093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7094 return;
7096 status = smb_set_posix_lock(conn, req,
7097 pdata, total_data, fsp);
7098 break;
7101 case SMB_POSIX_PATH_OPEN:
7103 if (tran_call != TRANSACT2_SETPATHINFO) {
7104 /* We must have a pathname for this. */
7105 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7106 return;
7109 status = smb_posix_open(conn, req,
7110 ppdata,
7111 total_data,
7112 fname,
7113 &sbuf,
7114 &data_return_size);
7115 break;
7118 case SMB_POSIX_PATH_UNLINK:
7120 if (tran_call != TRANSACT2_SETPATHINFO) {
7121 /* We must have a pathname for this. */
7122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7123 return;
7126 status = smb_posix_unlink(conn, req,
7127 pdata,
7128 total_data,
7129 fname,
7130 &sbuf);
7131 break;
7134 default:
7135 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7136 return;
7140 if (!NT_STATUS_IS_OK(status)) {
7141 if (open_was_deferred(req->mid)) {
7142 /* We have re-scheduled this call. */
7143 return;
7145 if (blocking_lock_was_deferred(req->mid)) {
7146 /* We have re-scheduled this call. */
7147 return;
7149 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7150 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7151 ERRSRV, ERRbadpath);
7152 return;
7154 if (info_level == SMB_POSIX_PATH_OPEN) {
7155 reply_openerror(req, status);
7156 return;
7159 reply_nterror(req, status);
7160 return;
7163 SSVAL(params,0,0);
7164 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7165 max_data_bytes);
7167 return;
7170 /****************************************************************************
7171 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7172 ****************************************************************************/
7174 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7175 char **pparams, int total_params,
7176 char **ppdata, int total_data,
7177 unsigned int max_data_bytes)
7179 char *params = *pparams;
7180 char *pdata = *ppdata;
7181 char *directory = NULL;
7182 SMB_STRUCT_STAT sbuf;
7183 NTSTATUS status = NT_STATUS_OK;
7184 struct ea_list *ea_list = NULL;
7185 TALLOC_CTX *ctx = talloc_tos();
7187 if (!CAN_WRITE(conn)) {
7188 reply_doserror(req, ERRSRV, ERRaccess);
7189 return;
7192 if (total_params < 5) {
7193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7194 return;
7197 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7198 total_params - 4, STR_TERMINATE,
7199 &status);
7200 if (!NT_STATUS_IS_OK(status)) {
7201 reply_nterror(req, status);
7202 return;
7205 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7207 status = resolve_dfspath(ctx,
7208 conn,
7209 req->flags2 & FLAGS2_DFS_PATHNAMES,
7210 directory,
7211 &directory);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7214 reply_botherror(req,
7215 NT_STATUS_PATH_NOT_COVERED,
7216 ERRSRV, ERRbadpath);
7218 reply_nterror(req, status);
7219 return;
7222 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7223 if (!NT_STATUS_IS_OK(status)) {
7224 reply_nterror(req, status);
7225 return;
7228 status = check_name(conn, directory);
7229 if (!NT_STATUS_IS_OK(status)) {
7230 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7231 reply_nterror(req, status);
7232 return;
7235 /* Any data in this call is an EA list. */
7236 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7237 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7238 return;
7242 * OS/2 workplace shell seems to send SET_EA requests of "null"
7243 * length (4 bytes containing IVAL 4).
7244 * They seem to have no effect. Bug #3212. JRA.
7247 if (total_data != 4) {
7248 if (total_data < 10) {
7249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7250 return;
7253 if (IVAL(pdata,0) > total_data) {
7254 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7255 IVAL(pdata,0), (unsigned int)total_data));
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7257 return;
7260 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7261 total_data - 4);
7262 if (!ea_list) {
7263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7264 return;
7267 /* If total_data == 4 Windows doesn't care what values
7268 * are placed in that field, it just ignores them.
7269 * The System i QNTC IBM SMB client puts bad values here,
7270 * so ignore them. */
7272 status = create_directory(conn, req, directory);
7274 if (!NT_STATUS_IS_OK(status)) {
7275 reply_nterror(req, status);
7276 return;
7279 /* Try and set any given EA. */
7280 if (ea_list) {
7281 status = set_ea(conn, NULL, directory, ea_list);
7282 if (!NT_STATUS_IS_OK(status)) {
7283 reply_nterror(req, status);
7284 return;
7288 /* Realloc the parameter and data sizes */
7289 *pparams = (char *)SMB_REALLOC(*pparams,2);
7290 if(*pparams == NULL) {
7291 reply_nterror(req, NT_STATUS_NO_MEMORY);
7292 return;
7294 params = *pparams;
7296 SSVAL(params,0,0);
7298 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7300 return;
7303 /****************************************************************************
7304 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7305 We don't actually do this - we just send a null response.
7306 ****************************************************************************/
7308 static void call_trans2findnotifyfirst(connection_struct *conn,
7309 struct smb_request *req,
7310 char **pparams, int total_params,
7311 char **ppdata, int total_data,
7312 unsigned int max_data_bytes)
7314 char *params = *pparams;
7315 uint16 info_level;
7317 if (total_params < 6) {
7318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 return;
7322 info_level = SVAL(params,4);
7323 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7325 switch (info_level) {
7326 case 1:
7327 case 2:
7328 break;
7329 default:
7330 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7331 return;
7334 /* Realloc the parameter and data sizes */
7335 *pparams = (char *)SMB_REALLOC(*pparams,6);
7336 if (*pparams == NULL) {
7337 reply_nterror(req, NT_STATUS_NO_MEMORY);
7338 return;
7340 params = *pparams;
7342 SSVAL(params,0,fnf_handle);
7343 SSVAL(params,2,0); /* No changes */
7344 SSVAL(params,4,0); /* No EA errors */
7346 fnf_handle++;
7348 if(fnf_handle == 0)
7349 fnf_handle = 257;
7351 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7353 return;
7356 /****************************************************************************
7357 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7358 changes). Currently this does nothing.
7359 ****************************************************************************/
7361 static void call_trans2findnotifynext(connection_struct *conn,
7362 struct smb_request *req,
7363 char **pparams, int total_params,
7364 char **ppdata, int total_data,
7365 unsigned int max_data_bytes)
7367 char *params = *pparams;
7369 DEBUG(3,("call_trans2findnotifynext\n"));
7371 /* Realloc the parameter and data sizes */
7372 *pparams = (char *)SMB_REALLOC(*pparams,4);
7373 if (*pparams == NULL) {
7374 reply_nterror(req, NT_STATUS_NO_MEMORY);
7375 return;
7377 params = *pparams;
7379 SSVAL(params,0,0); /* No changes */
7380 SSVAL(params,2,0); /* No EA errors */
7382 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7384 return;
7387 /****************************************************************************
7388 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7389 ****************************************************************************/
7391 static void call_trans2getdfsreferral(connection_struct *conn,
7392 struct smb_request *req,
7393 char **pparams, int total_params,
7394 char **ppdata, int total_data,
7395 unsigned int max_data_bytes)
7397 char *params = *pparams;
7398 char *pathname = NULL;
7399 int reply_size = 0;
7400 int max_referral_level;
7401 NTSTATUS status = NT_STATUS_OK;
7402 TALLOC_CTX *ctx = talloc_tos();
7404 DEBUG(10,("call_trans2getdfsreferral\n"));
7406 if (total_params < 3) {
7407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7408 return;
7411 max_referral_level = SVAL(params,0);
7413 if(!lp_host_msdfs()) {
7414 reply_doserror(req, ERRDOS, ERRbadfunc);
7415 return;
7418 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7419 total_params - 2, STR_TERMINATE);
7420 if (!pathname) {
7421 reply_nterror(req, NT_STATUS_NOT_FOUND);
7422 return;
7424 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7425 ppdata,&status)) < 0) {
7426 reply_nterror(req, status);
7427 return;
7430 SSVAL(req->inbuf, smb_flg2,
7431 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7432 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7434 return;
7437 #define LMCAT_SPL 0x53
7438 #define LMFUNC_GETJOBID 0x60
7440 /****************************************************************************
7441 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7442 ****************************************************************************/
7444 static void call_trans2ioctl(connection_struct *conn,
7445 struct smb_request *req,
7446 char **pparams, int total_params,
7447 char **ppdata, int total_data,
7448 unsigned int max_data_bytes)
7450 char *pdata = *ppdata;
7451 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7453 /* check for an invalid fid before proceeding */
7455 if (!fsp) {
7456 reply_doserror(req, ERRDOS, ERRbadfid);
7457 return;
7460 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7461 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7462 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7463 if (*ppdata == NULL) {
7464 reply_nterror(req, NT_STATUS_NO_MEMORY);
7465 return;
7467 pdata = *ppdata;
7469 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7470 CAN ACCEPT THIS IN UNICODE. JRA. */
7472 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7473 srvstr_push(pdata, req->flags2, pdata + 2,
7474 global_myname(), 15,
7475 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7476 srvstr_push(pdata, req->flags2, pdata+18,
7477 lp_servicename(SNUM(conn)), 13,
7478 STR_ASCII|STR_TERMINATE); /* Service name */
7479 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7480 max_data_bytes);
7481 return;
7484 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7485 reply_doserror(req, ERRSRV, ERRerror);
7488 /****************************************************************************
7489 Reply to a SMBfindclose (stop trans2 directory search).
7490 ****************************************************************************/
7492 void reply_findclose(struct smb_request *req)
7494 int dptr_num;
7496 START_PROFILE(SMBfindclose);
7498 if (req->wct < 1) {
7499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7500 END_PROFILE(SMBfindclose);
7501 return;
7504 dptr_num = SVALS(req->vwv+0, 0);
7506 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7508 dptr_close(&dptr_num);
7510 reply_outbuf(req, 0, 0);
7512 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7514 END_PROFILE(SMBfindclose);
7515 return;
7518 /****************************************************************************
7519 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7520 ****************************************************************************/
7522 void reply_findnclose(struct smb_request *req)
7524 int dptr_num;
7526 START_PROFILE(SMBfindnclose);
7528 if (req->wct < 1) {
7529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7530 END_PROFILE(SMBfindnclose);
7531 return;
7534 dptr_num = SVAL(req->vwv+0, 0);
7536 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7538 /* We never give out valid handles for a
7539 findnotifyfirst - so any dptr_num is ok here.
7540 Just ignore it. */
7542 reply_outbuf(req, 0, 0);
7544 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7546 END_PROFILE(SMBfindnclose);
7547 return;
7550 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7551 struct trans_state *state)
7553 if (Protocol >= PROTOCOL_NT1) {
7554 req->flags2 |= 0x40; /* IS_LONG_NAME */
7555 SSVAL(req->inbuf,smb_flg2,req->flags2);
7558 if (conn->encrypt_level == Required && !req->encrypted) {
7559 if (state->call != TRANSACT2_QFSINFO &&
7560 state->call != TRANSACT2_SETFSINFO) {
7561 DEBUG(0,("handle_trans2: encryption required "
7562 "with call 0x%x\n",
7563 (unsigned int)state->call));
7564 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7565 return;
7569 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7571 /* Now we must call the relevant TRANS2 function */
7572 switch(state->call) {
7573 case TRANSACT2_OPEN:
7575 START_PROFILE(Trans2_open);
7576 call_trans2open(conn, req,
7577 &state->param, state->total_param,
7578 &state->data, state->total_data,
7579 state->max_data_return);
7580 END_PROFILE(Trans2_open);
7581 break;
7584 case TRANSACT2_FINDFIRST:
7586 START_PROFILE(Trans2_findfirst);
7587 call_trans2findfirst(conn, req,
7588 &state->param, state->total_param,
7589 &state->data, state->total_data,
7590 state->max_data_return);
7591 END_PROFILE(Trans2_findfirst);
7592 break;
7595 case TRANSACT2_FINDNEXT:
7597 START_PROFILE(Trans2_findnext);
7598 call_trans2findnext(conn, req,
7599 &state->param, state->total_param,
7600 &state->data, state->total_data,
7601 state->max_data_return);
7602 END_PROFILE(Trans2_findnext);
7603 break;
7606 case TRANSACT2_QFSINFO:
7608 START_PROFILE(Trans2_qfsinfo);
7609 call_trans2qfsinfo(conn, req,
7610 &state->param, state->total_param,
7611 &state->data, state->total_data,
7612 state->max_data_return);
7613 END_PROFILE(Trans2_qfsinfo);
7614 break;
7617 case TRANSACT2_SETFSINFO:
7619 START_PROFILE(Trans2_setfsinfo);
7620 call_trans2setfsinfo(conn, req,
7621 &state->param, state->total_param,
7622 &state->data, state->total_data,
7623 state->max_data_return);
7624 END_PROFILE(Trans2_setfsinfo);
7625 break;
7628 case TRANSACT2_QPATHINFO:
7629 case TRANSACT2_QFILEINFO:
7631 START_PROFILE(Trans2_qpathinfo);
7632 call_trans2qfilepathinfo(conn, req, state->call,
7633 &state->param, state->total_param,
7634 &state->data, state->total_data,
7635 state->max_data_return);
7636 END_PROFILE(Trans2_qpathinfo);
7637 break;
7640 case TRANSACT2_SETPATHINFO:
7641 case TRANSACT2_SETFILEINFO:
7643 START_PROFILE(Trans2_setpathinfo);
7644 call_trans2setfilepathinfo(conn, req, state->call,
7645 &state->param, state->total_param,
7646 &state->data, state->total_data,
7647 state->max_data_return);
7648 END_PROFILE(Trans2_setpathinfo);
7649 break;
7652 case TRANSACT2_FINDNOTIFYFIRST:
7654 START_PROFILE(Trans2_findnotifyfirst);
7655 call_trans2findnotifyfirst(conn, req,
7656 &state->param, state->total_param,
7657 &state->data, state->total_data,
7658 state->max_data_return);
7659 END_PROFILE(Trans2_findnotifyfirst);
7660 break;
7663 case TRANSACT2_FINDNOTIFYNEXT:
7665 START_PROFILE(Trans2_findnotifynext);
7666 call_trans2findnotifynext(conn, req,
7667 &state->param, state->total_param,
7668 &state->data, state->total_data,
7669 state->max_data_return);
7670 END_PROFILE(Trans2_findnotifynext);
7671 break;
7674 case TRANSACT2_MKDIR:
7676 START_PROFILE(Trans2_mkdir);
7677 call_trans2mkdir(conn, req,
7678 &state->param, state->total_param,
7679 &state->data, state->total_data,
7680 state->max_data_return);
7681 END_PROFILE(Trans2_mkdir);
7682 break;
7685 case TRANSACT2_GET_DFS_REFERRAL:
7687 START_PROFILE(Trans2_get_dfs_referral);
7688 call_trans2getdfsreferral(conn, req,
7689 &state->param, state->total_param,
7690 &state->data, state->total_data,
7691 state->max_data_return);
7692 END_PROFILE(Trans2_get_dfs_referral);
7693 break;
7696 case TRANSACT2_IOCTL:
7698 START_PROFILE(Trans2_ioctl);
7699 call_trans2ioctl(conn, req,
7700 &state->param, state->total_param,
7701 &state->data, state->total_data,
7702 state->max_data_return);
7703 END_PROFILE(Trans2_ioctl);
7704 break;
7707 default:
7708 /* Error in request */
7709 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7710 reply_doserror(req, ERRSRV,ERRerror);
7714 /****************************************************************************
7715 Reply to a SMBtrans2.
7716 ****************************************************************************/
7718 void reply_trans2(struct smb_request *req)
7720 connection_struct *conn = req->conn;
7721 unsigned int dsoff;
7722 unsigned int dscnt;
7723 unsigned int psoff;
7724 unsigned int pscnt;
7725 unsigned int tran_call;
7726 struct trans_state *state;
7727 NTSTATUS result;
7729 START_PROFILE(SMBtrans2);
7731 if (req->wct < 14) {
7732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7733 END_PROFILE(SMBtrans2);
7734 return;
7737 dsoff = SVAL(req->vwv+12, 0);
7738 dscnt = SVAL(req->vwv+11, 0);
7739 psoff = SVAL(req->vwv+10, 0);
7740 pscnt = SVAL(req->vwv+9, 0);
7741 tran_call = SVAL(req->vwv+14, 0);
7743 result = allow_new_trans(conn->pending_trans, req->mid);
7744 if (!NT_STATUS_IS_OK(result)) {
7745 DEBUG(2, ("Got invalid trans2 request: %s\n",
7746 nt_errstr(result)));
7747 reply_nterror(req, result);
7748 END_PROFILE(SMBtrans2);
7749 return;
7752 if (IS_IPC(conn)) {
7753 switch (tran_call) {
7754 /* List the allowed trans2 calls on IPC$ */
7755 case TRANSACT2_OPEN:
7756 case TRANSACT2_GET_DFS_REFERRAL:
7757 case TRANSACT2_QFILEINFO:
7758 case TRANSACT2_QFSINFO:
7759 case TRANSACT2_SETFSINFO:
7760 break;
7761 default:
7762 reply_doserror(req, ERRSRV, ERRaccess);
7763 END_PROFILE(SMBtrans2);
7764 return;
7768 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7769 DEBUG(0, ("talloc failed\n"));
7770 reply_nterror(req, NT_STATUS_NO_MEMORY);
7771 END_PROFILE(SMBtrans2);
7772 return;
7775 state->cmd = SMBtrans2;
7777 state->mid = req->mid;
7778 state->vuid = req->vuid;
7779 state->setup_count = SVAL(req->vwv+13, 0);
7780 state->setup = NULL;
7781 state->total_param = SVAL(req->vwv+0, 0);
7782 state->param = NULL;
7783 state->total_data = SVAL(req->vwv+1, 0);
7784 state->data = NULL;
7785 state->max_param_return = SVAL(req->vwv+2, 0);
7786 state->max_data_return = SVAL(req->vwv+3, 0);
7787 state->max_setup_return = SVAL(req->vwv+4, 0);
7788 state->close_on_completion = BITSETW(req->vwv+5, 0);
7789 state->one_way = BITSETW(req->vwv+5, 1);
7791 state->call = tran_call;
7793 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7794 is so as a sanity check */
7795 if (state->setup_count != 1) {
7797 * Need to have rc=0 for ioctl to get job id for OS/2.
7798 * Network printing will fail if function is not successful.
7799 * Similar function in reply.c will be used if protocol
7800 * is LANMAN1.0 instead of LM1.2X002.
7801 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7802 * outbuf doesn't have to be set(only job id is used).
7804 if ( (state->setup_count == 4)
7805 && (tran_call == TRANSACT2_IOCTL)
7806 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7807 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7808 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7809 } else {
7810 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7811 DEBUG(2,("Transaction is %d\n",tran_call));
7812 TALLOC_FREE(state);
7813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7814 END_PROFILE(SMBtrans2);
7815 return;
7819 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7820 goto bad_param;
7822 if (state->total_data) {
7824 if (trans_oob(state->total_data, 0, dscnt)
7825 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7826 goto bad_param;
7829 /* Can't use talloc here, the core routines do realloc on the
7830 * params and data. */
7831 state->data = (char *)SMB_MALLOC(state->total_data);
7832 if (state->data == NULL) {
7833 DEBUG(0,("reply_trans2: data malloc fail for %u "
7834 "bytes !\n", (unsigned int)state->total_data));
7835 TALLOC_FREE(state);
7836 reply_nterror(req, NT_STATUS_NO_MEMORY);
7837 END_PROFILE(SMBtrans2);
7838 return;
7841 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7844 if (state->total_param) {
7846 if (trans_oob(state->total_param, 0, pscnt)
7847 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7848 goto bad_param;
7851 /* Can't use talloc here, the core routines do realloc on the
7852 * params and data. */
7853 state->param = (char *)SMB_MALLOC(state->total_param);
7854 if (state->param == NULL) {
7855 DEBUG(0,("reply_trans: param malloc fail for %u "
7856 "bytes !\n", (unsigned int)state->total_param));
7857 SAFE_FREE(state->data);
7858 TALLOC_FREE(state);
7859 reply_nterror(req, NT_STATUS_NO_MEMORY);
7860 END_PROFILE(SMBtrans2);
7861 return;
7864 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7867 state->received_data = dscnt;
7868 state->received_param = pscnt;
7870 if ((state->received_param == state->total_param) &&
7871 (state->received_data == state->total_data)) {
7873 handle_trans2(conn, req, state);
7875 SAFE_FREE(state->data);
7876 SAFE_FREE(state->param);
7877 TALLOC_FREE(state);
7878 END_PROFILE(SMBtrans2);
7879 return;
7882 DLIST_ADD(conn->pending_trans, state);
7884 /* We need to send an interim response then receive the rest
7885 of the parameter/data bytes */
7886 reply_outbuf(req, 0, 0);
7887 show_msg((char *)req->outbuf);
7888 END_PROFILE(SMBtrans2);
7889 return;
7891 bad_param:
7893 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7894 SAFE_FREE(state->data);
7895 SAFE_FREE(state->param);
7896 TALLOC_FREE(state);
7897 END_PROFILE(SMBtrans2);
7898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7902 /****************************************************************************
7903 Reply to a SMBtranss2
7904 ****************************************************************************/
7906 void reply_transs2(struct smb_request *req)
7908 connection_struct *conn = req->conn;
7909 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7910 struct trans_state *state;
7912 START_PROFILE(SMBtranss2);
7914 show_msg((char *)req->inbuf);
7916 if (req->wct < 8) {
7917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7918 END_PROFILE(SMBtranss2);
7919 return;
7922 for (state = conn->pending_trans; state != NULL;
7923 state = state->next) {
7924 if (state->mid == req->mid) {
7925 break;
7929 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7931 END_PROFILE(SMBtranss2);
7932 return;
7935 /* Revise state->total_param and state->total_data in case they have
7936 changed downwards */
7938 if (SVAL(req->vwv+0, 0) < state->total_param)
7939 state->total_param = SVAL(req->vwv+0, 0);
7940 if (SVAL(req->vwv+1, 0) < state->total_data)
7941 state->total_data = SVAL(req->vwv+1, 0);
7943 pcnt = SVAL(req->vwv+2, 0);
7944 poff = SVAL(req->vwv+3, 0);
7945 pdisp = SVAL(req->vwv+4, 0);
7947 dcnt = SVAL(req->vwv+5, 0);
7948 doff = SVAL(req->vwv+6, 0);
7949 ddisp = SVAL(req->vwv+7, 0);
7951 state->received_param += pcnt;
7952 state->received_data += dcnt;
7954 if ((state->received_data > state->total_data) ||
7955 (state->received_param > state->total_param))
7956 goto bad_param;
7958 if (pcnt) {
7959 if (trans_oob(state->total_param, pdisp, pcnt)
7960 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7961 goto bad_param;
7963 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7966 if (dcnt) {
7967 if (trans_oob(state->total_data, ddisp, dcnt)
7968 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7969 goto bad_param;
7971 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7974 if ((state->received_param < state->total_param) ||
7975 (state->received_data < state->total_data)) {
7976 END_PROFILE(SMBtranss2);
7977 return;
7980 handle_trans2(conn, req, state);
7982 DLIST_REMOVE(conn->pending_trans, state);
7983 SAFE_FREE(state->data);
7984 SAFE_FREE(state->param);
7985 TALLOC_FREE(state);
7987 END_PROFILE(SMBtranss2);
7988 return;
7990 bad_param:
7992 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7993 DLIST_REMOVE(conn->pending_trans, state);
7994 SAFE_FREE(state->data);
7995 SAFE_FREE(state->param);
7996 TALLOC_FREE(state);
7997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7998 END_PROFILE(SMBtranss2);
7999 return;