Fix the build of nfs4_acls.c
[Samba.git] / source3 / smbd / trans2.c
blob1d95c207bafc9c8c6a4b488457841c69bf4e6a50
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"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
75 NULL
78 int i;
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
82 return true;
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
86 return true;
88 return false;
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
101 char *val = NULL;
102 ssize_t sizeret;
104 again:
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107 if (!val) {
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113 } else {
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
118 attr_size = 65536;
119 goto again;
122 if (sizeret == -1) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
129 pea->flags = 0;
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132 } else {
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
136 TALLOC_FREE(val);
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
141 return NT_STATUS_OK;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
152 char *p;
153 char **names, **tmp;
154 size_t num_names;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
158 *pnames = NULL;
159 *pnum_names = 0;
160 return NT_STATUS_OK;
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
168 if (names == NULL) {
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
179 TALLOC_FREE(names);
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
185 ea_namelist_size);
186 } else {
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
188 ea_namelist_size);
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
194 else {
195 break;
199 if (sizeret == -1) {
200 TALLOC_FREE(names);
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
207 if (sizeret == 0) {
208 TALLOC_FREE(names);
209 *pnames = NULL;
210 *pnum_names = 0;
211 return NT_STATUS_OK;
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
219 TALLOC_FREE(names);
220 return NT_STATUS_INTERNAL_ERROR;
224 * count the names
226 num_names = 0;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
229 num_names += 1;
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
233 if (tmp == NULL) {
234 DEBUG(0, ("talloc failed\n"));
235 TALLOC_FREE(names);
236 return NT_STATUS_NO_MEMORY;
239 names = tmp;
240 num_names = 0;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
246 *pnames = names;
247 *pnum_names = num_names;
248 return NT_STATUS_OK;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
259 size_t i, num_names;
260 char **names;
261 struct ea_list *ea_list_head = NULL;
262 NTSTATUS status;
264 *pea_total_len = 0;
266 if (!lp_ea_support(SNUM(conn))) {
267 return NULL;
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
271 &names, &num_names);
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
274 return NULL;
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
279 fstring dos_ea_name;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
283 continue;
285 listp = TALLOC_P(mem_ctx, struct ea_list);
286 if (listp == NULL) {
287 return NULL;
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
291 fname, names[i],
292 &listp->ea))) {
293 return NULL;
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
298 *pea_total_len +=
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
311 *pea_total_len += 4;
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
317 return ea_list_head;
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
322 that was filled.
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
329 char *p = pdata;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
334 SIVAL(pdata,4,0);
335 return 4;
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
339 size_t dos_namelen;
340 fstring dos_ea_name;
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
344 break;
346 if (ea_list->ea.value.length > 65535) {
347 break;
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
350 break;
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
376 return 0;
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
380 return total_ea_len;
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
389 size_t total_ea_len;
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
398 break;
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED;
413 for (;ea_list; ea_list = ea_list->next) {
414 int ret;
415 fstring unix_ea_name;
417 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name, ea_list->ea.name);
420 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
424 if (samba_private_attr_name(unix_ea_name)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426 return NT_STATUS_ACCESS_DENIED;
429 if (ea_list->ea.value.length == 0) {
430 /* Remove the attribute. */
431 if (fsp && (fsp->fh->fd != -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name, fsp->fsp_name));
434 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
435 } else {
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name, fname));
438 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
440 #ifdef ENOATTR
441 /* Removing a non existent attribute always succeeds. */
442 if (ret == -1 && errno == ENOATTR) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
444 unix_ea_name));
445 ret = 0;
447 #endif
448 } else {
449 if (fsp && (fsp->fh->fd != -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name, fsp->fsp_name));
452 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453 ea_list->ea.value.data, ea_list->ea.value.length, 0);
454 } else {
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name, fname));
457 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458 ea_list->ea.value.data, ea_list->ea.value.length, 0);
462 if (ret == -1) {
463 #ifdef ENOTSUP
464 if (errno == ENOTSUP) {
465 return NT_STATUS_EAS_NOT_SUPPORTED;
467 #endif
468 return map_nt_error_from_unix(errno);
472 return NT_STATUS_OK;
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
481 size_t converted_size, offset = 0;
483 while (offset + 2 < data_size) {
484 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485 unsigned int namelen = CVAL(pdata,offset);
487 offset++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491 (offset > data_size) || (namelen > data_size) ||
492 (offset + namelen >= data_size)) {
493 break;
495 /* Ensure the name is null terminated. */
496 if (pdata[offset + namelen] != '\0') {
497 return NULL;
499 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
500 &converted_size)) {
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno)));
504 if (!eal->ea.name) {
505 return NULL;
508 offset += (namelen + 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
513 return ea_list_head;
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
522 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
523 uint16 val_len;
524 unsigned int namelen;
525 size_t converted_size;
527 if (!eal) {
528 return NULL;
531 if (data_size < 6) {
532 return NULL;
535 eal->ea.flags = CVAL(pdata,0);
536 namelen = CVAL(pdata,1);
537 val_len = SVAL(pdata,2);
539 if (4 + namelen + 1 + val_len > data_size) {
540 return NULL;
543 /* Ensure the name is null terminated. */
544 if (pdata[namelen + 4] != '\0') {
545 return NULL;
547 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
549 strerror(errno)));
551 if (!eal->ea.name) {
552 return NULL;
555 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556 if (!eal->ea.value.data) {
557 return NULL;
560 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal->ea.value.data[val_len] = '\0';
564 /* But don't count the null. */
565 eal->ea.value.length--;
567 if (pbytes_used) {
568 *pbytes_used = 4 + namelen + 1 + val_len;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572 dump_data(10, eal->ea.value.data, eal->ea.value.length);
574 return eal;
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
584 size_t offset = 0;
585 size_t bytes_used = 0;
587 while (offset < data_size) {
588 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
590 if (!eal) {
591 return NULL;
594 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595 offset += bytes_used;
598 return ea_list_head;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list *ealist)
607 fstring dos_ea_name;
608 struct ea_list *listp;
609 size_t ret = 0;
611 for (listp = ealist; listp; listp = listp->next) {
612 push_ascii_fstring(dos_ea_name, listp->ea.name);
613 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
615 /* Add on 4 for total length. */
616 if (ret) {
617 ret += 4;
620 return ret;
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
631 struct ea_list *nlistp, *flistp;
633 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634 for (flistp = file_list; flistp; flistp = flistp->next) {
635 if (strequal(nlistp->ea.name, flistp->ea.name)) {
636 break;
640 if (flistp) {
641 /* Copy the data from this entry. */
642 nlistp->ea.flags = flistp->ea.flags;
643 nlistp->ea.value = flistp->ea.value;
644 } else {
645 /* Null entry. */
646 nlistp->ea.flags = 0;
647 ZERO_STRUCT(nlistp->ea.value);
651 *total_ea_len = ea_list_size(name_list);
652 return name_list;
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct *conn,
663 struct smb_request *req,
664 const char *params,
665 int paramsize,
666 const char *pdata,
667 int datasize,
668 int max_data_bytes)
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send = datasize;
677 int params_to_send = paramsize;
678 int useable_space;
679 const char *pp = params;
680 const char *pd = pdata;
681 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset = 0;
684 bool overflow = False;
686 /* Modify the data_to_send and datasize and set the error if
687 we're trying to send more than max_data_bytes. We still send
688 the part of the packet(s) that fit. Strange, but needed
689 for OS/2. */
691 if (max_data_bytes > 0 && datasize > max_data_bytes) {
692 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
693 max_data_bytes, datasize ));
694 datasize = data_to_send = max_data_bytes;
695 overflow = True;
698 /* If there genuinely are no parameters or data to send just send the empty packet */
700 if(params_to_send == 0 && data_to_send == 0) {
701 reply_outbuf(req, 10, 0);
702 show_msg((char *)req->outbuf);
703 return;
706 /* When sending params and data ensure that both are nicely aligned */
707 /* Only do this alignment when there is also data to send - else
708 can cause NT redirector problems. */
710 if (((params_to_send % 4) != 0) && (data_to_send != 0))
711 data_alignment_offset = 4 - (params_to_send % 4);
713 /* Space is bufsize minus Netbios over TCP header minus SMB header */
714 /* The alignment_offset is to align the param bytes on an even byte
715 boundary. NT 4.0 Beta needs this to work correctly. */
717 useable_space = max_send - (smb_size
718 + 2 * 10 /* wct */
719 + alignment_offset
720 + data_alignment_offset);
722 if (useable_space < 0) {
723 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
724 "= %d!!!", useable_space));
725 exit_server_cleanly("send_trans2_replies: Not enough space");
728 while (params_to_send || data_to_send) {
729 /* Calculate whether we will totally or partially fill this packet */
731 total_sent_thistime = params_to_send + data_to_send;
733 /* We can never send more than useable_space */
735 * Note that 'useable_space' does not include the alignment offsets,
736 * but we must include the alignment offsets in the calculation of
737 * the length of the data we send over the wire, as the alignment offsets
738 * are sent here. Fix from Marc_Jacobsen@hp.com.
741 total_sent_thistime = MIN(total_sent_thistime, useable_space);
743 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
744 + data_alignment_offset);
747 * We might have SMBtrans2s in req which was transferred to
748 * the outbuf, fix that.
750 SCVAL(req->outbuf, smb_com, SMBtrans2);
752 /* Set total params and data to be sent */
753 SSVAL(req->outbuf,smb_tprcnt,paramsize);
754 SSVAL(req->outbuf,smb_tdrcnt,datasize);
756 /* Calculate how many parameters and data we can fit into
757 * this packet. Parameters get precedence
760 params_sent_thistime = MIN(params_to_send,useable_space);
761 data_sent_thistime = useable_space - params_sent_thistime;
762 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
764 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
766 /* smb_proff is the offset from the start of the SMB header to the
767 parameter bytes, however the first 4 bytes of outbuf are
768 the Netbios over TCP header. Thus use smb_base() to subtract
769 them from the calculation */
771 SSVAL(req->outbuf,smb_proff,
772 ((smb_buf(req->outbuf)+alignment_offset)
773 - smb_base(req->outbuf)));
775 if(params_sent_thistime == 0)
776 SSVAL(req->outbuf,smb_prdisp,0);
777 else
778 /* Absolute displacement of param bytes sent in this packet */
779 SSVAL(req->outbuf,smb_prdisp,pp - params);
781 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
782 if(data_sent_thistime == 0) {
783 SSVAL(req->outbuf,smb_droff,0);
784 SSVAL(req->outbuf,smb_drdisp, 0);
785 } else {
786 /* The offset of the data bytes is the offset of the
787 parameter bytes plus the number of parameters being sent this time */
788 SSVAL(req->outbuf, smb_droff,
789 ((smb_buf(req->outbuf)+alignment_offset)
790 - smb_base(req->outbuf))
791 + params_sent_thistime + data_alignment_offset);
792 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
795 /* Initialize the padding for alignment */
797 if (alignment_offset != 0) {
798 memset(smb_buf(req->outbuf), 0, alignment_offset);
801 /* Copy the param bytes into the packet */
803 if(params_sent_thistime) {
804 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
805 params_sent_thistime);
808 /* Copy in the data bytes */
809 if(data_sent_thistime) {
810 if (data_alignment_offset != 0) {
811 memset((smb_buf(req->outbuf)+alignment_offset+
812 params_sent_thistime), 0,
813 data_alignment_offset);
815 memcpy(smb_buf(req->outbuf)+alignment_offset
816 +params_sent_thistime+data_alignment_offset,
817 pd,data_sent_thistime);
820 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
821 params_sent_thistime, data_sent_thistime, useable_space));
822 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
823 params_to_send, data_to_send, paramsize, datasize));
825 if (overflow) {
826 error_packet_set((char *)req->outbuf,
827 ERRDOS,ERRbufferoverflow,
828 STATUS_BUFFER_OVERFLOW,
829 __LINE__,__FILE__);
832 /* Send the packet */
833 show_msg((char *)req->outbuf);
834 if (!srv_send_smb(smbd_server_fd(),
835 (char *)req->outbuf,
836 true, req->seqnum+1,
837 IS_CONN_ENCRYPTED(conn),
838 &req->pcd))
839 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
841 TALLOC_FREE(req->outbuf);
843 pp += params_sent_thistime;
844 pd += data_sent_thistime;
846 params_to_send -= params_sent_thistime;
847 data_to_send -= data_sent_thistime;
849 /* Sanity check */
850 if(params_to_send < 0 || data_to_send < 0) {
851 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
852 params_to_send, data_to_send));
853 return;
857 return;
860 /****************************************************************************
861 Reply to a TRANSACT2_OPEN.
862 ****************************************************************************/
864 static void call_trans2open(connection_struct *conn,
865 struct smb_request *req,
866 char **pparams, int total_params,
867 char **ppdata, int total_data,
868 unsigned int max_data_bytes)
870 char *params = *pparams;
871 char *pdata = *ppdata;
872 int deny_mode;
873 int32 open_attr;
874 bool oplock_request;
875 #if 0
876 bool return_additional_info;
877 int16 open_sattr;
878 time_t open_time;
879 #endif
880 int open_ofun;
881 uint32 open_size;
882 char *pname;
883 char *fname = NULL;
884 SMB_OFF_T size=0;
885 int fattr=0,mtime=0;
886 SMB_INO_T inode = 0;
887 SMB_STRUCT_STAT sbuf;
888 int smb_action = 0;
889 files_struct *fsp;
890 struct ea_list *ea_list = NULL;
891 uint16 flags = 0;
892 NTSTATUS status;
893 uint32 access_mask;
894 uint32 share_mode;
895 uint32 create_disposition;
896 uint32 create_options = 0;
897 TALLOC_CTX *ctx = talloc_tos();
899 SET_STAT_INVALID(sbuf);
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params < 29) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
907 return;
910 flags = SVAL(params, 0);
911 deny_mode = SVAL(params, 2);
912 open_attr = SVAL(params,6);
913 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914 if (oplock_request) {
915 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
918 #if 0
919 return_additional_info = BITSETW(params,0);
920 open_sattr = SVAL(params, 4);
921 open_time = make_unix_date3(params+8);
922 #endif
923 open_ofun = SVAL(params,12);
924 open_size = IVAL(params,14);
925 pname = &params[28];
927 if (IS_IPC(conn)) {
928 reply_doserror(req, ERRSRV, ERRaccess);
929 return;
932 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933 total_params - 28, STR_TERMINATE,
934 &status);
935 if (!NT_STATUS_IS_OK(status)) {
936 reply_nterror(req, status);
937 return;
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942 (unsigned int)open_ofun, open_size));
944 if (open_ofun == 0) {
945 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
946 return;
949 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
950 &access_mask,
951 &share_mode,
952 &create_disposition,
953 &create_options)) {
954 reply_doserror(req, ERRDOS, ERRbadaccess);
955 return;
958 /* Any data in this call is an EA list. */
959 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
960 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
961 return;
964 if (total_data != 4) {
965 if (total_data < 10) {
966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
967 return;
970 if (IVAL(pdata,0) > total_data) {
971 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
972 IVAL(pdata,0), (unsigned int)total_data));
973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
974 return;
977 ea_list = read_ea_list(talloc_tos(), pdata + 4,
978 total_data - 4);
979 if (!ea_list) {
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981 return;
983 } else if (IVAL(pdata,0) != 4) {
984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
985 return;
988 status = SMB_VFS_CREATE_FILE(
989 conn, /* conn */
990 req, /* req */
991 0, /* root_dir_fid */
992 fname, /* fname */
993 CFF_DOS_PATH, /* create_file_flags */
994 access_mask, /* access_mask */
995 share_mode, /* share_access */
996 create_disposition, /* create_disposition*/
997 create_options, /* create_options */
998 open_attr, /* file_attributes */
999 oplock_request, /* oplock_request */
1000 open_size, /* allocation_size */
1001 NULL, /* sd */
1002 ea_list, /* ea_list */
1003 &fsp, /* result */
1004 &smb_action, /* pinfo */
1005 &sbuf); /* psbuf */
1007 if (!NT_STATUS_IS_OK(status)) {
1008 if (open_was_deferred(req->mid)) {
1009 /* We have re-scheduled this call. */
1010 return;
1012 reply_openerror(req, status);
1013 return;
1016 size = get_file_size_stat(&sbuf);
1017 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1018 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1019 inode = sbuf.st_ex_ino;
1020 if (fattr & aDIR) {
1021 close_file(req, fsp, ERROR_CLOSE);
1022 reply_doserror(req, ERRDOS,ERRnoaccess);
1023 return;
1026 /* Realloc the size of parameters and data we will return */
1027 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1028 if(*pparams == NULL ) {
1029 reply_nterror(req, NT_STATUS_NO_MEMORY);
1030 return;
1032 params = *pparams;
1034 SSVAL(params,0,fsp->fnum);
1035 SSVAL(params,2,fattr);
1036 srv_put_dos_date2(params,4, mtime);
1037 SIVAL(params,8, (uint32)size);
1038 SSVAL(params,12,deny_mode);
1039 SSVAL(params,14,0); /* open_type - file or directory. */
1040 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1042 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1043 smb_action |= EXTENDED_OPLOCK_GRANTED;
1046 SSVAL(params,18,smb_action);
1049 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1051 SIVAL(params,20,inode);
1052 SSVAL(params,24,0); /* Padding. */
1053 if (flags & 8) {
1054 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1055 SIVAL(params, 26, ea_size);
1056 } else {
1057 SIVAL(params, 26, 0);
1060 /* Send the required number of replies */
1061 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1064 /*********************************************************
1065 Routine to check if a given string matches exactly.
1066 as a special case a mask of "." does NOT match. That
1067 is required for correct wildcard semantics
1068 Case can be significant or not.
1069 **********************************************************/
1071 static bool exact_match(connection_struct *conn,
1072 const char *str,
1073 const char *mask)
1075 if (mask[0] == '.' && mask[1] == 0)
1076 return False;
1077 if (dptr_has_wild(conn->dirptr)) {
1078 return False;
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1082 else
1083 return StrCaseCmp(str,mask) == 0;
1086 /****************************************************************************
1087 Return the filetype for UNIX extensions.
1088 ****************************************************************************/
1090 static uint32 unix_filetype(mode_t mode)
1092 if(S_ISREG(mode))
1093 return UNIX_TYPE_FILE;
1094 else if(S_ISDIR(mode))
1095 return UNIX_TYPE_DIR;
1096 #ifdef S_ISLNK
1097 else if(S_ISLNK(mode))
1098 return UNIX_TYPE_SYMLINK;
1099 #endif
1100 #ifdef S_ISCHR
1101 else if(S_ISCHR(mode))
1102 return UNIX_TYPE_CHARDEV;
1103 #endif
1104 #ifdef S_ISBLK
1105 else if(S_ISBLK(mode))
1106 return UNIX_TYPE_BLKDEV;
1107 #endif
1108 #ifdef S_ISFIFO
1109 else if(S_ISFIFO(mode))
1110 return UNIX_TYPE_FIFO;
1111 #endif
1112 #ifdef S_ISSOCK
1113 else if(S_ISSOCK(mode))
1114 return UNIX_TYPE_SOCKET;
1115 #endif
1117 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1118 return UNIX_TYPE_UNKNOWN;
1121 /****************************************************************************
1122 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1123 ****************************************************************************/
1125 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1127 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1128 SMB_STRUCT_STAT *psbuf,
1129 uint32 perms,
1130 enum perm_type ptype,
1131 mode_t *ret_perms)
1133 mode_t ret = 0;
1135 if (perms == SMB_MODE_NO_CHANGE) {
1136 if (!VALID_STAT(*psbuf)) {
1137 return NT_STATUS_INVALID_PARAMETER;
1138 } else {
1139 *ret_perms = psbuf->st_ex_mode;
1140 return NT_STATUS_OK;
1144 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1145 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1146 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1147 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1148 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1149 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1150 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1151 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1152 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1153 #ifdef S_ISVTX
1154 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1155 #endif
1156 #ifdef S_ISGID
1157 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1158 #endif
1159 #ifdef S_ISUID
1160 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1161 #endif
1163 switch (ptype) {
1164 case PERM_NEW_FILE:
1165 /* Apply mode mask */
1166 ret &= lp_create_mask(SNUM(conn));
1167 /* Add in force bits */
1168 ret |= lp_force_create_mode(SNUM(conn));
1169 break;
1170 case PERM_NEW_DIR:
1171 ret &= lp_dir_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_dir_mode(SNUM(conn));
1174 break;
1175 case PERM_EXISTING_FILE:
1176 /* Apply mode mask */
1177 ret &= lp_security_mask(SNUM(conn));
1178 /* Add in force bits */
1179 ret |= lp_force_security_mode(SNUM(conn));
1180 break;
1181 case PERM_EXISTING_DIR:
1182 /* Apply mode mask */
1183 ret &= lp_dir_security_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_dir_security_mode(SNUM(conn));
1186 break;
1189 *ret_perms = ret;
1190 return NT_STATUS_OK;
1193 /****************************************************************************
1194 Needed to show the msdfs symlinks as directories. Modifies psbuf
1195 to be a directory if it's a msdfs link.
1196 ****************************************************************************/
1198 static bool check_msdfs_link(connection_struct *conn,
1199 const char *pathname,
1200 SMB_STRUCT_STAT *psbuf)
1202 int saved_errno = errno;
1203 if(lp_host_msdfs() &&
1204 lp_msdfs_root(SNUM(conn)) &&
1205 is_msdfs_link(conn, pathname, psbuf)) {
1207 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1208 "as a directory\n",
1209 pathname));
1210 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1211 errno = saved_errno;
1212 return true;
1214 errno = saved_errno;
1215 return false;
1219 /****************************************************************************
1220 Get a level dependent lanman2 dir entry.
1221 ****************************************************************************/
1223 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1224 connection_struct *conn,
1225 uint16 flags2,
1226 const char *path_mask,
1227 uint32 dirtype,
1228 int info_level,
1229 int requires_resume_key,
1230 bool dont_descend,
1231 bool ask_sharemode,
1232 char **ppdata,
1233 char *base_data,
1234 char *end_data,
1235 int space_remaining,
1236 bool *out_of_space,
1237 bool *got_exact_match,
1238 int *last_entry_off,
1239 struct ea_list *name_list)
1241 char *dname;
1242 bool found = False;
1243 SMB_STRUCT_STAT sbuf;
1244 const char *mask = NULL;
1245 char *pathreal = NULL;
1246 char *fname = NULL;
1247 char *p, *q, *pdata = *ppdata;
1248 uint32 reskey=0;
1249 long prev_dirpos=0;
1250 uint32 mode=0;
1251 SMB_OFF_T file_size = 0;
1252 uint64_t allocation_size = 0;
1253 uint32 len;
1254 struct timespec mdate_ts, adate_ts, create_date_ts;
1255 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1256 char *nameptr;
1257 char *last_entry_ptr;
1258 bool was_8_3;
1259 uint32 nt_extmode; /* Used for NT connections instead of mode */
1260 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1261 bool check_mangled_names = lp_manglednames(conn->params);
1262 char mangled_name[13]; /* mangled 8.3 name. */
1264 *out_of_space = False;
1265 *got_exact_match = False;
1267 ZERO_STRUCT(mdate_ts);
1268 ZERO_STRUCT(adate_ts);
1269 ZERO_STRUCT(create_date_ts);
1271 if (!conn->dirptr) {
1272 return(False);
1275 p = strrchr_m(path_mask,'/');
1276 if(p != NULL) {
1277 if(p[1] == '\0') {
1278 mask = talloc_strdup(ctx,"*.*");
1279 } else {
1280 mask = p+1;
1282 } else {
1283 mask = path_mask;
1286 while (!found) {
1287 bool got_match;
1288 bool ms_dfs_link = False;
1290 /* Needed if we run out of space */
1291 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1292 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1295 * Due to bugs in NT client redirectors we are not using
1296 * resume keys any more - set them to zero.
1297 * Check out the related comments in findfirst/findnext.
1298 * JRA.
1301 reskey = 0;
1303 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1304 (long)conn->dirptr,curr_dirpos));
1306 if (!dname) {
1307 return(False);
1311 * fname may get mangled, dname is never mangled.
1312 * Whenever we're accessing the filesystem we use
1313 * pathreal which is composed from dname.
1316 pathreal = NULL;
1317 fname = dname;
1319 /* Mangle fname if it's an illegal name. */
1320 if (mangle_must_mangle(dname,conn->params)) {
1321 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1322 TALLOC_FREE(fname);
1323 continue; /* Error - couldn't mangle. */
1325 fname = talloc_strdup(ctx, mangled_name);
1326 if (!fname) {
1327 return False;
1331 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1332 got_match = mask_match(fname, mask, conn->case_sensitive);
1335 if(!got_match && check_mangled_names &&
1336 !mangle_is_8_3(fname, False, conn->params)) {
1338 * It turns out that NT matches wildcards against
1339 * both long *and* short names. This may explain some
1340 * of the wildcard wierdness from old DOS clients
1341 * that some people have been seeing.... JRA.
1343 /* Force the mangling into 8.3. */
1344 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1345 TALLOC_FREE(fname);
1346 continue; /* Error - couldn't mangle. */
1349 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1350 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1354 if (got_match) {
1355 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1357 if (dont_descend && !isdots) {
1358 TALLOC_FREE(fname);
1359 continue;
1362 if (needslash) {
1363 pathreal = NULL;
1364 pathreal = talloc_asprintf(ctx,
1365 "%s/%s",
1366 conn->dirpath,
1367 dname);
1368 } else {
1369 pathreal = talloc_asprintf(ctx,
1370 "%s%s",
1371 conn->dirpath,
1372 dname);
1375 if (!pathreal) {
1376 TALLOC_FREE(fname);
1377 return False;
1380 if (INFO_LEVEL_IS_UNIX(info_level)) {
1381 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1382 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1383 pathreal,strerror(errno)));
1384 TALLOC_FREE(pathreal);
1385 TALLOC_FREE(fname);
1386 continue;
1388 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1389 /* Needed to show the msdfs symlinks as
1390 * directories */
1392 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1393 if (!ms_dfs_link) {
1394 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395 pathreal,strerror(errno)));
1396 TALLOC_FREE(pathreal);
1397 TALLOC_FREE(fname);
1398 continue;
1402 if (ms_dfs_link) {
1403 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1404 } else {
1405 mode = dos_mode(conn,pathreal,&sbuf);
1408 if (!dir_check_ftype(conn,mode,dirtype)) {
1409 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1410 TALLOC_FREE(pathreal);
1411 TALLOC_FREE(fname);
1412 continue;
1415 if (!(mode & aDIR)) {
1416 file_size = get_file_size_stat(&sbuf);
1418 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1420 mdate_ts = sbuf.st_ex_mtime;
1421 adate_ts = sbuf.st_ex_atime;
1422 create_date_ts = sbuf.st_ex_btime;
1424 if (ask_sharemode) {
1425 struct timespec write_time_ts;
1426 struct file_id fileid;
1428 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1429 get_file_infos(fileid, NULL, &write_time_ts);
1430 if (!null_timespec(write_time_ts)) {
1431 mdate_ts = write_time_ts;
1435 if (lp_dos_filetime_resolution(SNUM(conn))) {
1436 dos_filetime_timespec(&create_date_ts);
1437 dos_filetime_timespec(&mdate_ts);
1438 dos_filetime_timespec(&adate_ts);
1441 create_date = convert_timespec_to_time_t(create_date_ts);
1442 mdate = convert_timespec_to_time_t(mdate_ts);
1443 adate = convert_timespec_to_time_t(adate_ts);
1445 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1446 pathreal,fname));
1448 found = True;
1450 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1453 if (!found)
1454 TALLOC_FREE(fname);
1457 p = pdata;
1458 last_entry_ptr = p;
1460 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1462 switch (info_level) {
1463 case SMB_FIND_INFO_STANDARD:
1464 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1465 if(requires_resume_key) {
1466 SIVAL(p,0,reskey);
1467 p += 4;
1469 srv_put_dos_date2(p,0,create_date);
1470 srv_put_dos_date2(p,4,adate);
1471 srv_put_dos_date2(p,8,mdate);
1472 SIVAL(p,12,(uint32)file_size);
1473 SIVAL(p,16,(uint32)allocation_size);
1474 SSVAL(p,20,mode);
1475 p += 23;
1476 nameptr = p;
1477 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1478 p += ucs2_align(base_data, p, 0);
1480 len = srvstr_push(base_data, flags2, p,
1481 fname, PTR_DIFF(end_data, p),
1482 STR_TERMINATE);
1483 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1484 if (len > 2) {
1485 SCVAL(nameptr, -1, len - 2);
1486 } else {
1487 SCVAL(nameptr, -1, 0);
1489 } else {
1490 if (len > 1) {
1491 SCVAL(nameptr, -1, len - 1);
1492 } else {
1493 SCVAL(nameptr, -1, 0);
1496 p += len;
1497 break;
1499 case SMB_FIND_EA_SIZE:
1500 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1501 if(requires_resume_key) {
1502 SIVAL(p,0,reskey);
1503 p += 4;
1505 srv_put_dos_date2(p,0,create_date);
1506 srv_put_dos_date2(p,4,adate);
1507 srv_put_dos_date2(p,8,mdate);
1508 SIVAL(p,12,(uint32)file_size);
1509 SIVAL(p,16,(uint32)allocation_size);
1510 SSVAL(p,20,mode);
1512 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1513 SIVAL(p,22,ea_size); /* Extended attributes */
1515 p += 27;
1516 nameptr = p - 1;
1517 len = srvstr_push(base_data, flags2,
1518 p, fname, PTR_DIFF(end_data, p),
1519 STR_TERMINATE | STR_NOALIGN);
1520 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1521 if (len > 2) {
1522 len -= 2;
1523 } else {
1524 len = 0;
1526 } else {
1527 if (len > 1) {
1528 len -= 1;
1529 } else {
1530 len = 0;
1533 SCVAL(nameptr,0,len);
1534 p += len;
1535 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1536 break;
1538 case SMB_FIND_EA_LIST:
1540 struct ea_list *file_list = NULL;
1541 size_t ea_len = 0;
1543 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1544 if (!name_list) {
1545 return False;
1547 if(requires_resume_key) {
1548 SIVAL(p,0,reskey);
1549 p += 4;
1551 srv_put_dos_date2(p,0,create_date);
1552 srv_put_dos_date2(p,4,adate);
1553 srv_put_dos_date2(p,8,mdate);
1554 SIVAL(p,12,(uint32)file_size);
1555 SIVAL(p,16,(uint32)allocation_size);
1556 SSVAL(p,20,mode);
1557 p += 22; /* p now points to the EA area. */
1559 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1560 name_list = ea_list_union(name_list, file_list, &ea_len);
1562 /* We need to determine if this entry will fit in the space available. */
1563 /* Max string size is 255 bytes. */
1564 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1565 /* Move the dirptr back to prev_dirpos */
1566 dptr_SeekDir(conn->dirptr, prev_dirpos);
1567 *out_of_space = True;
1568 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1569 return False; /* Not finished - just out of space */
1572 /* Push the ea_data followed by the name. */
1573 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1574 nameptr = p;
1575 len = srvstr_push(base_data, flags2,
1576 p + 1, fname, PTR_DIFF(end_data, p+1),
1577 STR_TERMINATE | STR_NOALIGN);
1578 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1579 if (len > 2) {
1580 len -= 2;
1581 } else {
1582 len = 0;
1584 } else {
1585 if (len > 1) {
1586 len -= 1;
1587 } else {
1588 len = 0;
1591 SCVAL(nameptr,0,len);
1592 p += len + 1;
1593 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1594 break;
1597 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1598 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1599 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1600 p += 4;
1601 SIVAL(p,0,reskey); p += 4;
1602 put_long_date_timespec(p,create_date_ts); p += 8;
1603 put_long_date_timespec(p,adate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 put_long_date_timespec(p,mdate_ts); p += 8;
1606 SOFF_T(p,0,file_size); p += 8;
1607 SOFF_T(p,0,allocation_size); p += 8;
1608 SIVAL(p,0,nt_extmode); p += 4;
1609 q = p; p += 4; /* q is placeholder for name length. */
1611 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1612 SIVAL(p,0,ea_size); /* Extended attributes */
1613 p += 4;
1615 /* Clear the short name buffer. This is
1616 * IMPORTANT as not doing so will trigger
1617 * a Win2k client bug. JRA.
1619 if (!was_8_3 && check_mangled_names) {
1620 if (!name_to_8_3(fname,mangled_name,True,
1621 conn->params)) {
1622 /* Error - mangle failed ! */
1623 memset(mangled_name,'\0',12);
1625 mangled_name[12] = 0;
1626 len = srvstr_push(base_data, flags2,
1627 p+2, mangled_name, 24,
1628 STR_UPPER|STR_UNICODE);
1629 if (len < 24) {
1630 memset(p + 2 + len,'\0',24 - len);
1632 SSVAL(p, 0, len);
1633 } else {
1634 memset(p,'\0',26);
1636 p += 2 + 24;
1637 len = srvstr_push(base_data, flags2, p,
1638 fname, PTR_DIFF(end_data, p),
1639 STR_TERMINATE_ASCII);
1640 SIVAL(q,0,len);
1641 p += len;
1642 SIVAL(p,0,0); /* Ensure any padding is null. */
1643 len = PTR_DIFF(p, pdata);
1644 len = (len + 3) & ~3;
1645 SIVAL(pdata,0,len);
1646 p = pdata + len;
1647 break;
1649 case SMB_FIND_FILE_DIRECTORY_INFO:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1651 p += 4;
1652 SIVAL(p,0,reskey); p += 4;
1653 put_long_date_timespec(p,create_date_ts); p += 8;
1654 put_long_date_timespec(p,adate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 SOFF_T(p,0,file_size); p += 8;
1658 SOFF_T(p,0,allocation_size); p += 8;
1659 SIVAL(p,0,nt_extmode); p += 4;
1660 len = srvstr_push(base_data, flags2,
1661 p + 4, fname, PTR_DIFF(end_data, p+4),
1662 STR_TERMINATE_ASCII);
1663 SIVAL(p,0,len);
1664 p += 4 + len;
1665 SIVAL(p,0,0); /* Ensure any padding is null. */
1666 len = PTR_DIFF(p, pdata);
1667 len = (len + 3) & ~3;
1668 SIVAL(pdata,0,len);
1669 p = pdata + len;
1670 break;
1672 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1673 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1674 p += 4;
1675 SIVAL(p,0,reskey); p += 4;
1676 put_long_date_timespec(p,create_date_ts); p += 8;
1677 put_long_date_timespec(p,adate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 put_long_date_timespec(p,mdate_ts); p += 8;
1680 SOFF_T(p,0,file_size); p += 8;
1681 SOFF_T(p,0,allocation_size); p += 8;
1682 SIVAL(p,0,nt_extmode); p += 4;
1683 q = p; p += 4; /* q is placeholder for name length. */
1685 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1686 SIVAL(p,0,ea_size); /* Extended attributes */
1687 p +=4;
1689 len = srvstr_push(base_data, flags2, p,
1690 fname, PTR_DIFF(end_data, p),
1691 STR_TERMINATE_ASCII);
1692 SIVAL(q, 0, len);
1693 p += len;
1695 SIVAL(p,0,0); /* Ensure any padding is null. */
1696 len = PTR_DIFF(p, pdata);
1697 len = (len + 3) & ~3;
1698 SIVAL(pdata,0,len);
1699 p = pdata + len;
1700 break;
1702 case SMB_FIND_FILE_NAMES_INFO:
1703 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1704 p += 4;
1705 SIVAL(p,0,reskey); p += 4;
1706 p += 4;
1707 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1708 acl on a dir (tridge) */
1709 len = srvstr_push(base_data, flags2, p,
1710 fname, PTR_DIFF(end_data, p),
1711 STR_TERMINATE_ASCII);
1712 SIVAL(p, -4, len);
1713 p += len;
1714 SIVAL(p,0,0); /* Ensure any padding is null. */
1715 len = PTR_DIFF(p, pdata);
1716 len = (len + 3) & ~3;
1717 SIVAL(pdata,0,len);
1718 p = pdata + len;
1719 break;
1721 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1723 p += 4;
1724 SIVAL(p,0,reskey); p += 4;
1725 put_long_date_timespec(p,create_date_ts); p += 8;
1726 put_long_date_timespec(p,adate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 SOFF_T(p,0,file_size); p += 8;
1730 SOFF_T(p,0,allocation_size); p += 8;
1731 SIVAL(p,0,nt_extmode); p += 4;
1732 q = p; p += 4; /* q is placeholder for name length. */
1734 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1735 SIVAL(p,0,ea_size); /* Extended attributes */
1736 p +=4;
1738 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1739 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1740 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1741 len = srvstr_push(base_data, flags2, p,
1742 fname, PTR_DIFF(end_data, p),
1743 STR_TERMINATE_ASCII);
1744 SIVAL(q, 0, len);
1745 p += len;
1746 SIVAL(p,0,0); /* Ensure any padding is null. */
1747 len = PTR_DIFF(p, pdata);
1748 len = (len + 3) & ~3;
1749 SIVAL(pdata,0,len);
1750 p = pdata + len;
1751 break;
1753 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1754 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1755 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1756 p += 4;
1757 SIVAL(p,0,reskey); p += 4;
1758 put_long_date_timespec(p,create_date_ts); p += 8;
1759 put_long_date_timespec(p,adate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 SOFF_T(p,0,file_size); p += 8;
1763 SOFF_T(p,0,allocation_size); p += 8;
1764 SIVAL(p,0,nt_extmode); p += 4;
1765 q = p; p += 4; /* q is placeholder for name length */
1767 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1768 SIVAL(p,0,ea_size); /* Extended attributes */
1769 p +=4;
1771 /* Clear the short name buffer. This is
1772 * IMPORTANT as not doing so will trigger
1773 * a Win2k client bug. JRA.
1775 if (!was_8_3 && check_mangled_names) {
1776 if (!name_to_8_3(fname,mangled_name,True,
1777 conn->params)) {
1778 /* Error - mangle failed ! */
1779 memset(mangled_name,'\0',12);
1781 mangled_name[12] = 0;
1782 len = srvstr_push(base_data, flags2,
1783 p+2, mangled_name, 24,
1784 STR_UPPER|STR_UNICODE);
1785 SSVAL(p, 0, len);
1786 if (len < 24) {
1787 memset(p + 2 + len,'\0',24 - len);
1789 SSVAL(p, 0, len);
1790 } else {
1791 memset(p,'\0',26);
1793 p += 26;
1794 SSVAL(p,0,0); p += 2; /* Reserved ? */
1795 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1796 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1797 len = srvstr_push(base_data, flags2, p,
1798 fname, PTR_DIFF(end_data, p),
1799 STR_TERMINATE_ASCII);
1800 SIVAL(q,0,len);
1801 p += len;
1802 SIVAL(p,0,0); /* Ensure any padding is null. */
1803 len = PTR_DIFF(p, pdata);
1804 len = (len + 3) & ~3;
1805 SIVAL(pdata,0,len);
1806 p = pdata + len;
1807 break;
1809 /* CIFS UNIX Extension. */
1811 case SMB_FIND_FILE_UNIX:
1812 case SMB_FIND_FILE_UNIX_INFO2:
1813 p+= 4;
1814 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1816 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1818 if (info_level == SMB_FIND_FILE_UNIX) {
1819 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1820 p = store_file_unix_basic(conn, p,
1821 NULL, &sbuf);
1822 len = srvstr_push(base_data, flags2, p,
1823 fname, PTR_DIFF(end_data, p),
1824 STR_TERMINATE);
1825 } else {
1826 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1827 p = store_file_unix_basic_info2(conn, p,
1828 NULL, &sbuf);
1829 nameptr = p;
1830 p += 4;
1831 len = srvstr_push(base_data, flags2, p, fname,
1832 PTR_DIFF(end_data, p), 0);
1833 SIVAL(nameptr, 0, len);
1836 p += len;
1837 SIVAL(p,0,0); /* Ensure any padding is null. */
1839 len = PTR_DIFF(p, pdata);
1840 len = (len + 3) & ~3;
1841 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1842 p = pdata + len;
1843 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1845 break;
1847 default:
1848 TALLOC_FREE(fname);
1849 return(False);
1852 TALLOC_FREE(fname);
1853 if (PTR_DIFF(p,pdata) > space_remaining) {
1854 /* Move the dirptr back to prev_dirpos */
1855 dptr_SeekDir(conn->dirptr, prev_dirpos);
1856 *out_of_space = True;
1857 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1858 return False; /* Not finished - just out of space */
1861 /* Setup the last entry pointer, as an offset from base_data */
1862 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1863 /* Advance the data pointer to the next slot */
1864 *ppdata = p;
1866 return(found);
1869 /****************************************************************************
1870 Reply to a TRANS2_FINDFIRST.
1871 ****************************************************************************/
1873 static void call_trans2findfirst(connection_struct *conn,
1874 struct smb_request *req,
1875 char **pparams, int total_params,
1876 char **ppdata, int total_data,
1877 unsigned int max_data_bytes)
1879 /* We must be careful here that we don't return more than the
1880 allowed number of data bytes. If this means returning fewer than
1881 maxentries then so be it. We assume that the redirector has
1882 enough room for the fixed number of parameter bytes it has
1883 requested. */
1884 struct smb_filename *smb_dname = NULL;
1885 char *params = *pparams;
1886 char *pdata = *ppdata;
1887 char *data_end;
1888 uint32 dirtype;
1889 int maxentries;
1890 uint16 findfirst_flags;
1891 bool close_after_first;
1892 bool close_if_end;
1893 bool requires_resume_key;
1894 int info_level;
1895 char *directory = NULL;
1896 char *mask = NULL;
1897 char *p;
1898 int last_entry_off=0;
1899 int dptr_num = -1;
1900 int numentries = 0;
1901 int i;
1902 bool finished = False;
1903 bool dont_descend = False;
1904 bool out_of_space = False;
1905 int space_remaining;
1906 bool mask_contains_wcard = False;
1907 struct ea_list *ea_list = NULL;
1908 NTSTATUS ntstatus = NT_STATUS_OK;
1909 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1910 TALLOC_CTX *ctx = talloc_tos();
1912 if (total_params < 13) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1914 return;
1917 dirtype = SVAL(params,0);
1918 maxentries = SVAL(params,2);
1919 findfirst_flags = SVAL(params,4);
1920 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1921 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1922 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1923 info_level = SVAL(params,6);
1925 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1926 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1927 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1928 info_level, max_data_bytes));
1930 if (!maxentries) {
1931 /* W2K3 seems to treat zero as 1. */
1932 maxentries = 1;
1935 switch (info_level) {
1936 case SMB_FIND_INFO_STANDARD:
1937 case SMB_FIND_EA_SIZE:
1938 case SMB_FIND_EA_LIST:
1939 case SMB_FIND_FILE_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1941 case SMB_FIND_FILE_NAMES_INFO:
1942 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1943 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1944 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1945 break;
1946 case SMB_FIND_FILE_UNIX:
1947 case SMB_FIND_FILE_UNIX_INFO2:
1948 /* Always use filesystem for UNIX mtime query. */
1949 ask_sharemode = false;
1950 if (!lp_unix_extensions()) {
1951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1952 return;
1954 break;
1955 default:
1956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1957 return;
1960 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1961 params+12, total_params - 12,
1962 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1963 if (!NT_STATUS_IS_OK(ntstatus)) {
1964 reply_nterror(req, ntstatus);
1965 return;
1968 ntstatus = resolve_dfspath_wcard(ctx, conn,
1969 req->flags2 & FLAGS2_DFS_PATHNAMES,
1970 directory,
1971 &directory,
1972 &mask_contains_wcard);
1973 if (!NT_STATUS_IS_OK(ntstatus)) {
1974 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1975 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1976 ERRSRV, ERRbadpath);
1977 return;
1979 reply_nterror(req, ntstatus);
1980 return;
1983 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
1984 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
1985 if (!NT_STATUS_IS_OK(ntstatus)) {
1986 reply_nterror(req, ntstatus);
1987 return;
1990 mask = smb_dname->original_lcomp;
1992 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
1993 TALLOC_FREE(smb_dname);
1994 if (!NT_STATUS_IS_OK(ntstatus)) {
1995 reply_nterror(req, ntstatus);
1996 return;
1999 ntstatus = check_name(conn, directory);
2000 if (!NT_STATUS_IS_OK(ntstatus)) {
2001 reply_nterror(req, ntstatus);
2002 return;
2005 p = strrchr_m(directory,'/');
2006 if(p == NULL) {
2007 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2008 if((directory[0] == '.') && (directory[1] == '\0')) {
2009 mask = talloc_strdup(ctx,"*");
2010 if (!mask) {
2011 reply_nterror(req, NT_STATUS_NO_MEMORY);
2012 return;
2014 mask_contains_wcard = True;
2016 directory = talloc_strdup(talloc_tos(), "./");
2017 if (!directory) {
2018 reply_nterror(req, NT_STATUS_NO_MEMORY);
2019 return;
2021 } else {
2022 *p = 0;
2025 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2027 if (info_level == SMB_FIND_EA_LIST) {
2028 uint32 ea_size;
2030 if (total_data < 4) {
2031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2032 return;
2035 ea_size = IVAL(pdata,0);
2036 if (ea_size != total_data) {
2037 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2038 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 return;
2043 if (!lp_ea_support(SNUM(conn))) {
2044 reply_doserror(req, ERRDOS, ERReasnotsupported);
2045 return;
2048 /* Pull out the list of names. */
2049 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2050 if (!ea_list) {
2051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 return;
2056 *ppdata = (char *)SMB_REALLOC(
2057 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2058 if(*ppdata == NULL ) {
2059 reply_nterror(req, NT_STATUS_NO_MEMORY);
2060 return;
2062 pdata = *ppdata;
2063 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2065 /* Realloc the params space */
2066 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2067 if (*pparams == NULL) {
2068 reply_nterror(req, NT_STATUS_NO_MEMORY);
2069 return;
2071 params = *pparams;
2073 /* Save the wildcard match and attribs we are using on this directory -
2074 needed as lanman2 assumes these are being saved between calls */
2076 ntstatus = dptr_create(conn,
2077 directory,
2078 False,
2079 True,
2080 req->smbpid,
2081 mask,
2082 mask_contains_wcard,
2083 dirtype,
2084 &conn->dirptr);
2086 if (!NT_STATUS_IS_OK(ntstatus)) {
2087 reply_nterror(req, ntstatus);
2088 return;
2091 dptr_num = dptr_dnum(conn->dirptr);
2092 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2094 /* Initialize per TRANS2_FIND_FIRST operation data */
2095 dptr_init_search_op(conn->dirptr);
2097 /* We don't need to check for VOL here as this is returned by
2098 a different TRANS2 call. */
2100 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2101 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2102 dont_descend = True;
2104 p = pdata;
2105 space_remaining = max_data_bytes;
2106 out_of_space = False;
2108 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2109 bool got_exact_match = False;
2111 /* this is a heuristic to avoid seeking the dirptr except when
2112 absolutely necessary. It allows for a filename of about 40 chars */
2113 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2114 out_of_space = True;
2115 finished = False;
2116 } else {
2117 finished = !get_lanman2_dir_entry(ctx,
2118 conn,
2119 req->flags2,
2120 mask,dirtype,info_level,
2121 requires_resume_key,dont_descend,
2122 ask_sharemode,
2123 &p,pdata,data_end,
2124 space_remaining, &out_of_space,
2125 &got_exact_match,
2126 &last_entry_off, ea_list);
2129 if (finished && out_of_space)
2130 finished = False;
2132 if (!finished && !out_of_space)
2133 numentries++;
2136 * As an optimisation if we know we aren't looking
2137 * for a wildcard name (ie. the name matches the wildcard exactly)
2138 * then we can finish on any (first) match.
2139 * This speeds up large directory searches. JRA.
2142 if(got_exact_match)
2143 finished = True;
2145 /* Ensure space_remaining never goes -ve. */
2146 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2147 space_remaining = 0;
2148 out_of_space = true;
2149 } else {
2150 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2154 /* Check if we can close the dirptr */
2155 if(close_after_first || (finished && close_if_end)) {
2156 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2157 dptr_close(&dptr_num);
2161 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2162 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2163 * the protocol level is less than NT1. Tested with smbclient. JRA.
2164 * This should fix the OS/2 client bug #2335.
2167 if(numentries == 0) {
2168 dptr_close(&dptr_num);
2169 if (Protocol < PROTOCOL_NT1) {
2170 reply_doserror(req, ERRDOS, ERRnofiles);
2171 return;
2172 } else {
2173 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2174 ERRDOS, ERRbadfile);
2175 return;
2179 /* At this point pdata points to numentries directory entries. */
2181 /* Set up the return parameter block */
2182 SSVAL(params,0,dptr_num);
2183 SSVAL(params,2,numentries);
2184 SSVAL(params,4,finished);
2185 SSVAL(params,6,0); /* Never an EA error */
2186 SSVAL(params,8,last_entry_off);
2188 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2189 max_data_bytes);
2191 if ((! *directory) && dptr_path(dptr_num)) {
2192 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2193 if (!directory) {
2194 reply_nterror(req, NT_STATUS_NO_MEMORY);
2198 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2199 smb_fn_name(req->cmd),
2200 mask, directory, dirtype, numentries ) );
2203 * Force a name mangle here to ensure that the
2204 * mask as an 8.3 name is top of the mangled cache.
2205 * The reasons for this are subtle. Don't remove
2206 * this code unless you know what you are doing
2207 * (see PR#13758). JRA.
2210 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2211 char mangled_name[13];
2212 name_to_8_3(mask, mangled_name, True, conn->params);
2215 return;
2218 /****************************************************************************
2219 Reply to a TRANS2_FINDNEXT.
2220 ****************************************************************************/
2222 static void call_trans2findnext(connection_struct *conn,
2223 struct smb_request *req,
2224 char **pparams, int total_params,
2225 char **ppdata, int total_data,
2226 unsigned int max_data_bytes)
2228 /* We must be careful here that we don't return more than the
2229 allowed number of data bytes. If this means returning fewer than
2230 maxentries then so be it. We assume that the redirector has
2231 enough room for the fixed number of parameter bytes it has
2232 requested. */
2233 char *params = *pparams;
2234 char *pdata = *ppdata;
2235 char *data_end;
2236 int dptr_num;
2237 int maxentries;
2238 uint16 info_level;
2239 uint32 resume_key;
2240 uint16 findnext_flags;
2241 bool close_after_request;
2242 bool close_if_end;
2243 bool requires_resume_key;
2244 bool continue_bit;
2245 bool mask_contains_wcard = False;
2246 char *resume_name = NULL;
2247 const char *mask = NULL;
2248 const char *directory = NULL;
2249 char *p = NULL;
2250 uint16 dirtype;
2251 int numentries = 0;
2252 int i, last_entry_off=0;
2253 bool finished = False;
2254 bool dont_descend = False;
2255 bool out_of_space = False;
2256 int space_remaining;
2257 struct ea_list *ea_list = NULL;
2258 NTSTATUS ntstatus = NT_STATUS_OK;
2259 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2260 TALLOC_CTX *ctx = talloc_tos();
2262 if (total_params < 13) {
2263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2264 return;
2267 dptr_num = SVAL(params,0);
2268 maxentries = SVAL(params,2);
2269 info_level = SVAL(params,4);
2270 resume_key = IVAL(params,6);
2271 findnext_flags = SVAL(params,10);
2272 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2273 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2274 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2275 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2277 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2278 params+12,
2279 total_params - 12, STR_TERMINATE, &ntstatus,
2280 &mask_contains_wcard);
2281 if (!NT_STATUS_IS_OK(ntstatus)) {
2282 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2283 complain (it thinks we're asking for the directory above the shared
2284 path or an invalid name). Catch this as the resume name is only compared, never used in
2285 a file access. JRA. */
2286 srvstr_pull_talloc(ctx, params, req->flags2,
2287 &resume_name, params+12,
2288 total_params - 12,
2289 STR_TERMINATE);
2291 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2292 reply_nterror(req, ntstatus);
2293 return;
2297 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2298 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2299 resume_key = %d resume name = %s continue=%d level = %d\n",
2300 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2301 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2303 if (!maxentries) {
2304 /* W2K3 seems to treat zero as 1. */
2305 maxentries = 1;
2308 switch (info_level) {
2309 case SMB_FIND_INFO_STANDARD:
2310 case SMB_FIND_EA_SIZE:
2311 case SMB_FIND_EA_LIST:
2312 case SMB_FIND_FILE_DIRECTORY_INFO:
2313 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2314 case SMB_FIND_FILE_NAMES_INFO:
2315 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2316 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2317 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2318 break;
2319 case SMB_FIND_FILE_UNIX:
2320 case SMB_FIND_FILE_UNIX_INFO2:
2321 /* Always use filesystem for UNIX mtime query. */
2322 ask_sharemode = false;
2323 if (!lp_unix_extensions()) {
2324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2325 return;
2327 break;
2328 default:
2329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2330 return;
2333 if (info_level == SMB_FIND_EA_LIST) {
2334 uint32 ea_size;
2336 if (total_data < 4) {
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 return;
2341 ea_size = IVAL(pdata,0);
2342 if (ea_size != total_data) {
2343 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2344 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2346 return;
2349 if (!lp_ea_support(SNUM(conn))) {
2350 reply_doserror(req, ERRDOS, ERReasnotsupported);
2351 return;
2354 /* Pull out the list of names. */
2355 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2356 if (!ea_list) {
2357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2358 return;
2362 *ppdata = (char *)SMB_REALLOC(
2363 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2364 if(*ppdata == NULL) {
2365 reply_nterror(req, NT_STATUS_NO_MEMORY);
2366 return;
2369 pdata = *ppdata;
2370 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2372 /* Realloc the params space */
2373 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2374 if(*pparams == NULL ) {
2375 reply_nterror(req, NT_STATUS_NO_MEMORY);
2376 return;
2379 params = *pparams;
2381 /* Check that the dptr is valid */
2382 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2383 reply_doserror(req, ERRDOS, ERRnofiles);
2384 return;
2387 string_set(&conn->dirpath,dptr_path(dptr_num));
2389 /* Get the wildcard mask from the dptr */
2390 if((p = dptr_wcard(dptr_num))== NULL) {
2391 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2392 reply_doserror(req, ERRDOS, ERRnofiles);
2393 return;
2396 mask = p;
2397 directory = conn->dirpath;
2399 /* Get the attr mask from the dptr */
2400 dirtype = dptr_attr(dptr_num);
2402 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2403 dptr_num, mask, dirtype,
2404 (long)conn->dirptr,
2405 dptr_TellDir(conn->dirptr)));
2407 /* Initialize per TRANS2_FIND_NEXT operation data */
2408 dptr_init_search_op(conn->dirptr);
2410 /* We don't need to check for VOL here as this is returned by
2411 a different TRANS2 call. */
2413 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2414 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2415 dont_descend = True;
2417 p = pdata;
2418 space_remaining = max_data_bytes;
2419 out_of_space = False;
2422 * Seek to the correct position. We no longer use the resume key but
2423 * depend on the last file name instead.
2426 if(*resume_name && !continue_bit) {
2427 SMB_STRUCT_STAT st;
2429 long current_pos = 0;
2431 * Remember, name_to_8_3 is called by
2432 * get_lanman2_dir_entry(), so the resume name
2433 * could be mangled. Ensure we check the unmangled name.
2436 if (mangle_is_mangled(resume_name, conn->params)) {
2437 char *new_resume_name = NULL;
2438 mangle_lookup_name_from_8_3(ctx,
2439 resume_name,
2440 &new_resume_name,
2441 conn->params);
2442 if (new_resume_name) {
2443 resume_name = new_resume_name;
2448 * Fix for NT redirector problem triggered by resume key indexes
2449 * changing between directory scans. We now return a resume key of 0
2450 * and instead look for the filename to continue from (also given
2451 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2452 * findfirst/findnext (as is usual) then the directory pointer
2453 * should already be at the correct place.
2456 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2457 } /* end if resume_name && !continue_bit */
2459 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2460 bool got_exact_match = False;
2462 /* this is a heuristic to avoid seeking the dirptr except when
2463 absolutely necessary. It allows for a filename of about 40 chars */
2464 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2465 out_of_space = True;
2466 finished = False;
2467 } else {
2468 finished = !get_lanman2_dir_entry(ctx,
2469 conn,
2470 req->flags2,
2471 mask,dirtype,info_level,
2472 requires_resume_key,dont_descend,
2473 ask_sharemode,
2474 &p,pdata,data_end,
2475 space_remaining, &out_of_space,
2476 &got_exact_match,
2477 &last_entry_off, ea_list);
2480 if (finished && out_of_space)
2481 finished = False;
2483 if (!finished && !out_of_space)
2484 numentries++;
2487 * As an optimisation if we know we aren't looking
2488 * for a wildcard name (ie. the name matches the wildcard exactly)
2489 * then we can finish on any (first) match.
2490 * This speeds up large directory searches. JRA.
2493 if(got_exact_match)
2494 finished = True;
2496 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2499 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2500 smb_fn_name(req->cmd),
2501 mask, directory, dirtype, numentries ) );
2503 /* Check if we can close the dirptr */
2504 if(close_after_request || (finished && close_if_end)) {
2505 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2506 dptr_close(&dptr_num); /* This frees up the saved mask */
2509 /* Set up the return parameter block */
2510 SSVAL(params,0,numentries);
2511 SSVAL(params,2,finished);
2512 SSVAL(params,4,0); /* Never an EA error */
2513 SSVAL(params,6,last_entry_off);
2515 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2516 max_data_bytes);
2518 return;
2521 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2523 E_md4hash(lp_servicename(SNUM(conn)),objid);
2524 return objid;
2527 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2529 SMB_ASSERT(extended_info != NULL);
2531 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2532 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2533 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2534 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2535 #ifdef SAMBA_VERSION_REVISION
2536 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2537 #endif
2538 extended_info->samba_subversion = 0;
2539 #ifdef SAMBA_VERSION_RC_RELEASE
2540 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2541 #else
2542 #ifdef SAMBA_VERSION_PRE_RELEASE
2543 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2544 #endif
2545 #endif
2546 #ifdef SAMBA_VERSION_VENDOR_PATCH
2547 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2548 #endif
2549 extended_info->samba_gitcommitdate = 0;
2550 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2551 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2552 #endif
2554 memset(extended_info->samba_version_string, 0,
2555 sizeof(extended_info->samba_version_string));
2557 snprintf (extended_info->samba_version_string,
2558 sizeof(extended_info->samba_version_string),
2559 "%s", samba_version_string());
2562 /****************************************************************************
2563 Reply to a TRANS2_QFSINFO (query filesystem info).
2564 ****************************************************************************/
2566 static void call_trans2qfsinfo(connection_struct *conn,
2567 struct smb_request *req,
2568 char **pparams, int total_params,
2569 char **ppdata, int total_data,
2570 unsigned int max_data_bytes)
2572 char *pdata, *end_data;
2573 char *params = *pparams;
2574 uint16 info_level;
2575 int data_len, len;
2576 SMB_STRUCT_STAT st;
2577 const char *vname = volume_label(SNUM(conn));
2578 int snum = SNUM(conn);
2579 char *fstype = lp_fstype(SNUM(conn));
2580 uint32 additional_flags = 0;
2582 if (total_params < 2) {
2583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2584 return;
2587 info_level = SVAL(params,0);
2589 if (IS_IPC(conn)) {
2590 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2591 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2592 "info level (0x%x) on IPC$.\n",
2593 (unsigned int)info_level));
2594 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2595 return;
2599 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2600 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2601 DEBUG(0,("call_trans2qfsinfo: encryption required "
2602 "and info level 0x%x sent.\n",
2603 (unsigned int)info_level));
2604 exit_server_cleanly("encryption required "
2605 "on connection");
2606 return;
2610 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2612 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2613 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2614 reply_doserror(req, ERRSRV, ERRinvdevice);
2615 return;
2618 *ppdata = (char *)SMB_REALLOC(
2619 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2620 if (*ppdata == NULL ) {
2621 reply_nterror(req, NT_STATUS_NO_MEMORY);
2622 return;
2625 pdata = *ppdata;
2626 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2627 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2629 switch (info_level) {
2630 case SMB_INFO_ALLOCATION:
2632 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2633 data_len = 18;
2634 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2635 reply_unixerror(req, ERRHRD, ERRgeneral);
2636 return;
2639 block_size = lp_block_size(snum);
2640 if (bsize < block_size) {
2641 uint64_t factor = block_size/bsize;
2642 bsize = block_size;
2643 dsize /= factor;
2644 dfree /= factor;
2646 if (bsize > block_size) {
2647 uint64_t factor = bsize/block_size;
2648 bsize = block_size;
2649 dsize *= factor;
2650 dfree *= factor;
2652 bytes_per_sector = 512;
2653 sectors_per_unit = bsize/bytes_per_sector;
2655 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2656 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2657 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2659 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2660 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2661 SIVAL(pdata,l1_cUnit,dsize);
2662 SIVAL(pdata,l1_cUnitAvail,dfree);
2663 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2664 break;
2667 case SMB_INFO_VOLUME:
2668 /* Return volume name */
2670 * Add volume serial number - hash of a combination of
2671 * the called hostname and the service name.
2673 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2675 * Win2k3 and previous mess this up by sending a name length
2676 * one byte short. I believe only older clients (OS/2 Win9x) use
2677 * this call so try fixing this by adding a terminating null to
2678 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2680 len = srvstr_push(
2681 pdata, req->flags2,
2682 pdata+l2_vol_szVolLabel, vname,
2683 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2684 STR_NOALIGN|STR_TERMINATE);
2685 SCVAL(pdata,l2_vol_cch,len);
2686 data_len = l2_vol_szVolLabel + len;
2687 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2688 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2689 len, vname));
2690 break;
2692 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2693 case SMB_FS_ATTRIBUTE_INFORMATION:
2695 additional_flags = 0;
2696 #if defined(HAVE_SYS_QUOTAS)
2697 additional_flags |= FILE_VOLUME_QUOTAS;
2698 #endif
2700 if(lp_nt_acl_support(SNUM(conn))) {
2701 additional_flags |= FILE_PERSISTENT_ACLS;
2704 /* Capabilities are filled in at connection time through STATVFS call */
2705 additional_flags |= conn->fs_capabilities;
2707 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2708 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2709 additional_flags); /* FS ATTRIBUTES */
2711 SIVAL(pdata,4,255); /* Max filename component length */
2712 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2713 and will think we can't do long filenames */
2714 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2715 PTR_DIFF(end_data, pdata+12),
2716 STR_UNICODE);
2717 SIVAL(pdata,8,len);
2718 data_len = 12 + len;
2719 break;
2721 case SMB_QUERY_FS_LABEL_INFO:
2722 case SMB_FS_LABEL_INFORMATION:
2723 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2724 PTR_DIFF(end_data, pdata+4), 0);
2725 data_len = 4 + len;
2726 SIVAL(pdata,0,len);
2727 break;
2729 case SMB_QUERY_FS_VOLUME_INFO:
2730 case SMB_FS_VOLUME_INFORMATION:
2733 * Add volume serial number - hash of a combination of
2734 * the called hostname and the service name.
2736 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2737 (str_checksum(get_local_machine_name())<<16));
2739 /* Max label len is 32 characters. */
2740 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2741 PTR_DIFF(end_data, pdata+18),
2742 STR_UNICODE);
2743 SIVAL(pdata,12,len);
2744 data_len = 18+len;
2746 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2747 (int)strlen(vname),vname, lp_servicename(snum)));
2748 break;
2750 case SMB_QUERY_FS_SIZE_INFO:
2751 case SMB_FS_SIZE_INFORMATION:
2753 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2754 data_len = 24;
2755 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2756 reply_unixerror(req, ERRHRD, ERRgeneral);
2757 return;
2759 block_size = lp_block_size(snum);
2760 if (bsize < block_size) {
2761 uint64_t factor = block_size/bsize;
2762 bsize = block_size;
2763 dsize /= factor;
2764 dfree /= factor;
2766 if (bsize > block_size) {
2767 uint64_t factor = bsize/block_size;
2768 bsize = block_size;
2769 dsize *= factor;
2770 dfree *= factor;
2772 bytes_per_sector = 512;
2773 sectors_per_unit = bsize/bytes_per_sector;
2774 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2775 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2776 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2777 SBIG_UINT(pdata,0,dsize);
2778 SBIG_UINT(pdata,8,dfree);
2779 SIVAL(pdata,16,sectors_per_unit);
2780 SIVAL(pdata,20,bytes_per_sector);
2781 break;
2784 case SMB_FS_FULL_SIZE_INFORMATION:
2786 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2787 data_len = 32;
2788 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2789 reply_unixerror(req, ERRHRD, ERRgeneral);
2790 return;
2792 block_size = lp_block_size(snum);
2793 if (bsize < block_size) {
2794 uint64_t factor = block_size/bsize;
2795 bsize = block_size;
2796 dsize /= factor;
2797 dfree /= factor;
2799 if (bsize > block_size) {
2800 uint64_t factor = bsize/block_size;
2801 bsize = block_size;
2802 dsize *= factor;
2803 dfree *= factor;
2805 bytes_per_sector = 512;
2806 sectors_per_unit = bsize/bytes_per_sector;
2807 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2808 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2809 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2810 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2811 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2812 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2813 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2814 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2815 break;
2818 case SMB_QUERY_FS_DEVICE_INFO:
2819 case SMB_FS_DEVICE_INFORMATION:
2820 data_len = 8;
2821 SIVAL(pdata,0,0); /* dev type */
2822 SIVAL(pdata,4,0); /* characteristics */
2823 break;
2825 #ifdef HAVE_SYS_QUOTAS
2826 case SMB_FS_QUOTA_INFORMATION:
2828 * what we have to send --metze:
2830 * Unknown1: 24 NULL bytes
2831 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2832 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2833 * Quota Flags: 2 byte :
2834 * Unknown3: 6 NULL bytes
2836 * 48 bytes total
2838 * details for Quota Flags:
2840 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2841 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2842 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2843 * 0x0001 Enable Quotas: enable quota for this fs
2847 /* we need to fake up a fsp here,
2848 * because its not send in this call
2850 files_struct fsp;
2851 SMB_NTQUOTA_STRUCT quotas;
2853 ZERO_STRUCT(fsp);
2854 ZERO_STRUCT(quotas);
2856 fsp.conn = conn;
2857 fsp.fnum = -1;
2859 /* access check */
2860 if (conn->server_info->utok.uid != 0) {
2861 DEBUG(0,("set_user_quota: access_denied "
2862 "service [%s] user [%s]\n",
2863 lp_servicename(SNUM(conn)),
2864 conn->server_info->unix_name));
2865 reply_doserror(req, ERRDOS, ERRnoaccess);
2866 return;
2869 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2870 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2871 reply_doserror(req, ERRSRV, ERRerror);
2872 return;
2875 data_len = 48;
2877 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2879 /* Unknown1 24 NULL bytes*/
2880 SBIG_UINT(pdata,0,(uint64_t)0);
2881 SBIG_UINT(pdata,8,(uint64_t)0);
2882 SBIG_UINT(pdata,16,(uint64_t)0);
2884 /* Default Soft Quota 8 bytes */
2885 SBIG_UINT(pdata,24,quotas.softlim);
2887 /* Default Hard Quota 8 bytes */
2888 SBIG_UINT(pdata,32,quotas.hardlim);
2890 /* Quota flag 2 bytes */
2891 SSVAL(pdata,40,quotas.qflags);
2893 /* Unknown3 6 NULL bytes */
2894 SSVAL(pdata,42,0);
2895 SIVAL(pdata,44,0);
2897 break;
2899 #endif /* HAVE_SYS_QUOTAS */
2900 case SMB_FS_OBJECTID_INFORMATION:
2902 unsigned char objid[16];
2903 struct smb_extended_info extended_info;
2904 memcpy(pdata,create_volume_objectid(conn, objid),16);
2905 samba_extended_info_version (&extended_info);
2906 SIVAL(pdata,16,extended_info.samba_magic);
2907 SIVAL(pdata,20,extended_info.samba_version);
2908 SIVAL(pdata,24,extended_info.samba_subversion);
2909 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2910 memcpy(pdata+36,extended_info.samba_version_string,28);
2911 data_len = 64;
2912 break;
2916 * Query the version and capabilities of the CIFS UNIX extensions
2917 * in use.
2920 case SMB_QUERY_CIFS_UNIX_INFO:
2922 bool large_write = lp_min_receive_file_size() &&
2923 !srv_is_signing_active(smbd_server_conn);
2924 bool large_read = !srv_is_signing_active(smbd_server_conn);
2925 int encrypt_caps = 0;
2927 if (!lp_unix_extensions()) {
2928 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2929 return;
2932 switch (conn->encrypt_level) {
2933 case 0:
2934 encrypt_caps = 0;
2935 break;
2936 case 1:
2937 case Auto:
2938 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2939 break;
2940 case Required:
2941 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2942 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2943 large_write = false;
2944 large_read = false;
2945 break;
2948 data_len = 12;
2949 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2950 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2952 /* We have POSIX ACLs, pathname, encryption,
2953 * large read/write, and locking capability. */
2955 SBIG_UINT(pdata,4,((uint64_t)(
2956 CIFS_UNIX_POSIX_ACLS_CAP|
2957 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2958 CIFS_UNIX_FCNTL_LOCKS_CAP|
2959 CIFS_UNIX_EXTATTR_CAP|
2960 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2961 encrypt_caps|
2962 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2963 (large_write ?
2964 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2965 break;
2968 case SMB_QUERY_POSIX_FS_INFO:
2970 int rc;
2971 vfs_statvfs_struct svfs;
2973 if (!lp_unix_extensions()) {
2974 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2975 return;
2978 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2980 if (!rc) {
2981 data_len = 56;
2982 SIVAL(pdata,0,svfs.OptimalTransferSize);
2983 SIVAL(pdata,4,svfs.BlockSize);
2984 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2985 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2986 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2987 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2988 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2989 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2990 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2991 #ifdef EOPNOTSUPP
2992 } else if (rc == EOPNOTSUPP) {
2993 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2994 return;
2995 #endif /* EOPNOTSUPP */
2996 } else {
2997 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2998 reply_doserror(req, ERRSRV, ERRerror);
2999 return;
3001 break;
3004 case SMB_QUERY_POSIX_WHOAMI:
3006 uint32_t flags = 0;
3007 uint32_t sid_bytes;
3008 int i;
3010 if (!lp_unix_extensions()) {
3011 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3012 return;
3015 if (max_data_bytes < 40) {
3016 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3017 return;
3020 /* We ARE guest if global_sid_Builtin_Guests is
3021 * in our list of SIDs.
3023 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3024 conn->server_info->ptok)) {
3025 flags |= SMB_WHOAMI_GUEST;
3028 /* We are NOT guest if global_sid_Authenticated_Users
3029 * is in our list of SIDs.
3031 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3032 conn->server_info->ptok)) {
3033 flags &= ~SMB_WHOAMI_GUEST;
3036 /* NOTE: 8 bytes for UID/GID, irrespective of native
3037 * platform size. This matches
3038 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3040 data_len = 4 /* flags */
3041 + 4 /* flag mask */
3042 + 8 /* uid */
3043 + 8 /* gid */
3044 + 4 /* ngroups */
3045 + 4 /* num_sids */
3046 + 4 /* SID bytes */
3047 + 4 /* pad/reserved */
3048 + (conn->server_info->utok.ngroups * 8)
3049 /* groups list */
3050 + (conn->server_info->ptok->num_sids *
3051 SID_MAX_SIZE)
3052 /* SID list */;
3054 SIVAL(pdata, 0, flags);
3055 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3056 SBIG_UINT(pdata, 8,
3057 (uint64_t)conn->server_info->utok.uid);
3058 SBIG_UINT(pdata, 16,
3059 (uint64_t)conn->server_info->utok.gid);
3062 if (data_len >= max_data_bytes) {
3063 /* Potential overflow, skip the GIDs and SIDs. */
3065 SIVAL(pdata, 24, 0); /* num_groups */
3066 SIVAL(pdata, 28, 0); /* num_sids */
3067 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3068 SIVAL(pdata, 36, 0); /* reserved */
3070 data_len = 40;
3071 break;
3074 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3075 SIVAL(pdata, 28, conn->server_info->num_sids);
3077 /* We walk the SID list twice, but this call is fairly
3078 * infrequent, and I don't expect that it's performance
3079 * sensitive -- jpeach
3081 for (i = 0, sid_bytes = 0;
3082 i < conn->server_info->ptok->num_sids; ++i) {
3083 sid_bytes += ndr_size_dom_sid(
3084 &conn->server_info->ptok->user_sids[i],
3085 NULL,
3089 /* SID list byte count */
3090 SIVAL(pdata, 32, sid_bytes);
3092 /* 4 bytes pad/reserved - must be zero */
3093 SIVAL(pdata, 36, 0);
3094 data_len = 40;
3096 /* GID list */
3097 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3098 SBIG_UINT(pdata, data_len,
3099 (uint64_t)conn->server_info->utok.groups[i]);
3100 data_len += 8;
3103 /* SID list */
3104 for (i = 0;
3105 i < conn->server_info->ptok->num_sids; ++i) {
3106 int sid_len = ndr_size_dom_sid(
3107 &conn->server_info->ptok->user_sids[i],
3108 NULL,
3111 sid_linearize(pdata + data_len, sid_len,
3112 &conn->server_info->ptok->user_sids[i]);
3113 data_len += sid_len;
3116 break;
3119 case SMB_MAC_QUERY_FS_INFO:
3121 * Thursby MAC extension... ONLY on NTFS filesystems
3122 * once we do streams then we don't need this
3124 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3125 data_len = 88;
3126 SIVAL(pdata,84,0x100); /* Don't support mac... */
3127 break;
3129 /* drop through */
3130 default:
3131 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3132 return;
3136 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3137 max_data_bytes);
3139 DEBUG( 4, ( "%s info_level = %d\n",
3140 smb_fn_name(req->cmd), info_level) );
3142 return;
3145 /****************************************************************************
3146 Reply to a TRANS2_SETFSINFO (set filesystem info).
3147 ****************************************************************************/
3149 static void call_trans2setfsinfo(connection_struct *conn,
3150 struct smb_request *req,
3151 char **pparams, int total_params,
3152 char **ppdata, int total_data,
3153 unsigned int max_data_bytes)
3155 char *pdata = *ppdata;
3156 char *params = *pparams;
3157 uint16 info_level;
3159 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3161 /* */
3162 if (total_params < 4) {
3163 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3164 total_params));
3165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3166 return;
3169 info_level = SVAL(params,2);
3171 if (IS_IPC(conn)) {
3172 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3173 info_level != SMB_SET_CIFS_UNIX_INFO) {
3174 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3175 "info level (0x%x) on IPC$.\n",
3176 (unsigned int)info_level));
3177 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3178 return;
3182 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3183 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3184 DEBUG(0,("call_trans2setfsinfo: encryption required "
3185 "and info level 0x%x sent.\n",
3186 (unsigned int)info_level));
3187 exit_server_cleanly("encryption required "
3188 "on connection");
3189 return;
3193 switch(info_level) {
3194 case SMB_SET_CIFS_UNIX_INFO:
3196 uint16 client_unix_major;
3197 uint16 client_unix_minor;
3198 uint32 client_unix_cap_low;
3199 uint32 client_unix_cap_high;
3201 if (!lp_unix_extensions()) {
3202 reply_nterror(req,
3203 NT_STATUS_INVALID_LEVEL);
3204 return;
3207 /* There should be 12 bytes of capabilities set. */
3208 if (total_data < 8) {
3209 reply_nterror(
3210 req,
3211 NT_STATUS_INVALID_PARAMETER);
3212 return;
3214 client_unix_major = SVAL(pdata,0);
3215 client_unix_minor = SVAL(pdata,2);
3216 client_unix_cap_low = IVAL(pdata,4);
3217 client_unix_cap_high = IVAL(pdata,8);
3218 /* Just print these values for now. */
3219 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3220 cap_low = 0x%x, cap_high = 0x%x\n",
3221 (unsigned int)client_unix_major,
3222 (unsigned int)client_unix_minor,
3223 (unsigned int)client_unix_cap_low,
3224 (unsigned int)client_unix_cap_high ));
3226 /* Here is where we must switch to posix pathname processing... */
3227 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3228 lp_set_posix_pathnames();
3229 mangle_change_to_posix();
3232 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3233 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3234 /* Client that knows how to do posix locks,
3235 * but not posix open/mkdir operations. Set a
3236 * default type for read/write checks. */
3238 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3241 break;
3244 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3246 NTSTATUS status;
3247 size_t param_len = 0;
3248 size_t data_len = total_data;
3250 if (!lp_unix_extensions()) {
3251 reply_nterror(
3252 req,
3253 NT_STATUS_INVALID_LEVEL);
3254 return;
3257 if (lp_smb_encrypt(SNUM(conn)) == false) {
3258 reply_nterror(
3259 req,
3260 NT_STATUS_NOT_SUPPORTED);
3261 return;
3264 DEBUG( 4,("call_trans2setfsinfo: "
3265 "request transport encryption.\n"));
3267 status = srv_request_encryption_setup(conn,
3268 (unsigned char **)ppdata,
3269 &data_len,
3270 (unsigned char **)pparams,
3271 &param_len);
3273 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3274 !NT_STATUS_IS_OK(status)) {
3275 reply_nterror(req, status);
3276 return;
3279 send_trans2_replies(conn, req,
3280 *pparams,
3281 param_len,
3282 *ppdata,
3283 data_len,
3284 max_data_bytes);
3286 if (NT_STATUS_IS_OK(status)) {
3287 /* Server-side transport
3288 * encryption is now *on*. */
3289 status = srv_encryption_start(conn);
3290 if (!NT_STATUS_IS_OK(status)) {
3291 exit_server_cleanly(
3292 "Failure in setting "
3293 "up encrypted transport");
3296 return;
3299 case SMB_FS_QUOTA_INFORMATION:
3301 files_struct *fsp = NULL;
3302 SMB_NTQUOTA_STRUCT quotas;
3304 ZERO_STRUCT(quotas);
3306 /* access check */
3307 if ((conn->server_info->utok.uid != 0)
3308 ||!CAN_WRITE(conn)) {
3309 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3310 lp_servicename(SNUM(conn)),
3311 conn->server_info->unix_name));
3312 reply_doserror(req, ERRSRV, ERRaccess);
3313 return;
3316 /* note: normaly there're 48 bytes,
3317 * but we didn't use the last 6 bytes for now
3318 * --metze
3320 fsp = file_fsp(req, SVAL(params,0));
3322 if (!check_fsp_ntquota_handle(conn, req,
3323 fsp)) {
3324 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3325 reply_nterror(
3326 req, NT_STATUS_INVALID_HANDLE);
3327 return;
3330 if (total_data < 42) {
3331 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3332 total_data));
3333 reply_nterror(
3334 req,
3335 NT_STATUS_INVALID_PARAMETER);
3336 return;
3339 /* unknown_1 24 NULL bytes in pdata*/
3341 /* the soft quotas 8 bytes (uint64_t)*/
3342 quotas.softlim = (uint64_t)IVAL(pdata,24);
3343 #ifdef LARGE_SMB_OFF_T
3344 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3345 #else /* LARGE_SMB_OFF_T */
3346 if ((IVAL(pdata,28) != 0)&&
3347 ((quotas.softlim != 0xFFFFFFFF)||
3348 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3349 /* more than 32 bits? */
3350 reply_nterror(
3351 req,
3352 NT_STATUS_INVALID_PARAMETER);
3353 return;
3355 #endif /* LARGE_SMB_OFF_T */
3357 /* the hard quotas 8 bytes (uint64_t)*/
3358 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3359 #ifdef LARGE_SMB_OFF_T
3360 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3361 #else /* LARGE_SMB_OFF_T */
3362 if ((IVAL(pdata,36) != 0)&&
3363 ((quotas.hardlim != 0xFFFFFFFF)||
3364 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3365 /* more than 32 bits? */
3366 reply_nterror(
3367 req,
3368 NT_STATUS_INVALID_PARAMETER);
3369 return;
3371 #endif /* LARGE_SMB_OFF_T */
3373 /* quota_flags 2 bytes **/
3374 quotas.qflags = SVAL(pdata,40);
3376 /* unknown_2 6 NULL bytes follow*/
3378 /* now set the quotas */
3379 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3380 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3381 reply_doserror(req, ERRSRV, ERRerror);
3382 return;
3385 break;
3387 default:
3388 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3389 info_level));
3390 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3391 return;
3392 break;
3396 * sending this reply works fine,
3397 * but I'm not sure it's the same
3398 * like windows do...
3399 * --metze
3401 reply_outbuf(req, 10, 0);
3404 #if defined(HAVE_POSIX_ACLS)
3405 /****************************************************************************
3406 Utility function to count the number of entries in a POSIX acl.
3407 ****************************************************************************/
3409 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3411 unsigned int ace_count = 0;
3412 int entry_id = SMB_ACL_FIRST_ENTRY;
3413 SMB_ACL_ENTRY_T entry;
3415 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3416 /* get_next... */
3417 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3418 entry_id = SMB_ACL_NEXT_ENTRY;
3420 ace_count++;
3422 return ace_count;
3425 /****************************************************************************
3426 Utility function to marshall a POSIX acl into wire format.
3427 ****************************************************************************/
3429 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3431 int entry_id = SMB_ACL_FIRST_ENTRY;
3432 SMB_ACL_ENTRY_T entry;
3434 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3435 SMB_ACL_TAG_T tagtype;
3436 SMB_ACL_PERMSET_T permset;
3437 unsigned char perms = 0;
3438 unsigned int own_grp;
3440 /* get_next... */
3441 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3442 entry_id = SMB_ACL_NEXT_ENTRY;
3445 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3446 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3447 return False;
3450 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3451 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3452 return False;
3455 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3456 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3457 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3459 SCVAL(pdata,1,perms);
3461 switch (tagtype) {
3462 case SMB_ACL_USER_OBJ:
3463 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3464 own_grp = (unsigned int)pst->st_ex_uid;
3465 SIVAL(pdata,2,own_grp);
3466 SIVAL(pdata,6,0);
3467 break;
3468 case SMB_ACL_USER:
3470 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3471 if (!puid) {
3472 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3473 return False;
3475 own_grp = (unsigned int)*puid;
3476 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3477 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3478 SIVAL(pdata,2,own_grp);
3479 SIVAL(pdata,6,0);
3480 break;
3482 case SMB_ACL_GROUP_OBJ:
3483 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3484 own_grp = (unsigned int)pst->st_ex_gid;
3485 SIVAL(pdata,2,own_grp);
3486 SIVAL(pdata,6,0);
3487 break;
3488 case SMB_ACL_GROUP:
3490 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3491 if (!pgid) {
3492 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3493 return False;
3495 own_grp = (unsigned int)*pgid;
3496 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3497 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3498 SIVAL(pdata,2,own_grp);
3499 SIVAL(pdata,6,0);
3500 break;
3502 case SMB_ACL_MASK:
3503 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3504 SIVAL(pdata,2,0xFFFFFFFF);
3505 SIVAL(pdata,6,0xFFFFFFFF);
3506 break;
3507 case SMB_ACL_OTHER:
3508 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3509 SIVAL(pdata,2,0xFFFFFFFF);
3510 SIVAL(pdata,6,0xFFFFFFFF);
3511 break;
3512 default:
3513 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3514 return False;
3516 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3519 return True;
3521 #endif
3523 /****************************************************************************
3524 Store the FILE_UNIX_BASIC info.
3525 ****************************************************************************/
3527 static char *store_file_unix_basic(connection_struct *conn,
3528 char *pdata,
3529 files_struct *fsp,
3530 const SMB_STRUCT_STAT *psbuf)
3532 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3533 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3535 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3536 pdata += 8;
3538 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3539 pdata += 8;
3541 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3542 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3543 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3544 pdata += 24;
3546 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3547 SIVAL(pdata,4,0);
3548 pdata += 8;
3550 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3551 SIVAL(pdata,4,0);
3552 pdata += 8;
3554 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3555 pdata += 4;
3557 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3558 SIVAL(pdata,4,0);
3559 pdata += 8;
3561 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3562 SIVAL(pdata,4,0);
3563 pdata += 8;
3565 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3566 pdata += 8;
3568 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3569 SIVAL(pdata,4,0);
3570 pdata += 8;
3572 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3573 SIVAL(pdata,4,0);
3574 pdata += 8;
3576 return pdata;
3579 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3580 * the chflags(2) (or equivalent) flags.
3582 * XXX: this really should be behind the VFS interface. To do this, we would
3583 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3584 * Each VFS module could then implement its own mapping as appropriate for the
3585 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3587 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3588 info2_flags_map[] =
3590 #ifdef UF_NODUMP
3591 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3592 #endif
3594 #ifdef UF_IMMUTABLE
3595 { UF_IMMUTABLE, EXT_IMMUTABLE },
3596 #endif
3598 #ifdef UF_APPEND
3599 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3600 #endif
3602 #ifdef UF_HIDDEN
3603 { UF_HIDDEN, EXT_HIDDEN },
3604 #endif
3606 /* Do not remove. We need to guarantee that this array has at least one
3607 * entry to build on HP-UX.
3609 { 0, 0 }
3613 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3614 uint32 *smb_fflags, uint32 *smb_fmask)
3616 int i;
3618 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3619 *smb_fmask |= info2_flags_map[i].smb_fflag;
3620 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3621 *smb_fflags |= info2_flags_map[i].smb_fflag;
3626 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3627 const uint32 smb_fflags,
3628 const uint32 smb_fmask,
3629 int *stat_fflags)
3631 uint32 max_fmask = 0;
3632 int i;
3634 *stat_fflags = psbuf->st_ex_flags;
3636 /* For each flags requested in smb_fmask, check the state of the
3637 * corresponding flag in smb_fflags and set or clear the matching
3638 * stat flag.
3641 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3642 max_fmask |= info2_flags_map[i].smb_fflag;
3643 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3644 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3645 *stat_fflags |= info2_flags_map[i].stat_fflag;
3646 } else {
3647 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3652 /* If smb_fmask is asking to set any bits that are not supported by
3653 * our flag mappings, we should fail.
3655 if ((smb_fmask & max_fmask) != smb_fmask) {
3656 return False;
3659 return True;
3663 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3664 * of file flags and birth (create) time.
3666 static char *store_file_unix_basic_info2(connection_struct *conn,
3667 char *pdata,
3668 files_struct *fsp,
3669 const SMB_STRUCT_STAT *psbuf)
3671 uint32 file_flags = 0;
3672 uint32 flags_mask = 0;
3674 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3676 /* Create (birth) time 64 bit */
3677 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3678 pdata += 8;
3680 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3681 SIVAL(pdata, 0, file_flags); /* flags */
3682 SIVAL(pdata, 4, flags_mask); /* mask */
3683 pdata += 8;
3685 return pdata;
3688 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3689 const struct stream_struct *streams,
3690 char *data,
3691 unsigned int max_data_bytes,
3692 unsigned int *data_size)
3694 unsigned int i;
3695 unsigned int ofs = 0;
3697 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3698 unsigned int next_offset;
3699 size_t namelen;
3700 smb_ucs2_t *namebuf;
3702 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3703 streams[i].name, &namelen) ||
3704 namelen <= 2)
3706 return NT_STATUS_INVALID_PARAMETER;
3710 * name_buf is now null-terminated, we need to marshall as not
3711 * terminated
3714 namelen -= 2;
3716 SIVAL(data, ofs+4, namelen);
3717 SOFF_T(data, ofs+8, streams[i].size);
3718 SOFF_T(data, ofs+16, streams[i].alloc_size);
3719 memcpy(data+ofs+24, namebuf, namelen);
3720 TALLOC_FREE(namebuf);
3722 next_offset = ofs + 24 + namelen;
3724 if (i == num_streams-1) {
3725 SIVAL(data, ofs, 0);
3727 else {
3728 unsigned int align = ndr_align_size(next_offset, 8);
3730 memset(data+next_offset, 0, align);
3731 next_offset += align;
3733 SIVAL(data, ofs, next_offset - ofs);
3734 ofs = next_offset;
3737 ofs = next_offset;
3740 *data_size = ofs;
3742 return NT_STATUS_OK;
3745 /****************************************************************************
3746 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3747 ****************************************************************************/
3749 static void call_trans2qpipeinfo(connection_struct *conn,
3750 struct smb_request *req,
3751 unsigned int tran_call,
3752 char **pparams, int total_params,
3753 char **ppdata, int total_data,
3754 unsigned int max_data_bytes)
3756 char *params = *pparams;
3757 char *pdata = *ppdata;
3758 unsigned int data_size = 0;
3759 unsigned int param_size = 2;
3760 uint16 info_level;
3761 files_struct *fsp;
3763 if (!params) {
3764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3765 return;
3768 if (total_params < 4) {
3769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3770 return;
3773 fsp = file_fsp(req, SVAL(params,0));
3774 if (!fsp_is_np(fsp)) {
3775 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3776 return;
3779 info_level = SVAL(params,2);
3781 *pparams = (char *)SMB_REALLOC(*pparams,2);
3782 if (*pparams == NULL) {
3783 reply_nterror(req, NT_STATUS_NO_MEMORY);
3784 return;
3786 params = *pparams;
3787 SSVAL(params,0,0);
3788 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3789 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3790 if (*ppdata == NULL ) {
3791 reply_nterror(req, NT_STATUS_NO_MEMORY);
3792 return;
3794 pdata = *ppdata;
3796 switch (info_level) {
3797 case SMB_FILE_STANDARD_INFORMATION:
3798 memset(pdata,0,24);
3799 SOFF_T(pdata,0,4096LL);
3800 SIVAL(pdata,16,1);
3801 SIVAL(pdata,20,1);
3802 data_size = 24;
3803 break;
3805 default:
3806 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3807 return;
3810 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3811 max_data_bytes);
3813 return;
3816 /****************************************************************************
3817 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3818 file name or file id).
3819 ****************************************************************************/
3821 static void call_trans2qfilepathinfo(connection_struct *conn,
3822 struct smb_request *req,
3823 unsigned int tran_call,
3824 char **pparams, int total_params,
3825 char **ppdata, int total_data,
3826 unsigned int max_data_bytes)
3828 char *params = *pparams;
3829 char *pdata = *ppdata;
3830 char *dstart, *dend;
3831 uint16 info_level;
3832 int mode=0;
3833 int nlink;
3834 SMB_OFF_T file_size=0;
3835 uint64_t allocation_size=0;
3836 unsigned int data_size = 0;
3837 unsigned int param_size = 2;
3838 SMB_STRUCT_STAT sbuf;
3839 char *dos_fname = NULL;
3840 char *fname = NULL;
3841 struct smb_filename *smb_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, &smb_fname, 0);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 reply_nterror(req, status);
3992 return;
3994 sbuf = smb_fname->st;
3996 status = get_full_smb_filename(ctx, smb_fname, &fname);
3997 TALLOC_FREE(smb_fname);
3998 if (!NT_STATUS_IS_OK(status)) {
3999 reply_nterror(req, status);
4000 return;
4003 status = check_name(conn, fname);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4006 reply_nterror(req, status);
4007 return;
4010 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4011 && is_ntfs_stream_name(fname)) {
4012 char *base;
4013 SMB_STRUCT_STAT bsbuf;
4015 status = split_ntfs_stream_name(talloc_tos(), fname,
4016 &base, NULL);
4017 if (!NT_STATUS_IS_OK(status)) {
4018 DEBUG(10, ("create_file_unixpath: "
4019 "split_ntfs_stream_name failed: %s\n",
4020 nt_errstr(status)));
4021 reply_nterror(req, status);
4022 return;
4025 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4027 if (INFO_LEVEL_IS_UNIX(info_level)) {
4028 /* Always do lstat for UNIX calls. */
4029 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4030 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4031 reply_unixerror(req,ERRDOS,ERRbadpath);
4032 return;
4034 } else {
4035 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4036 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4037 reply_unixerror(req,ERRDOS,ERRbadpath);
4038 return;
4042 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4043 get_file_infos(fileid, &delete_pending, NULL);
4044 if (delete_pending) {
4045 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4046 return;
4050 if (INFO_LEVEL_IS_UNIX(info_level)) {
4051 /* Always do lstat for UNIX calls. */
4052 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4053 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4054 reply_unixerror(req, ERRDOS, ERRbadpath);
4055 return;
4058 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4059 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4061 if (!ms_dfs_link) {
4062 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4063 reply_unixerror(req, ERRDOS, ERRbadpath);
4064 return;
4068 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4069 get_file_infos(fileid, &delete_pending, &write_time_ts);
4070 if (delete_pending) {
4071 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4072 return;
4076 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4078 return;
4081 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4082 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4084 p = strrchr_m(fname,'/');
4085 if (!p)
4086 base_name = fname;
4087 else
4088 base_name = p+1;
4090 if (ms_dfs_link) {
4091 mode = dos_mode_msdfs(conn,fname,&sbuf);
4092 } else {
4093 mode = dos_mode(conn,fname,&sbuf);
4095 if (!mode)
4096 mode = FILE_ATTRIBUTE_NORMAL;
4098 nlink = sbuf.st_ex_nlink;
4100 if (nlink && (mode&aDIR)) {
4101 nlink = 1;
4104 if ((nlink > 0) && delete_pending) {
4105 nlink -= 1;
4108 fullpathname = fname;
4109 if (!(mode & aDIR))
4110 file_size = get_file_size_stat(&sbuf);
4112 /* Pull out any data sent here before we realloc. */
4113 switch (info_level) {
4114 case SMB_INFO_QUERY_EAS_FROM_LIST:
4116 /* Pull any EA list from the data portion. */
4117 uint32 ea_size;
4119 if (total_data < 4) {
4120 reply_nterror(
4121 req, NT_STATUS_INVALID_PARAMETER);
4122 return;
4124 ea_size = IVAL(pdata,0);
4126 if (total_data > 0 && ea_size != total_data) {
4127 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4128 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4129 reply_nterror(
4130 req, NT_STATUS_INVALID_PARAMETER);
4131 return;
4134 if (!lp_ea_support(SNUM(conn))) {
4135 reply_doserror(req, ERRDOS,
4136 ERReasnotsupported);
4137 return;
4140 /* Pull out the list of names. */
4141 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4142 if (!ea_list) {
4143 reply_nterror(
4144 req, NT_STATUS_INVALID_PARAMETER);
4145 return;
4147 break;
4150 case SMB_QUERY_POSIX_LOCK:
4152 if (fsp == NULL || fsp->fh->fd == -1) {
4153 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4154 return;
4157 if (total_data != POSIX_LOCK_DATA_SIZE) {
4158 reply_nterror(
4159 req, NT_STATUS_INVALID_PARAMETER);
4160 return;
4163 /* Copy the lock range data. */
4164 lock_data = (char *)TALLOC_MEMDUP(
4165 ctx, pdata, total_data);
4166 if (!lock_data) {
4167 reply_nterror(req, NT_STATUS_NO_MEMORY);
4168 return;
4171 default:
4172 break;
4175 *pparams = (char *)SMB_REALLOC(*pparams,2);
4176 if (*pparams == NULL) {
4177 reply_nterror(req, NT_STATUS_NO_MEMORY);
4178 return;
4180 params = *pparams;
4181 SSVAL(params,0,0);
4182 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4183 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4184 if (*ppdata == NULL ) {
4185 reply_nterror(req, NT_STATUS_NO_MEMORY);
4186 return;
4188 pdata = *ppdata;
4189 dstart = pdata;
4190 dend = dstart + data_size - 1;
4192 create_time_ts = sbuf.st_ex_btime;
4193 mtime_ts = sbuf.st_ex_mtime;
4194 atime_ts = sbuf.st_ex_atime;
4196 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4198 if (!fsp) {
4199 /* Do we have this path open ? */
4200 files_struct *fsp1;
4201 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4202 fsp1 = file_find_di_first(fileid);
4203 if (fsp1 && fsp1->initial_allocation_size) {
4204 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4208 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4209 mtime_ts = write_time_ts;
4212 if (lp_dos_filetime_resolution(SNUM(conn))) {
4213 dos_filetime_timespec(&create_time_ts);
4214 dos_filetime_timespec(&mtime_ts);
4215 dos_filetime_timespec(&atime_ts);
4218 create_time = convert_timespec_to_time_t(create_time_ts);
4219 mtime = convert_timespec_to_time_t(mtime_ts);
4220 atime = convert_timespec_to_time_t(atime_ts);
4222 /* NT expects the name to be in an exact form of the *full*
4223 filename. See the trans2 torture test */
4224 if (ISDOT(base_name)) {
4225 dos_fname = talloc_strdup(ctx, "\\");
4226 if (!dos_fname) {
4227 reply_nterror(req, NT_STATUS_NO_MEMORY);
4228 return;
4230 } else {
4231 dos_fname = talloc_asprintf(ctx,
4232 "\\%s",
4233 fname);
4234 if (!dos_fname) {
4235 reply_nterror(req, NT_STATUS_NO_MEMORY);
4236 return;
4238 string_replace(dos_fname, '/', '\\');
4241 switch (info_level) {
4242 case SMB_INFO_STANDARD:
4243 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4244 data_size = 22;
4245 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4246 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4247 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4248 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4249 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4250 SSVAL(pdata,l1_attrFile,mode);
4251 break;
4253 case SMB_INFO_QUERY_EA_SIZE:
4255 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4257 data_size = 26;
4258 srv_put_dos_date2(pdata,0,create_time);
4259 srv_put_dos_date2(pdata,4,atime);
4260 srv_put_dos_date2(pdata,8,mtime); /* write time */
4261 SIVAL(pdata,12,(uint32)file_size);
4262 SIVAL(pdata,16,(uint32)allocation_size);
4263 SSVAL(pdata,20,mode);
4264 SIVAL(pdata,22,ea_size);
4265 break;
4268 case SMB_INFO_IS_NAME_VALID:
4269 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4270 if (tran_call == TRANSACT2_QFILEINFO) {
4271 /* os/2 needs this ? really ?*/
4272 reply_doserror(req, ERRDOS, ERRbadfunc);
4273 return;
4275 data_size = 0;
4276 param_size = 0;
4277 break;
4279 case SMB_INFO_QUERY_EAS_FROM_LIST:
4281 size_t total_ea_len = 0;
4282 struct ea_list *ea_file_list = NULL;
4284 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4286 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4287 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4289 if (!ea_list || (total_ea_len > data_size)) {
4290 data_size = 4;
4291 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4292 break;
4295 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4296 break;
4299 case SMB_INFO_QUERY_ALL_EAS:
4301 /* We have data_size bytes to put EA's into. */
4302 size_t total_ea_len = 0;
4304 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4306 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4307 if (!ea_list || (total_ea_len > data_size)) {
4308 data_size = 4;
4309 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4310 break;
4313 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4314 break;
4317 case SMB_FILE_BASIC_INFORMATION:
4318 case SMB_QUERY_FILE_BASIC_INFO:
4320 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4321 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4322 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4323 } else {
4324 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4325 data_size = 40;
4326 SIVAL(pdata,36,0);
4328 put_long_date_timespec(pdata,create_time_ts);
4329 put_long_date_timespec(pdata+8,atime_ts);
4330 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4331 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4332 SIVAL(pdata,32,mode);
4334 DEBUG(5,("SMB_QFBI - "));
4335 DEBUG(5,("create: %s ", ctime(&create_time)));
4336 DEBUG(5,("access: %s ", ctime(&atime)));
4337 DEBUG(5,("write: %s ", ctime(&mtime)));
4338 DEBUG(5,("change: %s ", ctime(&mtime)));
4339 DEBUG(5,("mode: %x\n", mode));
4340 break;
4342 case SMB_FILE_STANDARD_INFORMATION:
4343 case SMB_QUERY_FILE_STANDARD_INFO:
4345 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4346 data_size = 24;
4347 SOFF_T(pdata,0,allocation_size);
4348 SOFF_T(pdata,8,file_size);
4349 SIVAL(pdata,16,nlink);
4350 SCVAL(pdata,20,delete_pending?1:0);
4351 SCVAL(pdata,21,(mode&aDIR)?1:0);
4352 SSVAL(pdata,22,0); /* Padding. */
4353 break;
4355 case SMB_FILE_EA_INFORMATION:
4356 case SMB_QUERY_FILE_EA_INFO:
4358 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4359 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4360 data_size = 4;
4361 SIVAL(pdata,0,ea_size);
4362 break;
4365 /* Get the 8.3 name - used if NT SMB was negotiated. */
4366 case SMB_QUERY_FILE_ALT_NAME_INFO:
4367 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4369 char mangled_name[13];
4370 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4371 if (!name_to_8_3(base_name,mangled_name,
4372 True,conn->params)) {
4373 reply_nterror(
4374 req,
4375 NT_STATUS_NO_MEMORY);
4377 len = srvstr_push(dstart, req->flags2,
4378 pdata+4, mangled_name,
4379 PTR_DIFF(dend, pdata+4),
4380 STR_UNICODE);
4381 data_size = 4 + len;
4382 SIVAL(pdata,0,len);
4383 break;
4386 case SMB_QUERY_FILE_NAME_INFO:
4388 this must be *exactly* right for ACLs on mapped drives to work
4390 len = srvstr_push(dstart, req->flags2,
4391 pdata+4, dos_fname,
4392 PTR_DIFF(dend, pdata+4),
4393 STR_UNICODE);
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4395 data_size = 4 + len;
4396 SIVAL(pdata,0,len);
4397 break;
4399 case SMB_FILE_ALLOCATION_INFORMATION:
4400 case SMB_QUERY_FILE_ALLOCATION_INFO:
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4402 data_size = 8;
4403 SOFF_T(pdata,0,allocation_size);
4404 break;
4406 case SMB_FILE_END_OF_FILE_INFORMATION:
4407 case SMB_QUERY_FILE_END_OF_FILEINFO:
4408 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4409 data_size = 8;
4410 SOFF_T(pdata,0,file_size);
4411 break;
4413 case SMB_QUERY_FILE_ALL_INFO:
4414 case SMB_FILE_ALL_INFORMATION:
4416 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4417 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4418 put_long_date_timespec(pdata,create_time_ts);
4419 put_long_date_timespec(pdata+8,atime_ts);
4420 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4421 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4422 SIVAL(pdata,32,mode);
4423 SIVAL(pdata,36,0); /* padding. */
4424 pdata += 40;
4425 SOFF_T(pdata,0,allocation_size);
4426 SOFF_T(pdata,8,file_size);
4427 SIVAL(pdata,16,nlink);
4428 SCVAL(pdata,20,delete_pending);
4429 SCVAL(pdata,21,(mode&aDIR)?1:0);
4430 SSVAL(pdata,22,0);
4431 pdata += 24;
4432 SIVAL(pdata,0,ea_size);
4433 pdata += 4; /* EA info */
4434 len = srvstr_push(dstart, req->flags2,
4435 pdata+4, dos_fname,
4436 PTR_DIFF(dend, pdata+4),
4437 STR_UNICODE);
4438 SIVAL(pdata,0,len);
4439 pdata += 4 + len;
4440 data_size = PTR_DIFF(pdata,(*ppdata));
4441 break;
4443 case SMB_FILE_INTERNAL_INFORMATION:
4444 /* This should be an index number - looks like
4445 dev/ino to me :-)
4447 I think this causes us to fail the IFSKIT
4448 BasicFileInformationTest. -tpot */
4450 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4451 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4452 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4453 data_size = 8;
4454 break;
4456 case SMB_FILE_ACCESS_INFORMATION:
4457 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4458 if (fsp) {
4459 SIVAL(pdata,0,fsp->access_mask);
4460 } else {
4461 /* GENERIC_EXECUTE mapping from Windows */
4462 SIVAL(pdata,0,0x12019F);
4464 data_size = 4;
4465 break;
4467 case SMB_FILE_NAME_INFORMATION:
4468 /* Pathname with leading '\'. */
4470 size_t byte_len;
4471 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4473 SIVAL(pdata,0,byte_len);
4474 data_size = 4 + byte_len;
4475 break;
4478 case SMB_FILE_DISPOSITION_INFORMATION:
4479 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4480 data_size = 1;
4481 SCVAL(pdata,0,delete_pending);
4482 break;
4484 case SMB_FILE_POSITION_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4486 data_size = 8;
4487 SOFF_T(pdata,0,pos);
4488 break;
4490 case SMB_FILE_MODE_INFORMATION:
4491 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4492 SIVAL(pdata,0,mode);
4493 data_size = 4;
4494 break;
4496 case SMB_FILE_ALIGNMENT_INFORMATION:
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4498 SIVAL(pdata,0,0); /* No alignment needed. */
4499 data_size = 4;
4500 break;
4503 * NT4 server just returns "invalid query" to this - if we try
4504 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4505 * want this. JRA.
4507 /* The first statement above is false - verified using Thursby
4508 * client against NT4 -- gcolley.
4510 case SMB_QUERY_FILE_STREAM_INFO:
4511 case SMB_FILE_STREAM_INFORMATION: {
4512 unsigned int num_streams;
4513 struct stream_struct *streams;
4514 NTSTATUS status;
4516 DEBUG(10,("call_trans2qfilepathinfo: "
4517 "SMB_FILE_STREAM_INFORMATION\n"));
4519 status = SMB_VFS_STREAMINFO(
4520 conn, fsp, fname, talloc_tos(),
4521 &num_streams, &streams);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 DEBUG(10, ("could not get stream info: %s\n",
4525 nt_errstr(status)));
4526 reply_nterror(req, status);
4527 return;
4530 status = marshall_stream_info(num_streams, streams,
4531 pdata, max_data_bytes,
4532 &data_size);
4534 if (!NT_STATUS_IS_OK(status)) {
4535 DEBUG(10, ("marshall_stream_info failed: %s\n",
4536 nt_errstr(status)));
4537 reply_nterror(req, status);
4538 return;
4541 TALLOC_FREE(streams);
4543 break;
4545 case SMB_QUERY_COMPRESSION_INFO:
4546 case SMB_FILE_COMPRESSION_INFORMATION:
4547 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4548 SOFF_T(pdata,0,file_size);
4549 SIVAL(pdata,8,0); /* ??? */
4550 SIVAL(pdata,12,0); /* ??? */
4551 data_size = 16;
4552 break;
4554 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4555 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4556 put_long_date_timespec(pdata,create_time_ts);
4557 put_long_date_timespec(pdata+8,atime_ts);
4558 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4559 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4560 SOFF_T(pdata,32,allocation_size);
4561 SOFF_T(pdata,40,file_size);
4562 SIVAL(pdata,48,mode);
4563 SIVAL(pdata,52,0); /* ??? */
4564 data_size = 56;
4565 break;
4567 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4568 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4569 SIVAL(pdata,0,mode);
4570 SIVAL(pdata,4,0);
4571 data_size = 8;
4572 break;
4575 * CIFS UNIX Extensions.
4578 case SMB_QUERY_FILE_UNIX_BASIC:
4580 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4584 int i;
4585 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4587 for (i=0; i<100; i++)
4588 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4589 DEBUG(4,("\n"));
4592 break;
4594 case SMB_QUERY_FILE_UNIX_INFO2:
4596 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4597 data_size = PTR_DIFF(pdata,(*ppdata));
4600 int i;
4601 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4603 for (i=0; i<100; i++)
4604 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4605 DEBUG(4,("\n"));
4608 break;
4610 case SMB_QUERY_FILE_UNIX_LINK:
4612 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4614 if (!buffer) {
4615 reply_nterror(req, NT_STATUS_NO_MEMORY);
4616 return;
4619 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4620 #ifdef S_ISLNK
4621 if(!S_ISLNK(sbuf.st_ex_mode)) {
4622 reply_unixerror(req, ERRSRV,
4623 ERRbadlink);
4624 return;
4626 #else
4627 reply_unixerror(req, ERRDOS, ERRbadlink);
4628 return;
4629 #endif
4630 len = SMB_VFS_READLINK(conn,fullpathname,
4631 buffer, PATH_MAX);
4632 if (len == -1) {
4633 reply_unixerror(req, ERRDOS,
4634 ERRnoaccess);
4635 return;
4637 buffer[len] = 0;
4638 len = srvstr_push(dstart, req->flags2,
4639 pdata, buffer,
4640 PTR_DIFF(dend, pdata),
4641 STR_TERMINATE);
4642 pdata += len;
4643 data_size = PTR_DIFF(pdata,(*ppdata));
4645 break;
4648 #if defined(HAVE_POSIX_ACLS)
4649 case SMB_QUERY_POSIX_ACL:
4651 SMB_ACL_T file_acl = NULL;
4652 SMB_ACL_T def_acl = NULL;
4653 uint16 num_file_acls = 0;
4654 uint16 num_def_acls = 0;
4656 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4657 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4658 } else {
4659 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4662 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4663 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4664 fname ));
4665 reply_nterror(
4666 req,
4667 NT_STATUS_NOT_IMPLEMENTED);
4668 return;
4671 if (S_ISDIR(sbuf.st_ex_mode)) {
4672 if (fsp && fsp->is_directory) {
4673 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4674 } else {
4675 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4677 def_acl = free_empty_sys_acl(conn, def_acl);
4680 num_file_acls = count_acl_entries(conn, file_acl);
4681 num_def_acls = count_acl_entries(conn, def_acl);
4683 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4684 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4685 data_size,
4686 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4687 SMB_POSIX_ACL_HEADER_SIZE) ));
4688 if (file_acl) {
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4691 if (def_acl) {
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4694 reply_nterror(
4695 req,
4696 NT_STATUS_BUFFER_TOO_SMALL);
4697 return;
4700 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4701 SSVAL(pdata,2,num_file_acls);
4702 SSVAL(pdata,4,num_def_acls);
4703 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4704 if (file_acl) {
4705 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4707 if (def_acl) {
4708 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4710 reply_nterror(
4711 req, NT_STATUS_INTERNAL_ERROR);
4712 return;
4714 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4715 if (file_acl) {
4716 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4718 if (def_acl) {
4719 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4721 reply_nterror(
4722 req,
4723 NT_STATUS_INTERNAL_ERROR);
4724 return;
4727 if (file_acl) {
4728 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4730 if (def_acl) {
4731 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4733 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4734 break;
4736 #endif
4739 case SMB_QUERY_POSIX_LOCK:
4741 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4742 uint64_t count;
4743 uint64_t offset;
4744 uint32 lock_pid;
4745 enum brl_type lock_type;
4747 if (total_data != POSIX_LOCK_DATA_SIZE) {
4748 reply_nterror(
4749 req, NT_STATUS_INVALID_PARAMETER);
4750 return;
4753 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4754 case POSIX_LOCK_TYPE_READ:
4755 lock_type = READ_LOCK;
4756 break;
4757 case POSIX_LOCK_TYPE_WRITE:
4758 lock_type = WRITE_LOCK;
4759 break;
4760 case POSIX_LOCK_TYPE_UNLOCK:
4761 default:
4762 /* There's no point in asking for an unlock... */
4763 reply_nterror(
4764 req,
4765 NT_STATUS_INVALID_PARAMETER);
4766 return;
4769 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4770 #if defined(HAVE_LONGLONG)
4771 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4772 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4773 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4774 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4775 #else /* HAVE_LONGLONG */
4776 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4777 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4778 #endif /* HAVE_LONGLONG */
4780 status = query_lock(fsp,
4781 &lock_pid,
4782 &count,
4783 &offset,
4784 &lock_type,
4785 POSIX_LOCK);
4787 if (ERROR_WAS_LOCK_DENIED(status)) {
4788 /* Here we need to report who has it locked... */
4789 data_size = POSIX_LOCK_DATA_SIZE;
4791 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4792 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4793 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4794 #if defined(HAVE_LONGLONG)
4795 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4796 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4797 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4798 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4799 #else /* HAVE_LONGLONG */
4800 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4801 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4802 #endif /* HAVE_LONGLONG */
4804 } else if (NT_STATUS_IS_OK(status)) {
4805 /* For success we just return a copy of what we sent
4806 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4807 data_size = POSIX_LOCK_DATA_SIZE;
4808 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4809 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4810 } else {
4811 reply_nterror(req, status);
4812 return;
4814 break;
4817 default:
4818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4819 return;
4822 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4823 max_data_bytes);
4825 return;
4828 /****************************************************************************
4829 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4830 code.
4831 ****************************************************************************/
4833 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4834 connection_struct *conn,
4835 const char *oldname_in,
4836 const char *newname_in)
4838 struct smb_filename *smb_fname = NULL;
4839 struct smb_filename *smb_fname_new = NULL;
4840 char *oldname = NULL;
4841 char *newname = NULL;
4842 NTSTATUS status = NT_STATUS_OK;
4844 status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
4845 if (!NT_STATUS_IS_OK(status)) {
4846 goto out;
4849 status = get_full_smb_filename(ctx, smb_fname, &oldname);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 goto out;
4854 status = check_name(conn, oldname);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 goto out;
4859 /* source must already exist. */
4860 if (!VALID_STAT(smb_fname->st)) {
4861 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4862 goto out;
4865 status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 goto out;
4870 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 goto out;
4875 status = check_name(conn, newname);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 goto out;
4880 /* Disallow if newname already exists. */
4881 if (VALID_STAT(smb_fname_new->st)) {
4882 status = NT_STATUS_OBJECT_NAME_COLLISION;
4883 goto out;
4886 /* No links from a directory. */
4887 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4888 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4889 goto out;
4892 /* Ensure this is within the share. */
4893 status = check_reduced_name(conn, oldname);
4894 if (!NT_STATUS_IS_OK(status)) {
4895 goto out;
4898 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4900 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4901 status = map_nt_error_from_unix(errno);
4902 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4903 nt_errstr(status), newname, oldname));
4905 out:
4906 TALLOC_FREE(smb_fname);
4907 TALLOC_FREE(smb_fname_new);
4908 return status;
4911 /****************************************************************************
4912 Deal with setting the time from any of the setfilepathinfo functions.
4913 ****************************************************************************/
4915 NTSTATUS smb_set_file_time(connection_struct *conn,
4916 files_struct *fsp,
4917 const char *fname,
4918 const SMB_STRUCT_STAT *psbuf,
4919 struct smb_file_time *ft,
4920 bool setting_write_time)
4922 uint32 action =
4923 FILE_NOTIFY_CHANGE_LAST_ACCESS
4924 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4926 if (!VALID_STAT(*psbuf)) {
4927 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4930 /* get some defaults (no modifications) if any info is zero or -1. */
4931 if (null_timespec(ft->atime)) {
4932 ft->atime= psbuf->st_ex_atime;
4933 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4936 if (null_timespec(ft->mtime)) {
4937 ft->mtime = psbuf->st_ex_mtime;
4938 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4941 if (!setting_write_time) {
4942 /* ft->mtime comes from change time, not write time. */
4943 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4946 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4947 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4948 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4949 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4950 if (!null_timespec(ft->create_time)) {
4951 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4952 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4956 * Try and set the times of this file if
4957 * they are different from the current values.
4961 struct timespec mts = psbuf->st_ex_mtime;
4962 struct timespec ats = psbuf->st_ex_atime;
4963 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4964 (timespec_compare(&ft->mtime, &mts) == 0)) {
4965 return NT_STATUS_OK;
4969 if (setting_write_time) {
4971 * This was a setfileinfo on an open file.
4972 * NT does this a lot. We also need to
4973 * set the time here, as it can be read by
4974 * FindFirst/FindNext and with the patch for bug #2045
4975 * in smbd/fileio.c it ensures that this timestamp is
4976 * kept sticky even after a write. We save the request
4977 * away and will set it on file close and after a write. JRA.
4980 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4981 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4983 if (fsp != NULL) {
4984 if (fsp->base_fsp) {
4985 set_sticky_write_time_fsp(fsp->base_fsp,
4986 ft->mtime);
4987 } else {
4988 set_sticky_write_time_fsp(fsp, ft->mtime);
4990 } else {
4991 set_sticky_write_time_path(conn, fname,
4992 vfs_file_id_from_sbuf(conn, psbuf),
4993 ft->mtime);
4997 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4999 if (fsp && fsp->base_fsp) {
5000 fname = fsp->base_fsp->fsp_name;
5003 if(file_ntimes(conn, fname, ft)!=0) {
5004 return map_nt_error_from_unix(errno);
5006 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5008 return NT_STATUS_OK;
5011 /****************************************************************************
5012 Deal with setting the dosmode from any of the setfilepathinfo functions.
5013 ****************************************************************************/
5015 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5016 files_struct *fsp,
5017 const char *fname,
5018 SMB_STRUCT_STAT *psbuf,
5019 uint32 dosmode)
5021 if (!VALID_STAT(*psbuf)) {
5022 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5025 if (fsp) {
5026 if (fsp->base_fsp) {
5027 fname = fsp->base_fsp->fsp_name;
5028 } else {
5029 fname = fsp->fsp_name;
5033 if (dosmode) {
5034 if (S_ISDIR(psbuf->st_ex_mode)) {
5035 dosmode |= aDIR;
5036 } else {
5037 dosmode &= ~aDIR;
5041 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5043 /* check the mode isn't different, before changing it */
5044 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5046 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5047 fname, (unsigned int)dosmode ));
5049 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5050 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5051 fname, strerror(errno)));
5052 return map_nt_error_from_unix(errno);
5055 return NT_STATUS_OK;
5058 /****************************************************************************
5059 Deal with setting the size from any of the setfilepathinfo functions.
5060 ****************************************************************************/
5062 static NTSTATUS smb_set_file_size(connection_struct *conn,
5063 struct smb_request *req,
5064 files_struct *fsp,
5065 const char *fname,
5066 SMB_STRUCT_STAT *psbuf,
5067 SMB_OFF_T size)
5069 NTSTATUS status = NT_STATUS_OK;
5070 files_struct *new_fsp = NULL;
5072 if (!VALID_STAT(*psbuf)) {
5073 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5076 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5078 if (size == get_file_size_stat(psbuf)) {
5079 return NT_STATUS_OK;
5082 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5083 fname, (double)size ));
5085 if (fsp && fsp->fh->fd != -1) {
5086 /* Handle based call. */
5087 if (vfs_set_filelen(fsp, size) == -1) {
5088 return map_nt_error_from_unix(errno);
5090 trigger_write_time_update_immediate(fsp);
5091 return NT_STATUS_OK;
5094 status = SMB_VFS_CREATE_FILE(
5095 conn, /* conn */
5096 req, /* req */
5097 0, /* root_dir_fid */
5098 fname, /* fname */
5099 0, /* create_file_flags */
5100 FILE_WRITE_ATTRIBUTES, /* access_mask */
5101 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5102 FILE_SHARE_DELETE),
5103 FILE_OPEN, /* create_disposition*/
5104 0, /* create_options */
5105 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5106 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5107 0, /* allocation_size */
5108 NULL, /* sd */
5109 NULL, /* ea_list */
5110 &new_fsp, /* result */
5111 NULL, /* pinfo */
5112 psbuf); /* psbuf */
5114 if (!NT_STATUS_IS_OK(status)) {
5115 /* NB. We check for open_was_deferred in the caller. */
5116 return status;
5119 if (vfs_set_filelen(new_fsp, size) == -1) {
5120 status = map_nt_error_from_unix(errno);
5121 close_file(req, new_fsp,NORMAL_CLOSE);
5122 return status;
5125 trigger_write_time_update_immediate(new_fsp);
5126 close_file(req, new_fsp,NORMAL_CLOSE);
5127 return NT_STATUS_OK;
5130 /****************************************************************************
5131 Deal with SMB_INFO_SET_EA.
5132 ****************************************************************************/
5134 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5135 const char *pdata,
5136 int total_data,
5137 files_struct *fsp,
5138 const char *fname)
5140 struct ea_list *ea_list = NULL;
5141 TALLOC_CTX *ctx = NULL;
5142 NTSTATUS status = NT_STATUS_OK;
5144 if (total_data < 10) {
5146 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5147 length. They seem to have no effect. Bug #3212. JRA */
5149 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5150 /* We're done. We only get EA info in this call. */
5151 return NT_STATUS_OK;
5154 return NT_STATUS_INVALID_PARAMETER;
5157 if (IVAL(pdata,0) > total_data) {
5158 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5159 IVAL(pdata,0), (unsigned int)total_data));
5160 return NT_STATUS_INVALID_PARAMETER;
5163 ctx = talloc_tos();
5164 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5165 if (!ea_list) {
5166 return NT_STATUS_INVALID_PARAMETER;
5168 status = set_ea(conn, fsp, fname, ea_list);
5170 return status;
5173 /****************************************************************************
5174 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5175 ****************************************************************************/
5177 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5178 const char *pdata,
5179 int total_data,
5180 files_struct *fsp,
5181 const char *fname,
5182 SMB_STRUCT_STAT *psbuf)
5184 NTSTATUS status = NT_STATUS_OK;
5185 bool delete_on_close;
5186 uint32 dosmode = 0;
5188 if (total_data < 1) {
5189 return NT_STATUS_INVALID_PARAMETER;
5192 if (fsp == NULL) {
5193 return NT_STATUS_INVALID_HANDLE;
5196 delete_on_close = (CVAL(pdata,0) ? True : False);
5197 dosmode = dos_mode(conn, fname, psbuf);
5199 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5200 "delete_on_close = %u\n",
5201 fsp->fsp_name,
5202 (unsigned int)dosmode,
5203 (unsigned int)delete_on_close ));
5205 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5207 if (!NT_STATUS_IS_OK(status)) {
5208 return status;
5211 /* The set is across all open files on this dev/inode pair. */
5212 if (!set_delete_on_close(fsp, delete_on_close,
5213 &conn->server_info->utok)) {
5214 return NT_STATUS_ACCESS_DENIED;
5216 return NT_STATUS_OK;
5219 /****************************************************************************
5220 Deal with SMB_FILE_POSITION_INFORMATION.
5221 ****************************************************************************/
5223 static NTSTATUS smb_file_position_information(connection_struct *conn,
5224 const char *pdata,
5225 int total_data,
5226 files_struct *fsp)
5228 uint64_t position_information;
5230 if (total_data < 8) {
5231 return NT_STATUS_INVALID_PARAMETER;
5234 if (fsp == NULL) {
5235 /* Ignore on pathname based set. */
5236 return NT_STATUS_OK;
5239 position_information = (uint64_t)IVAL(pdata,0);
5240 #ifdef LARGE_SMB_OFF_T
5241 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5242 #else /* LARGE_SMB_OFF_T */
5243 if (IVAL(pdata,4) != 0) {
5244 /* more than 32 bits? */
5245 return NT_STATUS_INVALID_PARAMETER;
5247 #endif /* LARGE_SMB_OFF_T */
5249 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5250 fsp->fsp_name, (double)position_information ));
5251 fsp->fh->position_information = position_information;
5252 return NT_STATUS_OK;
5255 /****************************************************************************
5256 Deal with SMB_FILE_MODE_INFORMATION.
5257 ****************************************************************************/
5259 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5260 const char *pdata,
5261 int total_data)
5263 uint32 mode;
5265 if (total_data < 4) {
5266 return NT_STATUS_INVALID_PARAMETER;
5268 mode = IVAL(pdata,0);
5269 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5270 return NT_STATUS_INVALID_PARAMETER;
5272 return NT_STATUS_OK;
5275 /****************************************************************************
5276 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5277 ****************************************************************************/
5279 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5280 struct smb_request *req,
5281 const char *pdata,
5282 int total_data,
5283 const char *fname)
5285 char *link_target = NULL;
5286 const char *newname = fname;
5287 NTSTATUS status = NT_STATUS_OK;
5288 TALLOC_CTX *ctx = talloc_tos();
5290 /* Set a symbolic link. */
5291 /* Don't allow this if follow links is false. */
5293 if (total_data == 0) {
5294 return NT_STATUS_INVALID_PARAMETER;
5297 if (!lp_symlinks(SNUM(conn))) {
5298 return NT_STATUS_ACCESS_DENIED;
5301 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5302 total_data, STR_TERMINATE);
5304 if (!link_target) {
5305 return NT_STATUS_INVALID_PARAMETER;
5308 /* !widelinks forces the target path to be within the share. */
5309 /* This means we can interpret the target as a pathname. */
5310 if (!lp_widelinks(SNUM(conn))) {
5311 char *rel_name = NULL;
5312 char *last_dirp = NULL;
5314 if (*link_target == '/') {
5315 /* No absolute paths allowed. */
5316 return NT_STATUS_ACCESS_DENIED;
5318 rel_name = talloc_strdup(ctx,newname);
5319 if (!rel_name) {
5320 return NT_STATUS_NO_MEMORY;
5322 last_dirp = strrchr_m(rel_name, '/');
5323 if (last_dirp) {
5324 last_dirp[1] = '\0';
5325 } else {
5326 rel_name = talloc_strdup(ctx,"./");
5327 if (!rel_name) {
5328 return NT_STATUS_NO_MEMORY;
5331 rel_name = talloc_asprintf_append(rel_name,
5332 "%s",
5333 link_target);
5334 if (!rel_name) {
5335 return NT_STATUS_NO_MEMORY;
5338 status = check_name(conn, rel_name);
5339 if (!NT_STATUS_IS_OK(status)) {
5340 return status;
5344 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5345 newname, link_target ));
5347 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5348 return map_nt_error_from_unix(errno);
5351 return NT_STATUS_OK;
5354 /****************************************************************************
5355 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5356 ****************************************************************************/
5358 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5359 struct smb_request *req,
5360 const char *pdata, int total_data,
5361 const char *fname)
5363 char *oldname = NULL;
5364 TALLOC_CTX *ctx = talloc_tos();
5365 NTSTATUS status = NT_STATUS_OK;
5367 /* Set a hard link. */
5368 if (total_data == 0) {
5369 return NT_STATUS_INVALID_PARAMETER;
5372 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5373 total_data, STR_TERMINATE, &status);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 return status;
5378 status = resolve_dfspath(ctx, conn,
5379 req->flags2 & FLAGS2_DFS_PATHNAMES,
5380 oldname,
5381 &oldname);
5382 if (!NT_STATUS_IS_OK(status)) {
5383 return status;
5386 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5387 fname, oldname));
5389 return hardlink_internals(ctx, conn, oldname, fname);
5392 /****************************************************************************
5393 Deal with SMB_FILE_RENAME_INFORMATION.
5394 ****************************************************************************/
5396 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5397 struct smb_request *req,
5398 const char *pdata,
5399 int total_data,
5400 files_struct *fsp,
5401 const char *fname)
5403 bool overwrite;
5404 uint32 root_fid;
5405 uint32 len;
5406 char *newname = NULL;
5407 char *base_name = NULL;
5408 struct smb_filename *smb_fname = NULL;
5409 bool dest_has_wcard = False;
5410 NTSTATUS status = NT_STATUS_OK;
5411 char *p;
5412 TALLOC_CTX *ctx = talloc_tos();
5414 if (total_data < 13) {
5415 return NT_STATUS_INVALID_PARAMETER;
5418 overwrite = (CVAL(pdata,0) ? True : False);
5419 root_fid = IVAL(pdata,4);
5420 len = IVAL(pdata,8);
5422 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5423 return NT_STATUS_INVALID_PARAMETER;
5426 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5427 len, 0, &status,
5428 &dest_has_wcard);
5429 if (!NT_STATUS_IS_OK(status)) {
5430 return status;
5433 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5434 newname));
5436 status = resolve_dfspath_wcard(ctx, conn,
5437 req->flags2 & FLAGS2_DFS_PATHNAMES,
5438 newname,
5439 &newname,
5440 &dest_has_wcard);
5441 if (!NT_STATUS_IS_OK(status)) {
5442 return status;
5445 /* Check the new name has no '/' characters. */
5446 if (strchr_m(newname, '/')) {
5447 return NT_STATUS_NOT_SUPPORTED;
5450 if (fsp && fsp->base_fsp) {
5451 /* newname must be a stream name. */
5452 if (newname[0] != ':') {
5453 return NT_STATUS_NOT_SUPPORTED;
5455 base_name = talloc_asprintf(ctx, "%s%s",
5456 fsp->base_fsp->fsp_name,
5457 newname);
5458 if (!base_name) {
5459 return NT_STATUS_NO_MEMORY;
5461 } else {
5462 /* newname must *not* be a stream name. */
5463 if (is_ntfs_stream_name(newname)) {
5464 return NT_STATUS_NOT_SUPPORTED;
5467 /* Create the base directory. */
5468 base_name = talloc_strdup(ctx, fname);
5469 if (!base_name) {
5470 return NT_STATUS_NO_MEMORY;
5472 p = strrchr_m(base_name, '/');
5473 if (p) {
5474 p[1] = '\0';
5475 } else {
5476 base_name = talloc_strdup(ctx, "./");
5477 if (!base_name) {
5478 return NT_STATUS_NO_MEMORY;
5481 /* Append the new name. */
5482 base_name = talloc_asprintf_append(base_name,
5483 "%s",
5484 newname);
5485 if (!base_name) {
5486 return NT_STATUS_NO_MEMORY;
5489 status = unix_convert(ctx, conn, newname, &smb_fname,
5490 UCF_SAVE_LCOMP);
5492 /* If an error we expect this to be
5493 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5495 if (!NT_STATUS_IS_OK(status)
5496 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5497 status)) {
5498 goto out;
5502 if (fsp) {
5503 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5504 fsp->fnum, fsp->fsp_name, base_name ));
5505 status = rename_internals_fsp(conn, fsp, base_name,
5506 smb_fname ?
5507 smb_fname->original_lcomp : NULL,
5508 0, overwrite);
5509 } else {
5510 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5511 fname, base_name ));
5512 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5513 overwrite, False, dest_has_wcard,
5514 FILE_WRITE_ATTRIBUTES);
5516 out:
5517 TALLOC_FREE(smb_fname);
5518 return status;
5521 /****************************************************************************
5522 Deal with SMB_SET_POSIX_ACL.
5523 ****************************************************************************/
5525 #if defined(HAVE_POSIX_ACLS)
5526 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5527 const char *pdata,
5528 int total_data,
5529 files_struct *fsp,
5530 const char *fname,
5531 SMB_STRUCT_STAT *psbuf)
5533 uint16 posix_acl_version;
5534 uint16 num_file_acls;
5535 uint16 num_def_acls;
5536 bool valid_file_acls = True;
5537 bool valid_def_acls = True;
5539 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5540 return NT_STATUS_INVALID_PARAMETER;
5542 posix_acl_version = SVAL(pdata,0);
5543 num_file_acls = SVAL(pdata,2);
5544 num_def_acls = SVAL(pdata,4);
5546 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5547 valid_file_acls = False;
5548 num_file_acls = 0;
5551 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5552 valid_def_acls = False;
5553 num_def_acls = 0;
5556 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5557 return NT_STATUS_INVALID_PARAMETER;
5560 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5561 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5562 return NT_STATUS_INVALID_PARAMETER;
5565 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5566 fname ? fname : fsp->fsp_name,
5567 (unsigned int)num_file_acls,
5568 (unsigned int)num_def_acls));
5570 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5571 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5572 return map_nt_error_from_unix(errno);
5575 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5576 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5577 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5578 return map_nt_error_from_unix(errno);
5580 return NT_STATUS_OK;
5582 #endif
5584 /****************************************************************************
5585 Deal with SMB_SET_POSIX_LOCK.
5586 ****************************************************************************/
5588 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5589 struct smb_request *req,
5590 const char *pdata,
5591 int total_data,
5592 files_struct *fsp)
5594 uint64_t count;
5595 uint64_t offset;
5596 uint32 lock_pid;
5597 bool blocking_lock = False;
5598 enum brl_type lock_type;
5600 NTSTATUS status = NT_STATUS_OK;
5602 if (fsp == NULL || fsp->fh->fd == -1) {
5603 return NT_STATUS_INVALID_HANDLE;
5606 if (total_data != POSIX_LOCK_DATA_SIZE) {
5607 return NT_STATUS_INVALID_PARAMETER;
5610 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5611 case POSIX_LOCK_TYPE_READ:
5612 lock_type = READ_LOCK;
5613 break;
5614 case POSIX_LOCK_TYPE_WRITE:
5615 /* Return the right POSIX-mappable error code for files opened read-only. */
5616 if (!fsp->can_write) {
5617 return NT_STATUS_INVALID_HANDLE;
5619 lock_type = WRITE_LOCK;
5620 break;
5621 case POSIX_LOCK_TYPE_UNLOCK:
5622 lock_type = UNLOCK_LOCK;
5623 break;
5624 default:
5625 return NT_STATUS_INVALID_PARAMETER;
5628 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5629 blocking_lock = False;
5630 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5631 blocking_lock = True;
5632 } else {
5633 return NT_STATUS_INVALID_PARAMETER;
5636 if (!lp_blocking_locks(SNUM(conn))) {
5637 blocking_lock = False;
5640 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5641 #if defined(HAVE_LONGLONG)
5642 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5643 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5644 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5645 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5646 #else /* HAVE_LONGLONG */
5647 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5648 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5649 #endif /* HAVE_LONGLONG */
5651 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5652 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5653 fsp->fsp_name,
5654 (unsigned int)lock_type,
5655 (unsigned int)lock_pid,
5656 (double)count,
5657 (double)offset ));
5659 if (lock_type == UNLOCK_LOCK) {
5660 status = do_unlock(smbd_messaging_context(),
5661 fsp,
5662 lock_pid,
5663 count,
5664 offset,
5665 POSIX_LOCK);
5666 } else {
5667 uint32 block_smbpid;
5669 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5670 fsp,
5671 lock_pid,
5672 count,
5673 offset,
5674 lock_type,
5675 POSIX_LOCK,
5676 blocking_lock,
5677 &status,
5678 &block_smbpid,
5679 NULL);
5681 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5683 * A blocking lock was requested. Package up
5684 * this smb into a queued request and push it
5685 * onto the blocking lock queue.
5687 if(push_blocking_lock_request(br_lck,
5688 req,
5689 fsp,
5690 -1, /* infinite timeout. */
5692 lock_pid,
5693 lock_type,
5694 POSIX_LOCK,
5695 offset,
5696 count,
5697 block_smbpid)) {
5698 TALLOC_FREE(br_lck);
5699 return status;
5702 TALLOC_FREE(br_lck);
5705 return status;
5708 /****************************************************************************
5709 Deal with SMB_INFO_STANDARD.
5710 ****************************************************************************/
5712 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5713 const char *pdata,
5714 int total_data,
5715 files_struct *fsp,
5716 const char *fname,
5717 const SMB_STRUCT_STAT *psbuf)
5719 struct smb_file_time ft;
5720 ZERO_STRUCT(ft);
5722 if (total_data < 12) {
5723 return NT_STATUS_INVALID_PARAMETER;
5726 /* create time */
5727 ft.create_time = interpret_long_date(pdata);
5729 /* access time */
5730 ft.atime = interpret_long_date(pdata + 8);
5732 /* write time */
5733 ft.mtime = interpret_long_date(pdata + 16);
5735 DEBUG(10,("smb_set_info_standard: file %s\n",
5736 fname ? fname : fsp->fsp_name ));
5738 return smb_set_file_time(conn,
5739 fsp,
5740 fname,
5741 psbuf,
5742 &ft,
5743 true);
5746 /****************************************************************************
5747 Deal with SMB_SET_FILE_BASIC_INFO.
5748 ****************************************************************************/
5750 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5751 const char *pdata,
5752 int total_data,
5753 files_struct *fsp,
5754 const char *fname,
5755 SMB_STRUCT_STAT *psbuf)
5757 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5758 struct timespec write_time;
5759 struct timespec changed_time;
5760 struct smb_file_time ft;
5761 uint32 dosmode = 0;
5762 NTSTATUS status = NT_STATUS_OK;
5763 bool setting_write_time = true;
5765 ZERO_STRUCT(ft);
5767 if (total_data < 36) {
5768 return NT_STATUS_INVALID_PARAMETER;
5771 /* Set the attributes */
5772 dosmode = IVAL(pdata,32);
5773 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5774 if (!NT_STATUS_IS_OK(status)) {
5775 return status;
5778 /* access time */
5779 ft.atime = interpret_long_date(pdata+8);
5781 write_time = interpret_long_date(pdata+16);
5782 changed_time = interpret_long_date(pdata+24);
5784 /* mtime */
5785 ft.mtime = timespec_min(&write_time, &changed_time);
5787 /* create time */
5788 ft.create_time = interpret_long_date(pdata);
5790 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5791 !null_timespec(write_time)) {
5792 ft.mtime = write_time;
5795 /* Prefer a defined time to an undefined one. */
5796 if (null_timespec(ft.mtime)) {
5797 if (null_timespec(write_time)) {
5798 ft.mtime = changed_time;
5799 setting_write_time = false;
5800 } else {
5801 ft.mtime = write_time;
5805 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5806 fname ? fname : fsp->fsp_name ));
5808 return smb_set_file_time(conn,
5809 fsp,
5810 fname,
5811 psbuf,
5812 &ft,
5813 setting_write_time);
5816 /****************************************************************************
5817 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5818 ****************************************************************************/
5820 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5821 struct smb_request *req,
5822 const char *pdata,
5823 int total_data,
5824 files_struct *fsp,
5825 const char *fname,
5826 SMB_STRUCT_STAT *psbuf)
5828 uint64_t allocation_size = 0;
5829 NTSTATUS status = NT_STATUS_OK;
5830 files_struct *new_fsp = NULL;
5832 if (!VALID_STAT(*psbuf)) {
5833 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5836 if (total_data < 8) {
5837 return NT_STATUS_INVALID_PARAMETER;
5840 allocation_size = (uint64_t)IVAL(pdata,0);
5841 #ifdef LARGE_SMB_OFF_T
5842 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5843 #else /* LARGE_SMB_OFF_T */
5844 if (IVAL(pdata,4) != 0) {
5845 /* more than 32 bits? */
5846 return NT_STATUS_INVALID_PARAMETER;
5848 #endif /* LARGE_SMB_OFF_T */
5850 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5851 fname, (double)allocation_size ));
5853 if (allocation_size) {
5854 allocation_size = smb_roundup(conn, allocation_size);
5857 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5858 fname, (double)allocation_size ));
5860 if (fsp && fsp->fh->fd != -1) {
5861 /* Open file handle. */
5862 /* Only change if needed. */
5863 if (allocation_size != get_file_size_stat(psbuf)) {
5864 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5865 return map_nt_error_from_unix(errno);
5868 /* But always update the time. */
5870 * This is equivalent to a write. Ensure it's seen immediately
5871 * if there are no pending writes.
5873 trigger_write_time_update_immediate(fsp);
5874 return NT_STATUS_OK;
5877 /* Pathname or stat or directory file. */
5879 status = SMB_VFS_CREATE_FILE(
5880 conn, /* conn */
5881 req, /* req */
5882 0, /* root_dir_fid */
5883 fname, /* fname */
5884 0, /* create_file_flags */
5885 FILE_WRITE_DATA, /* access_mask */
5886 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5887 FILE_SHARE_DELETE),
5888 FILE_OPEN, /* create_disposition*/
5889 0, /* create_options */
5890 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5891 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5892 0, /* allocation_size */
5893 NULL, /* sd */
5894 NULL, /* ea_list */
5895 &new_fsp, /* result */
5896 NULL, /* pinfo */
5897 psbuf); /* psbuf */
5899 if (!NT_STATUS_IS_OK(status)) {
5900 /* NB. We check for open_was_deferred in the caller. */
5901 return status;
5904 /* Only change if needed. */
5905 if (allocation_size != get_file_size_stat(psbuf)) {
5906 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5907 status = map_nt_error_from_unix(errno);
5908 close_file(req, new_fsp, NORMAL_CLOSE);
5909 return status;
5913 /* Changing the allocation size should set the last mod time. */
5915 * This is equivalent to a write. Ensure it's seen immediately
5916 * if there are no pending writes.
5918 trigger_write_time_update_immediate(new_fsp);
5920 close_file(req, new_fsp, NORMAL_CLOSE);
5921 return NT_STATUS_OK;
5924 /****************************************************************************
5925 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5926 ****************************************************************************/
5928 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5929 struct smb_request *req,
5930 const char *pdata,
5931 int total_data,
5932 files_struct *fsp,
5933 const char *fname,
5934 SMB_STRUCT_STAT *psbuf)
5936 SMB_OFF_T size;
5938 if (total_data < 8) {
5939 return NT_STATUS_INVALID_PARAMETER;
5942 size = IVAL(pdata,0);
5943 #ifdef LARGE_SMB_OFF_T
5944 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5945 #else /* LARGE_SMB_OFF_T */
5946 if (IVAL(pdata,4) != 0) {
5947 /* more than 32 bits? */
5948 return NT_STATUS_INVALID_PARAMETER;
5950 #endif /* LARGE_SMB_OFF_T */
5951 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5952 "file %s to %.0f\n", fname, (double)size ));
5954 return smb_set_file_size(conn, req,
5955 fsp,
5956 fname,
5957 psbuf,
5958 size);
5961 /****************************************************************************
5962 Allow a UNIX info mknod.
5963 ****************************************************************************/
5965 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5966 const char *pdata,
5967 int total_data,
5968 const char *fname,
5969 SMB_STRUCT_STAT *psbuf)
5971 uint32 file_type = IVAL(pdata,56);
5972 #if defined(HAVE_MAKEDEV)
5973 uint32 dev_major = IVAL(pdata,60);
5974 uint32 dev_minor = IVAL(pdata,68);
5975 #endif
5976 SMB_DEV_T dev = (SMB_DEV_T)0;
5977 uint32 raw_unixmode = IVAL(pdata,84);
5978 NTSTATUS status;
5979 mode_t unixmode;
5981 if (total_data < 100) {
5982 return NT_STATUS_INVALID_PARAMETER;
5985 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 return status;
5990 #if defined(HAVE_MAKEDEV)
5991 dev = makedev(dev_major, dev_minor);
5992 #endif
5994 switch (file_type) {
5995 #if defined(S_IFIFO)
5996 case UNIX_TYPE_FIFO:
5997 unixmode |= S_IFIFO;
5998 break;
5999 #endif
6000 #if defined(S_IFSOCK)
6001 case UNIX_TYPE_SOCKET:
6002 unixmode |= S_IFSOCK;
6003 break;
6004 #endif
6005 #if defined(S_IFCHR)
6006 case UNIX_TYPE_CHARDEV:
6007 unixmode |= S_IFCHR;
6008 break;
6009 #endif
6010 #if defined(S_IFBLK)
6011 case UNIX_TYPE_BLKDEV:
6012 unixmode |= S_IFBLK;
6013 break;
6014 #endif
6015 default:
6016 return NT_STATUS_INVALID_PARAMETER;
6019 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6020 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6022 /* Ok - do the mknod. */
6023 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6024 return map_nt_error_from_unix(errno);
6027 /* If any of the other "set" calls fail we
6028 * don't want to end up with a half-constructed mknod.
6031 if (lp_inherit_perms(SNUM(conn))) {
6032 char *parent;
6033 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6034 return NT_STATUS_NO_MEMORY;
6036 inherit_access_posix_acl(conn, parent, fname, unixmode);
6037 TALLOC_FREE(parent);
6040 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6041 status = map_nt_error_from_unix(errno);
6042 SMB_VFS_UNLINK(conn,fname);
6043 return status;
6045 return NT_STATUS_OK;
6048 /****************************************************************************
6049 Deal with SMB_SET_FILE_UNIX_BASIC.
6050 ****************************************************************************/
6052 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6053 struct smb_request *req,
6054 const char *pdata,
6055 int total_data,
6056 files_struct *fsp,
6057 const char *fname,
6058 SMB_STRUCT_STAT *psbuf)
6060 struct smb_file_time ft;
6061 uint32 raw_unixmode;
6062 mode_t unixmode;
6063 SMB_OFF_T size = 0;
6064 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6065 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6066 NTSTATUS status = NT_STATUS_OK;
6067 bool delete_on_fail = False;
6068 enum perm_type ptype;
6070 ZERO_STRUCT(ft);
6072 if (total_data < 100) {
6073 return NT_STATUS_INVALID_PARAMETER;
6076 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6077 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6078 size=IVAL(pdata,0); /* first 8 Bytes are size */
6079 #ifdef LARGE_SMB_OFF_T
6080 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6081 #else /* LARGE_SMB_OFF_T */
6082 if (IVAL(pdata,4) != 0) {
6083 /* more than 32 bits? */
6084 return NT_STATUS_INVALID_PARAMETER;
6086 #endif /* LARGE_SMB_OFF_T */
6089 ft.atime = interpret_long_date(pdata+24); /* access_time */
6090 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6091 set_owner = (uid_t)IVAL(pdata,40);
6092 set_grp = (gid_t)IVAL(pdata,48);
6093 raw_unixmode = IVAL(pdata,84);
6095 if (VALID_STAT(*psbuf)) {
6096 if (S_ISDIR(psbuf->st_ex_mode)) {
6097 ptype = PERM_EXISTING_DIR;
6098 } else {
6099 ptype = PERM_EXISTING_FILE;
6101 } else {
6102 ptype = PERM_NEW_FILE;
6105 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 return status;
6110 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6111 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6112 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6114 if (!VALID_STAT(*psbuf)) {
6116 * The only valid use of this is to create character and block
6117 * devices, and named pipes. This is deprecated (IMHO) and
6118 * a new info level should be used for mknod. JRA.
6121 status = smb_unix_mknod(conn,
6122 pdata,
6123 total_data,
6124 fname,
6125 psbuf);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 return status;
6130 /* Ensure we don't try and change anything else. */
6131 raw_unixmode = SMB_MODE_NO_CHANGE;
6132 size = get_file_size_stat(psbuf);
6133 ft.atime = psbuf->st_ex_atime;
6134 ft.mtime = psbuf->st_ex_mtime;
6136 * We continue here as we might want to change the
6137 * owner uid/gid.
6139 delete_on_fail = True;
6142 #if 1
6143 /* Horrible backwards compatibility hack as an old server bug
6144 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6145 * */
6147 if (!size) {
6148 size = get_file_size_stat(psbuf);
6150 #endif
6153 * Deal with the UNIX specific mode set.
6156 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6157 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6158 (unsigned int)unixmode, fname ));
6159 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6160 return map_nt_error_from_unix(errno);
6165 * Deal with the UNIX specific uid set.
6168 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6169 int ret;
6171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6172 (unsigned int)set_owner, fname ));
6174 if (S_ISLNK(psbuf->st_ex_mode)) {
6175 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6176 } else {
6177 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6180 if (ret != 0) {
6181 status = map_nt_error_from_unix(errno);
6182 if (delete_on_fail) {
6183 SMB_VFS_UNLINK(conn,fname);
6185 return status;
6190 * Deal with the UNIX specific gid set.
6193 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6194 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6195 (unsigned int)set_owner, fname ));
6196 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6197 status = map_nt_error_from_unix(errno);
6198 if (delete_on_fail) {
6199 SMB_VFS_UNLINK(conn,fname);
6201 return status;
6205 /* Deal with any size changes. */
6207 status = smb_set_file_size(conn, req,
6208 fsp,
6209 fname,
6210 psbuf,
6211 size);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 return status;
6216 /* Deal with any time changes. */
6218 return smb_set_file_time(conn,
6219 fsp,
6220 fname,
6221 psbuf,
6222 &ft,
6223 true);
6226 /****************************************************************************
6227 Deal with SMB_SET_FILE_UNIX_INFO2.
6228 ****************************************************************************/
6230 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6231 struct smb_request *req,
6232 const char *pdata,
6233 int total_data,
6234 files_struct *fsp,
6235 const char *fname,
6236 SMB_STRUCT_STAT *psbuf)
6238 NTSTATUS status;
6239 uint32 smb_fflags;
6240 uint32 smb_fmask;
6242 if (total_data < 116) {
6243 return NT_STATUS_INVALID_PARAMETER;
6246 /* Start by setting all the fields that are common between UNIX_BASIC
6247 * and UNIX_INFO2.
6249 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6250 fsp, fname, psbuf);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 return status;
6255 smb_fflags = IVAL(pdata, 108);
6256 smb_fmask = IVAL(pdata, 112);
6258 /* NB: We should only attempt to alter the file flags if the client
6259 * sends a non-zero mask.
6261 if (smb_fmask != 0) {
6262 int stat_fflags = 0;
6264 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6265 &stat_fflags)) {
6266 /* Client asked to alter a flag we don't understand. */
6267 return NT_STATUS_INVALID_PARAMETER;
6270 if (fsp && fsp->fh->fd != -1) {
6271 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6272 return NT_STATUS_NOT_SUPPORTED;
6273 } else {
6274 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6275 return map_nt_error_from_unix(errno);
6280 /* XXX: need to add support for changing the create_time here. You
6281 * can do this for paths on Darwin with setattrlist(2). The right way
6282 * to hook this up is probably by extending the VFS utimes interface.
6285 return NT_STATUS_OK;
6288 /****************************************************************************
6289 Create a directory with POSIX semantics.
6290 ****************************************************************************/
6292 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6293 struct smb_request *req,
6294 char **ppdata,
6295 int total_data,
6296 const char *fname,
6297 SMB_STRUCT_STAT *psbuf,
6298 int *pdata_return_size)
6300 NTSTATUS status = NT_STATUS_OK;
6301 uint32 raw_unixmode = 0;
6302 uint32 mod_unixmode = 0;
6303 mode_t unixmode = (mode_t)0;
6304 files_struct *fsp = NULL;
6305 uint16 info_level_return = 0;
6306 int info;
6307 char *pdata = *ppdata;
6309 if (total_data < 18) {
6310 return NT_STATUS_INVALID_PARAMETER;
6313 raw_unixmode = IVAL(pdata,8);
6314 /* Next 4 bytes are not yet defined. */
6316 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6317 if (!NT_STATUS_IS_OK(status)) {
6318 return status;
6321 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6323 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6324 fname, (unsigned int)unixmode ));
6326 status = SMB_VFS_CREATE_FILE(
6327 conn, /* conn */
6328 req, /* req */
6329 0, /* root_dir_fid */
6330 fname, /* fname */
6331 0, /* create_file_flags */
6332 FILE_READ_ATTRIBUTES, /* access_mask */
6333 FILE_SHARE_NONE, /* share_access */
6334 FILE_CREATE, /* create_disposition*/
6335 FILE_DIRECTORY_FILE, /* create_options */
6336 mod_unixmode, /* file_attributes */
6337 0, /* oplock_request */
6338 0, /* allocation_size */
6339 NULL, /* sd */
6340 NULL, /* ea_list */
6341 &fsp, /* result */
6342 &info, /* pinfo */
6343 psbuf); /* psbuf */
6345 if (NT_STATUS_IS_OK(status)) {
6346 close_file(req, fsp, NORMAL_CLOSE);
6349 info_level_return = SVAL(pdata,16);
6351 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6352 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6353 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6354 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6355 } else {
6356 *pdata_return_size = 12;
6359 /* Realloc the data size */
6360 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6361 if (*ppdata == NULL) {
6362 *pdata_return_size = 0;
6363 return NT_STATUS_NO_MEMORY;
6365 pdata = *ppdata;
6367 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6368 SSVAL(pdata,2,0); /* No fnum. */
6369 SIVAL(pdata,4,info); /* Was directory created. */
6371 switch (info_level_return) {
6372 case SMB_QUERY_FILE_UNIX_BASIC:
6373 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6374 SSVAL(pdata,10,0); /* Padding. */
6375 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6376 break;
6377 case SMB_QUERY_FILE_UNIX_INFO2:
6378 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6379 SSVAL(pdata,10,0); /* Padding. */
6380 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6381 break;
6382 default:
6383 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6384 SSVAL(pdata,10,0); /* Padding. */
6385 break;
6388 return status;
6391 /****************************************************************************
6392 Open/Create a file with POSIX semantics.
6393 ****************************************************************************/
6395 static NTSTATUS smb_posix_open(connection_struct *conn,
6396 struct smb_request *req,
6397 char **ppdata,
6398 int total_data,
6399 const char *fname,
6400 SMB_STRUCT_STAT *psbuf,
6401 int *pdata_return_size)
6403 bool extended_oplock_granted = False;
6404 char *pdata = *ppdata;
6405 uint32 flags = 0;
6406 uint32 wire_open_mode = 0;
6407 uint32 raw_unixmode = 0;
6408 uint32 mod_unixmode = 0;
6409 uint32 create_disp = 0;
6410 uint32 access_mask = 0;
6411 uint32 create_options = 0;
6412 NTSTATUS status = NT_STATUS_OK;
6413 mode_t unixmode = (mode_t)0;
6414 files_struct *fsp = NULL;
6415 int oplock_request = 0;
6416 int info = 0;
6417 uint16 info_level_return = 0;
6419 if (total_data < 18) {
6420 return NT_STATUS_INVALID_PARAMETER;
6423 flags = IVAL(pdata,0);
6424 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6425 if (oplock_request) {
6426 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6429 wire_open_mode = IVAL(pdata,4);
6431 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6432 return smb_posix_mkdir(conn, req,
6433 ppdata,
6434 total_data,
6435 fname,
6436 psbuf,
6437 pdata_return_size);
6440 switch (wire_open_mode & SMB_ACCMODE) {
6441 case SMB_O_RDONLY:
6442 access_mask = FILE_READ_DATA;
6443 break;
6444 case SMB_O_WRONLY:
6445 access_mask = FILE_WRITE_DATA;
6446 break;
6447 case SMB_O_RDWR:
6448 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6449 break;
6450 default:
6451 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6452 (unsigned int)wire_open_mode ));
6453 return NT_STATUS_INVALID_PARAMETER;
6456 wire_open_mode &= ~SMB_ACCMODE;
6458 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6459 create_disp = FILE_CREATE;
6460 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6461 create_disp = FILE_OVERWRITE_IF;
6462 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6463 create_disp = FILE_OPEN_IF;
6464 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6465 create_disp = FILE_OPEN;
6466 } else {
6467 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6468 (unsigned int)wire_open_mode ));
6469 return NT_STATUS_INVALID_PARAMETER;
6472 raw_unixmode = IVAL(pdata,8);
6473 /* Next 4 bytes are not yet defined. */
6475 status = unix_perms_from_wire(conn,
6476 psbuf,
6477 raw_unixmode,
6478 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6479 &unixmode);
6481 if (!NT_STATUS_IS_OK(status)) {
6482 return status;
6485 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6487 if (wire_open_mode & SMB_O_SYNC) {
6488 create_options |= FILE_WRITE_THROUGH;
6490 if (wire_open_mode & SMB_O_APPEND) {
6491 access_mask |= FILE_APPEND_DATA;
6493 if (wire_open_mode & SMB_O_DIRECT) {
6494 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6497 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6498 fname,
6499 (unsigned int)wire_open_mode,
6500 (unsigned int)unixmode ));
6502 status = SMB_VFS_CREATE_FILE(
6503 conn, /* conn */
6504 req, /* req */
6505 0, /* root_dir_fid */
6506 fname, /* fname */
6507 0, /* create_file_flags */
6508 access_mask, /* access_mask */
6509 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6510 FILE_SHARE_DELETE),
6511 create_disp, /* create_disposition*/
6512 FILE_NON_DIRECTORY_FILE, /* create_options */
6513 mod_unixmode, /* file_attributes */
6514 oplock_request, /* oplock_request */
6515 0, /* allocation_size */
6516 NULL, /* sd */
6517 NULL, /* ea_list */
6518 &fsp, /* result */
6519 &info, /* pinfo */
6520 psbuf); /* psbuf */
6522 if (!NT_STATUS_IS_OK(status)) {
6523 return status;
6526 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6527 extended_oplock_granted = True;
6530 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6531 extended_oplock_granted = True;
6534 info_level_return = SVAL(pdata,16);
6536 /* Allocate the correct return size. */
6538 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6539 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6540 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6541 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6542 } else {
6543 *pdata_return_size = 12;
6546 /* Realloc the data size */
6547 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6548 if (*ppdata == NULL) {
6549 close_file(req, fsp, ERROR_CLOSE);
6550 *pdata_return_size = 0;
6551 return NT_STATUS_NO_MEMORY;
6553 pdata = *ppdata;
6555 if (extended_oplock_granted) {
6556 if (flags & REQUEST_BATCH_OPLOCK) {
6557 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6558 } else {
6559 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6561 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6562 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6563 } else {
6564 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6567 SSVAL(pdata,2,fsp->fnum);
6568 SIVAL(pdata,4,info); /* Was file created etc. */
6570 switch (info_level_return) {
6571 case SMB_QUERY_FILE_UNIX_BASIC:
6572 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6573 SSVAL(pdata,10,0); /* padding. */
6574 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6575 break;
6576 case SMB_QUERY_FILE_UNIX_INFO2:
6577 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6578 SSVAL(pdata,10,0); /* padding. */
6579 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6580 break;
6581 default:
6582 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6583 SSVAL(pdata,10,0); /* padding. */
6584 break;
6586 return NT_STATUS_OK;
6589 /****************************************************************************
6590 Delete a file with POSIX semantics.
6591 ****************************************************************************/
6593 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6594 struct smb_request *req,
6595 const char *pdata,
6596 int total_data,
6597 const char *fname,
6598 SMB_STRUCT_STAT *psbuf)
6600 NTSTATUS status = NT_STATUS_OK;
6601 files_struct *fsp = NULL;
6602 uint16 flags = 0;
6603 char del = 1;
6604 int info = 0;
6605 int create_options = 0;
6606 int i;
6607 struct share_mode_lock *lck = NULL;
6609 if (total_data < 2) {
6610 return NT_STATUS_INVALID_PARAMETER;
6613 flags = SVAL(pdata,0);
6615 if (!VALID_STAT(*psbuf)) {
6616 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6619 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6620 !VALID_STAT_OF_DIR(*psbuf)) {
6621 return NT_STATUS_NOT_A_DIRECTORY;
6624 DEBUG(10,("smb_posix_unlink: %s %s\n",
6625 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6626 fname));
6628 if (VALID_STAT_OF_DIR(*psbuf)) {
6629 create_options |= FILE_DIRECTORY_FILE;
6632 status = SMB_VFS_CREATE_FILE(
6633 conn, /* conn */
6634 req, /* req */
6635 0, /* root_dir_fid */
6636 fname, /* fname */
6637 0, /* create_file_flags */
6638 DELETE_ACCESS, /* access_mask */
6639 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6640 FILE_SHARE_DELETE),
6641 FILE_OPEN, /* create_disposition*/
6642 create_options, /* create_options */
6643 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6644 0, /* oplock_request */
6645 0, /* allocation_size */
6646 NULL, /* sd */
6647 NULL, /* ea_list */
6648 &fsp, /* result */
6649 &info, /* pinfo */
6650 psbuf); /* psbuf */
6652 if (!NT_STATUS_IS_OK(status)) {
6653 return status;
6657 * Don't lie to client. If we can't really delete due to
6658 * non-POSIX opens return SHARING_VIOLATION.
6661 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6662 NULL);
6663 if (lck == NULL) {
6664 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6665 "lock for file %s\n", fsp->fsp_name));
6666 close_file(req, fsp, NORMAL_CLOSE);
6667 return NT_STATUS_INVALID_PARAMETER;
6671 * See if others still have the file open. If this is the case, then
6672 * don't delete. If all opens are POSIX delete we can set the delete
6673 * on close disposition.
6675 for (i=0; i<lck->num_share_modes; i++) {
6676 struct share_mode_entry *e = &lck->share_modes[i];
6677 if (is_valid_share_mode_entry(e)) {
6678 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6679 continue;
6681 /* Fail with sharing violation. */
6682 close_file(req, fsp, NORMAL_CLOSE);
6683 TALLOC_FREE(lck);
6684 return NT_STATUS_SHARING_VIOLATION;
6689 * Set the delete on close.
6691 status = smb_set_file_disposition_info(conn,
6692 &del,
6694 fsp,
6695 fname,
6696 psbuf);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 close_file(req, fsp, NORMAL_CLOSE);
6700 TALLOC_FREE(lck);
6701 return status;
6703 TALLOC_FREE(lck);
6704 return close_file(req, fsp, NORMAL_CLOSE);
6707 /****************************************************************************
6708 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6709 ****************************************************************************/
6711 static void call_trans2setfilepathinfo(connection_struct *conn,
6712 struct smb_request *req,
6713 unsigned int tran_call,
6714 char **pparams, int total_params,
6715 char **ppdata, int total_data,
6716 unsigned int max_data_bytes)
6718 char *params = *pparams;
6719 char *pdata = *ppdata;
6720 uint16 info_level;
6721 SMB_STRUCT_STAT sbuf;
6722 char *fname = NULL;
6723 struct smb_filename *smb_fname = NULL;
6724 files_struct *fsp = NULL;
6725 NTSTATUS status = NT_STATUS_OK;
6726 int data_return_size = 0;
6727 TALLOC_CTX *ctx = talloc_tos();
6729 if (!params) {
6730 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6731 return;
6734 ZERO_STRUCT(sbuf);
6736 if (tran_call == TRANSACT2_SETFILEINFO) {
6737 if (total_params < 4) {
6738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6739 return;
6742 fsp = file_fsp(req, SVAL(params,0));
6743 /* Basic check for non-null fsp. */
6744 if (!check_fsp_open(conn, req, fsp)) {
6745 return;
6747 info_level = SVAL(params,2);
6749 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6750 if (!fname) {
6751 reply_nterror(req, NT_STATUS_NO_MEMORY);
6752 return;
6755 if(fsp->is_directory || fsp->fh->fd == -1) {
6757 * This is actually a SETFILEINFO on a directory
6758 * handle (returned from an NT SMB). NT5.0 seems
6759 * to do this call. JRA.
6761 if (INFO_LEVEL_IS_UNIX(info_level)) {
6762 /* Always do lstat for UNIX calls. */
6763 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6764 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6765 reply_unixerror(req,ERRDOS,ERRbadpath);
6766 return;
6768 } else {
6769 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6770 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6771 reply_unixerror(req,ERRDOS,ERRbadpath);
6772 return;
6775 } else if (fsp->print_file) {
6777 * Doing a DELETE_ON_CLOSE should cancel a print job.
6779 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6780 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6782 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6784 SSVAL(params,0,0);
6785 send_trans2_replies(conn, req, params, 2,
6786 *ppdata, 0,
6787 max_data_bytes);
6788 return;
6789 } else {
6790 reply_unixerror(req, ERRDOS, ERRbadpath);
6791 return;
6793 } else {
6795 * Original code - this is an open file.
6797 if (!check_fsp(conn, req, fsp)) {
6798 return;
6801 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6802 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6803 reply_unixerror(req, ERRDOS, ERRbadfid);
6804 return;
6807 } else {
6808 /* set path info */
6809 if (total_params < 7) {
6810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6811 return;
6814 info_level = SVAL(params,0);
6815 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6816 total_params - 6, STR_TERMINATE,
6817 &status);
6818 if (!NT_STATUS_IS_OK(status)) {
6819 reply_nterror(req, status);
6820 return;
6823 status = resolve_dfspath(ctx, conn,
6824 req->flags2 & FLAGS2_DFS_PATHNAMES,
6825 fname,
6826 &fname);
6827 if (!NT_STATUS_IS_OK(status)) {
6828 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6829 reply_botherror(req,
6830 NT_STATUS_PATH_NOT_COVERED,
6831 ERRSRV, ERRbadpath);
6832 return;
6834 reply_nterror(req, status);
6835 return;
6838 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
6839 if (!NT_STATUS_IS_OK(status)) {
6840 reply_nterror(req, status);
6841 return;
6843 sbuf = smb_fname->st;
6845 status = get_full_smb_filename(ctx, smb_fname, &fname);
6846 TALLOC_FREE(smb_fname);
6847 if (!NT_STATUS_IS_OK(status)) {
6848 reply_nterror(req, status);
6849 return;
6852 status = check_name(conn, fname);
6853 if (!NT_STATUS_IS_OK(status)) {
6854 reply_nterror(req, status);
6855 return;
6858 if (INFO_LEVEL_IS_UNIX(info_level)) {
6860 * For CIFS UNIX extensions the target name may not exist.
6863 /* Always do lstat for UNIX calls. */
6864 SMB_VFS_LSTAT(conn,fname,&sbuf);
6866 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6867 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6868 reply_unixerror(req, ERRDOS, ERRbadpath);
6869 return;
6873 if (!CAN_WRITE(conn)) {
6874 reply_doserror(req, ERRSRV, ERRaccess);
6875 return;
6878 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6879 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6880 return;
6883 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6884 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6886 /* Realloc the parameter size */
6887 *pparams = (char *)SMB_REALLOC(*pparams,2);
6888 if (*pparams == NULL) {
6889 reply_nterror(req, NT_STATUS_NO_MEMORY);
6890 return;
6892 params = *pparams;
6894 SSVAL(params,0,0);
6896 switch (info_level) {
6898 case SMB_INFO_STANDARD:
6900 status = smb_set_info_standard(conn,
6901 pdata,
6902 total_data,
6903 fsp,
6904 fname,
6905 &sbuf);
6906 break;
6909 case SMB_INFO_SET_EA:
6911 status = smb_info_set_ea(conn,
6912 pdata,
6913 total_data,
6914 fsp,
6915 fname);
6916 break;
6919 case SMB_SET_FILE_BASIC_INFO:
6920 case SMB_FILE_BASIC_INFORMATION:
6922 status = smb_set_file_basic_info(conn,
6923 pdata,
6924 total_data,
6925 fsp,
6926 fname,
6927 &sbuf);
6928 break;
6931 case SMB_FILE_ALLOCATION_INFORMATION:
6932 case SMB_SET_FILE_ALLOCATION_INFO:
6934 status = smb_set_file_allocation_info(conn, req,
6935 pdata,
6936 total_data,
6937 fsp,
6938 fname,
6939 &sbuf);
6940 break;
6943 case SMB_FILE_END_OF_FILE_INFORMATION:
6944 case SMB_SET_FILE_END_OF_FILE_INFO:
6946 status = smb_set_file_end_of_file_info(conn, req,
6947 pdata,
6948 total_data,
6949 fsp,
6950 fname,
6951 &sbuf);
6952 break;
6955 case SMB_FILE_DISPOSITION_INFORMATION:
6956 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6958 #if 0
6959 /* JRA - We used to just ignore this on a path ?
6960 * Shouldn't this be invalid level on a pathname
6961 * based call ?
6963 if (tran_call != TRANSACT2_SETFILEINFO) {
6964 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6966 #endif
6967 status = smb_set_file_disposition_info(conn,
6968 pdata,
6969 total_data,
6970 fsp,
6971 fname,
6972 &sbuf);
6973 break;
6976 case SMB_FILE_POSITION_INFORMATION:
6978 status = smb_file_position_information(conn,
6979 pdata,
6980 total_data,
6981 fsp);
6982 break;
6985 /* From tridge Samba4 :
6986 * MODE_INFORMATION in setfileinfo (I have no
6987 * idea what "mode information" on a file is - it takes a value of 0,
6988 * 2, 4 or 6. What could it be?).
6991 case SMB_FILE_MODE_INFORMATION:
6993 status = smb_file_mode_information(conn,
6994 pdata,
6995 total_data);
6996 break;
7000 * CIFS UNIX extensions.
7003 case SMB_SET_FILE_UNIX_BASIC:
7005 status = smb_set_file_unix_basic(conn, req,
7006 pdata,
7007 total_data,
7008 fsp,
7009 fname,
7010 &sbuf);
7011 break;
7014 case SMB_SET_FILE_UNIX_INFO2:
7016 status = smb_set_file_unix_info2(conn, req,
7017 pdata,
7018 total_data,
7019 fsp,
7020 fname,
7021 &sbuf);
7022 break;
7025 case SMB_SET_FILE_UNIX_LINK:
7027 if (tran_call != TRANSACT2_SETPATHINFO) {
7028 /* We must have a pathname for this. */
7029 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7030 return;
7032 status = smb_set_file_unix_link(conn, req, pdata,
7033 total_data, fname);
7034 break;
7037 case SMB_SET_FILE_UNIX_HLINK:
7039 if (tran_call != TRANSACT2_SETPATHINFO) {
7040 /* We must have a pathname for this. */
7041 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7042 return;
7044 status = smb_set_file_unix_hlink(conn, req,
7045 pdata, total_data,
7046 fname);
7047 break;
7050 case SMB_FILE_RENAME_INFORMATION:
7052 status = smb_file_rename_information(conn, req,
7053 pdata, total_data,
7054 fsp, fname);
7055 break;
7058 #if defined(HAVE_POSIX_ACLS)
7059 case SMB_SET_POSIX_ACL:
7061 status = smb_set_posix_acl(conn,
7062 pdata,
7063 total_data,
7064 fsp,
7065 fname,
7066 &sbuf);
7067 break;
7069 #endif
7071 case SMB_SET_POSIX_LOCK:
7073 if (tran_call != TRANSACT2_SETFILEINFO) {
7074 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7075 return;
7077 status = smb_set_posix_lock(conn, req,
7078 pdata, total_data, fsp);
7079 break;
7082 case SMB_POSIX_PATH_OPEN:
7084 if (tran_call != TRANSACT2_SETPATHINFO) {
7085 /* We must have a pathname for this. */
7086 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7087 return;
7090 status = smb_posix_open(conn, req,
7091 ppdata,
7092 total_data,
7093 fname,
7094 &sbuf,
7095 &data_return_size);
7096 break;
7099 case SMB_POSIX_PATH_UNLINK:
7101 if (tran_call != TRANSACT2_SETPATHINFO) {
7102 /* We must have a pathname for this. */
7103 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7104 return;
7107 status = smb_posix_unlink(conn, req,
7108 pdata,
7109 total_data,
7110 fname,
7111 &sbuf);
7112 break;
7115 default:
7116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7117 return;
7120 if (!NT_STATUS_IS_OK(status)) {
7121 if (open_was_deferred(req->mid)) {
7122 /* We have re-scheduled this call. */
7123 return;
7125 if (blocking_lock_was_deferred(req->mid)) {
7126 /* We have re-scheduled this call. */
7127 return;
7129 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7130 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7131 ERRSRV, ERRbadpath);
7132 return;
7134 if (info_level == SMB_POSIX_PATH_OPEN) {
7135 reply_openerror(req, status);
7136 return;
7139 reply_nterror(req, status);
7140 return;
7143 SSVAL(params,0,0);
7144 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7145 max_data_bytes);
7147 return;
7150 /****************************************************************************
7151 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7152 ****************************************************************************/
7154 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7155 char **pparams, int total_params,
7156 char **ppdata, int total_data,
7157 unsigned int max_data_bytes)
7159 struct smb_filename *smb_dname = NULL;
7160 char *params = *pparams;
7161 char *pdata = *ppdata;
7162 char *directory = NULL;
7163 NTSTATUS status = NT_STATUS_OK;
7164 struct ea_list *ea_list = NULL;
7165 TALLOC_CTX *ctx = talloc_tos();
7167 if (!CAN_WRITE(conn)) {
7168 reply_doserror(req, ERRSRV, ERRaccess);
7169 return;
7172 if (total_params < 5) {
7173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7174 return;
7177 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7178 total_params - 4, STR_TERMINATE,
7179 &status);
7180 if (!NT_STATUS_IS_OK(status)) {
7181 reply_nterror(req, status);
7182 return;
7185 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7187 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
7188 if (!NT_STATUS_IS_OK(status)) {
7189 reply_nterror(req, status);
7190 return;
7193 status = get_full_smb_filename(ctx, smb_dname, &directory);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 reply_nterror(req, status);
7196 return;
7199 status = check_name(conn, directory);
7200 if (!NT_STATUS_IS_OK(status)) {
7201 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7202 reply_nterror(req, status);
7203 return;
7206 /* Any data in this call is an EA list. */
7207 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7208 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7209 return;
7213 * OS/2 workplace shell seems to send SET_EA requests of "null"
7214 * length (4 bytes containing IVAL 4).
7215 * They seem to have no effect. Bug #3212. JRA.
7218 if (total_data != 4) {
7219 if (total_data < 10) {
7220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7221 return;
7224 if (IVAL(pdata,0) > total_data) {
7225 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7226 IVAL(pdata,0), (unsigned int)total_data));
7227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7228 return;
7231 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7232 total_data - 4);
7233 if (!ea_list) {
7234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7235 return;
7238 /* If total_data == 4 Windows doesn't care what values
7239 * are placed in that field, it just ignores them.
7240 * The System i QNTC IBM SMB client puts bad values here,
7241 * so ignore them. */
7243 status = create_directory(conn, req, directory);
7245 if (!NT_STATUS_IS_OK(status)) {
7246 reply_nterror(req, status);
7247 return;
7250 /* Try and set any given EA. */
7251 if (ea_list) {
7252 status = set_ea(conn, NULL, directory, ea_list);
7253 if (!NT_STATUS_IS_OK(status)) {
7254 reply_nterror(req, status);
7255 return;
7259 /* Realloc the parameter and data sizes */
7260 *pparams = (char *)SMB_REALLOC(*pparams,2);
7261 if(*pparams == NULL) {
7262 reply_nterror(req, NT_STATUS_NO_MEMORY);
7263 return;
7265 params = *pparams;
7267 SSVAL(params,0,0);
7269 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7271 return;
7274 /****************************************************************************
7275 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7276 We don't actually do this - we just send a null response.
7277 ****************************************************************************/
7279 static void call_trans2findnotifyfirst(connection_struct *conn,
7280 struct smb_request *req,
7281 char **pparams, int total_params,
7282 char **ppdata, int total_data,
7283 unsigned int max_data_bytes)
7285 char *params = *pparams;
7286 uint16 info_level;
7288 if (total_params < 6) {
7289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7290 return;
7293 info_level = SVAL(params,4);
7294 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7296 switch (info_level) {
7297 case 1:
7298 case 2:
7299 break;
7300 default:
7301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7302 return;
7305 /* Realloc the parameter and data sizes */
7306 *pparams = (char *)SMB_REALLOC(*pparams,6);
7307 if (*pparams == NULL) {
7308 reply_nterror(req, NT_STATUS_NO_MEMORY);
7309 return;
7311 params = *pparams;
7313 SSVAL(params,0,fnf_handle);
7314 SSVAL(params,2,0); /* No changes */
7315 SSVAL(params,4,0); /* No EA errors */
7317 fnf_handle++;
7319 if(fnf_handle == 0)
7320 fnf_handle = 257;
7322 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7324 return;
7327 /****************************************************************************
7328 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7329 changes). Currently this does nothing.
7330 ****************************************************************************/
7332 static void call_trans2findnotifynext(connection_struct *conn,
7333 struct smb_request *req,
7334 char **pparams, int total_params,
7335 char **ppdata, int total_data,
7336 unsigned int max_data_bytes)
7338 char *params = *pparams;
7340 DEBUG(3,("call_trans2findnotifynext\n"));
7342 /* Realloc the parameter and data sizes */
7343 *pparams = (char *)SMB_REALLOC(*pparams,4);
7344 if (*pparams == NULL) {
7345 reply_nterror(req, NT_STATUS_NO_MEMORY);
7346 return;
7348 params = *pparams;
7350 SSVAL(params,0,0); /* No changes */
7351 SSVAL(params,2,0); /* No EA errors */
7353 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7355 return;
7358 /****************************************************************************
7359 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7360 ****************************************************************************/
7362 static void call_trans2getdfsreferral(connection_struct *conn,
7363 struct smb_request *req,
7364 char **pparams, int total_params,
7365 char **ppdata, int total_data,
7366 unsigned int max_data_bytes)
7368 char *params = *pparams;
7369 char *pathname = NULL;
7370 int reply_size = 0;
7371 int max_referral_level;
7372 NTSTATUS status = NT_STATUS_OK;
7373 TALLOC_CTX *ctx = talloc_tos();
7375 DEBUG(10,("call_trans2getdfsreferral\n"));
7377 if (total_params < 3) {
7378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7379 return;
7382 max_referral_level = SVAL(params,0);
7384 if(!lp_host_msdfs()) {
7385 reply_doserror(req, ERRDOS, ERRbadfunc);
7386 return;
7389 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7390 total_params - 2, STR_TERMINATE);
7391 if (!pathname) {
7392 reply_nterror(req, NT_STATUS_NOT_FOUND);
7393 return;
7395 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7396 ppdata,&status)) < 0) {
7397 reply_nterror(req, status);
7398 return;
7401 SSVAL(req->inbuf, smb_flg2,
7402 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7403 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7405 return;
7408 #define LMCAT_SPL 0x53
7409 #define LMFUNC_GETJOBID 0x60
7411 /****************************************************************************
7412 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7413 ****************************************************************************/
7415 static void call_trans2ioctl(connection_struct *conn,
7416 struct smb_request *req,
7417 char **pparams, int total_params,
7418 char **ppdata, int total_data,
7419 unsigned int max_data_bytes)
7421 char *pdata = *ppdata;
7422 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7424 /* check for an invalid fid before proceeding */
7426 if (!fsp) {
7427 reply_doserror(req, ERRDOS, ERRbadfid);
7428 return;
7431 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7432 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7433 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7434 if (*ppdata == NULL) {
7435 reply_nterror(req, NT_STATUS_NO_MEMORY);
7436 return;
7438 pdata = *ppdata;
7440 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7441 CAN ACCEPT THIS IN UNICODE. JRA. */
7443 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7444 srvstr_push(pdata, req->flags2, pdata + 2,
7445 global_myname(), 15,
7446 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7447 srvstr_push(pdata, req->flags2, pdata+18,
7448 lp_servicename(SNUM(conn)), 13,
7449 STR_ASCII|STR_TERMINATE); /* Service name */
7450 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7451 max_data_bytes);
7452 return;
7455 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7456 reply_doserror(req, ERRSRV, ERRerror);
7459 /****************************************************************************
7460 Reply to a SMBfindclose (stop trans2 directory search).
7461 ****************************************************************************/
7463 void reply_findclose(struct smb_request *req)
7465 int dptr_num;
7467 START_PROFILE(SMBfindclose);
7469 if (req->wct < 1) {
7470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7471 END_PROFILE(SMBfindclose);
7472 return;
7475 dptr_num = SVALS(req->vwv+0, 0);
7477 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7479 dptr_close(&dptr_num);
7481 reply_outbuf(req, 0, 0);
7483 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7485 END_PROFILE(SMBfindclose);
7486 return;
7489 /****************************************************************************
7490 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7491 ****************************************************************************/
7493 void reply_findnclose(struct smb_request *req)
7495 int dptr_num;
7497 START_PROFILE(SMBfindnclose);
7499 if (req->wct < 1) {
7500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7501 END_PROFILE(SMBfindnclose);
7502 return;
7505 dptr_num = SVAL(req->vwv+0, 0);
7507 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7509 /* We never give out valid handles for a
7510 findnotifyfirst - so any dptr_num is ok here.
7511 Just ignore it. */
7513 reply_outbuf(req, 0, 0);
7515 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7517 END_PROFILE(SMBfindnclose);
7518 return;
7521 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7522 struct trans_state *state)
7524 if (Protocol >= PROTOCOL_NT1) {
7525 req->flags2 |= 0x40; /* IS_LONG_NAME */
7526 SSVAL(req->inbuf,smb_flg2,req->flags2);
7529 if (conn->encrypt_level == Required && !req->encrypted) {
7530 if (state->call != TRANSACT2_QFSINFO &&
7531 state->call != TRANSACT2_SETFSINFO) {
7532 DEBUG(0,("handle_trans2: encryption required "
7533 "with call 0x%x\n",
7534 (unsigned int)state->call));
7535 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7536 return;
7540 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7542 /* Now we must call the relevant TRANS2 function */
7543 switch(state->call) {
7544 case TRANSACT2_OPEN:
7546 START_PROFILE(Trans2_open);
7547 call_trans2open(conn, req,
7548 &state->param, state->total_param,
7549 &state->data, state->total_data,
7550 state->max_data_return);
7551 END_PROFILE(Trans2_open);
7552 break;
7555 case TRANSACT2_FINDFIRST:
7557 START_PROFILE(Trans2_findfirst);
7558 call_trans2findfirst(conn, req,
7559 &state->param, state->total_param,
7560 &state->data, state->total_data,
7561 state->max_data_return);
7562 END_PROFILE(Trans2_findfirst);
7563 break;
7566 case TRANSACT2_FINDNEXT:
7568 START_PROFILE(Trans2_findnext);
7569 call_trans2findnext(conn, req,
7570 &state->param, state->total_param,
7571 &state->data, state->total_data,
7572 state->max_data_return);
7573 END_PROFILE(Trans2_findnext);
7574 break;
7577 case TRANSACT2_QFSINFO:
7579 START_PROFILE(Trans2_qfsinfo);
7580 call_trans2qfsinfo(conn, req,
7581 &state->param, state->total_param,
7582 &state->data, state->total_data,
7583 state->max_data_return);
7584 END_PROFILE(Trans2_qfsinfo);
7585 break;
7588 case TRANSACT2_SETFSINFO:
7590 START_PROFILE(Trans2_setfsinfo);
7591 call_trans2setfsinfo(conn, req,
7592 &state->param, state->total_param,
7593 &state->data, state->total_data,
7594 state->max_data_return);
7595 END_PROFILE(Trans2_setfsinfo);
7596 break;
7599 case TRANSACT2_QPATHINFO:
7600 case TRANSACT2_QFILEINFO:
7602 START_PROFILE(Trans2_qpathinfo);
7603 call_trans2qfilepathinfo(conn, req, state->call,
7604 &state->param, state->total_param,
7605 &state->data, state->total_data,
7606 state->max_data_return);
7607 END_PROFILE(Trans2_qpathinfo);
7608 break;
7611 case TRANSACT2_SETPATHINFO:
7612 case TRANSACT2_SETFILEINFO:
7614 START_PROFILE(Trans2_setpathinfo);
7615 call_trans2setfilepathinfo(conn, req, state->call,
7616 &state->param, state->total_param,
7617 &state->data, state->total_data,
7618 state->max_data_return);
7619 END_PROFILE(Trans2_setpathinfo);
7620 break;
7623 case TRANSACT2_FINDNOTIFYFIRST:
7625 START_PROFILE(Trans2_findnotifyfirst);
7626 call_trans2findnotifyfirst(conn, req,
7627 &state->param, state->total_param,
7628 &state->data, state->total_data,
7629 state->max_data_return);
7630 END_PROFILE(Trans2_findnotifyfirst);
7631 break;
7634 case TRANSACT2_FINDNOTIFYNEXT:
7636 START_PROFILE(Trans2_findnotifynext);
7637 call_trans2findnotifynext(conn, req,
7638 &state->param, state->total_param,
7639 &state->data, state->total_data,
7640 state->max_data_return);
7641 END_PROFILE(Trans2_findnotifynext);
7642 break;
7645 case TRANSACT2_MKDIR:
7647 START_PROFILE(Trans2_mkdir);
7648 call_trans2mkdir(conn, req,
7649 &state->param, state->total_param,
7650 &state->data, state->total_data,
7651 state->max_data_return);
7652 END_PROFILE(Trans2_mkdir);
7653 break;
7656 case TRANSACT2_GET_DFS_REFERRAL:
7658 START_PROFILE(Trans2_get_dfs_referral);
7659 call_trans2getdfsreferral(conn, req,
7660 &state->param, state->total_param,
7661 &state->data, state->total_data,
7662 state->max_data_return);
7663 END_PROFILE(Trans2_get_dfs_referral);
7664 break;
7667 case TRANSACT2_IOCTL:
7669 START_PROFILE(Trans2_ioctl);
7670 call_trans2ioctl(conn, req,
7671 &state->param, state->total_param,
7672 &state->data, state->total_data,
7673 state->max_data_return);
7674 END_PROFILE(Trans2_ioctl);
7675 break;
7678 default:
7679 /* Error in request */
7680 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7681 reply_doserror(req, ERRSRV,ERRerror);
7685 /****************************************************************************
7686 Reply to a SMBtrans2.
7687 ****************************************************************************/
7689 void reply_trans2(struct smb_request *req)
7691 connection_struct *conn = req->conn;
7692 unsigned int dsoff;
7693 unsigned int dscnt;
7694 unsigned int psoff;
7695 unsigned int pscnt;
7696 unsigned int tran_call;
7697 struct trans_state *state;
7698 NTSTATUS result;
7700 START_PROFILE(SMBtrans2);
7702 if (req->wct < 14) {
7703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7704 END_PROFILE(SMBtrans2);
7705 return;
7708 dsoff = SVAL(req->vwv+12, 0);
7709 dscnt = SVAL(req->vwv+11, 0);
7710 psoff = SVAL(req->vwv+10, 0);
7711 pscnt = SVAL(req->vwv+9, 0);
7712 tran_call = SVAL(req->vwv+14, 0);
7714 result = allow_new_trans(conn->pending_trans, req->mid);
7715 if (!NT_STATUS_IS_OK(result)) {
7716 DEBUG(2, ("Got invalid trans2 request: %s\n",
7717 nt_errstr(result)));
7718 reply_nterror(req, result);
7719 END_PROFILE(SMBtrans2);
7720 return;
7723 if (IS_IPC(conn)) {
7724 switch (tran_call) {
7725 /* List the allowed trans2 calls on IPC$ */
7726 case TRANSACT2_OPEN:
7727 case TRANSACT2_GET_DFS_REFERRAL:
7728 case TRANSACT2_QFILEINFO:
7729 case TRANSACT2_QFSINFO:
7730 case TRANSACT2_SETFSINFO:
7731 break;
7732 default:
7733 reply_doserror(req, ERRSRV, ERRaccess);
7734 END_PROFILE(SMBtrans2);
7735 return;
7739 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7740 DEBUG(0, ("talloc failed\n"));
7741 reply_nterror(req, NT_STATUS_NO_MEMORY);
7742 END_PROFILE(SMBtrans2);
7743 return;
7746 state->cmd = SMBtrans2;
7748 state->mid = req->mid;
7749 state->vuid = req->vuid;
7750 state->setup_count = SVAL(req->vwv+13, 0);
7751 state->setup = NULL;
7752 state->total_param = SVAL(req->vwv+0, 0);
7753 state->param = NULL;
7754 state->total_data = SVAL(req->vwv+1, 0);
7755 state->data = NULL;
7756 state->max_param_return = SVAL(req->vwv+2, 0);
7757 state->max_data_return = SVAL(req->vwv+3, 0);
7758 state->max_setup_return = SVAL(req->vwv+4, 0);
7759 state->close_on_completion = BITSETW(req->vwv+5, 0);
7760 state->one_way = BITSETW(req->vwv+5, 1);
7762 state->call = tran_call;
7764 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7765 is so as a sanity check */
7766 if (state->setup_count != 1) {
7768 * Need to have rc=0 for ioctl to get job id for OS/2.
7769 * Network printing will fail if function is not successful.
7770 * Similar function in reply.c will be used if protocol
7771 * is LANMAN1.0 instead of LM1.2X002.
7772 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7773 * outbuf doesn't have to be set(only job id is used).
7775 if ( (state->setup_count == 4)
7776 && (tran_call == TRANSACT2_IOCTL)
7777 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7778 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7779 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7780 } else {
7781 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7782 DEBUG(2,("Transaction is %d\n",tran_call));
7783 TALLOC_FREE(state);
7784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7785 END_PROFILE(SMBtrans2);
7786 return;
7790 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7791 goto bad_param;
7793 if (state->total_data) {
7795 if (trans_oob(state->total_data, 0, dscnt)
7796 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7797 goto bad_param;
7800 /* Can't use talloc here, the core routines do realloc on the
7801 * params and data. */
7802 state->data = (char *)SMB_MALLOC(state->total_data);
7803 if (state->data == NULL) {
7804 DEBUG(0,("reply_trans2: data malloc fail for %u "
7805 "bytes !\n", (unsigned int)state->total_data));
7806 TALLOC_FREE(state);
7807 reply_nterror(req, NT_STATUS_NO_MEMORY);
7808 END_PROFILE(SMBtrans2);
7809 return;
7812 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7815 if (state->total_param) {
7817 if (trans_oob(state->total_param, 0, pscnt)
7818 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7819 goto bad_param;
7822 /* Can't use talloc here, the core routines do realloc on the
7823 * params and data. */
7824 state->param = (char *)SMB_MALLOC(state->total_param);
7825 if (state->param == NULL) {
7826 DEBUG(0,("reply_trans: param malloc fail for %u "
7827 "bytes !\n", (unsigned int)state->total_param));
7828 SAFE_FREE(state->data);
7829 TALLOC_FREE(state);
7830 reply_nterror(req, NT_STATUS_NO_MEMORY);
7831 END_PROFILE(SMBtrans2);
7832 return;
7835 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7838 state->received_data = dscnt;
7839 state->received_param = pscnt;
7841 if ((state->received_param == state->total_param) &&
7842 (state->received_data == state->total_data)) {
7844 handle_trans2(conn, req, state);
7846 SAFE_FREE(state->data);
7847 SAFE_FREE(state->param);
7848 TALLOC_FREE(state);
7849 END_PROFILE(SMBtrans2);
7850 return;
7853 DLIST_ADD(conn->pending_trans, state);
7855 /* We need to send an interim response then receive the rest
7856 of the parameter/data bytes */
7857 reply_outbuf(req, 0, 0);
7858 show_msg((char *)req->outbuf);
7859 END_PROFILE(SMBtrans2);
7860 return;
7862 bad_param:
7864 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7865 SAFE_FREE(state->data);
7866 SAFE_FREE(state->param);
7867 TALLOC_FREE(state);
7868 END_PROFILE(SMBtrans2);
7869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7873 /****************************************************************************
7874 Reply to a SMBtranss2
7875 ****************************************************************************/
7877 void reply_transs2(struct smb_request *req)
7879 connection_struct *conn = req->conn;
7880 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7881 struct trans_state *state;
7883 START_PROFILE(SMBtranss2);
7885 show_msg((char *)req->inbuf);
7887 if (req->wct < 8) {
7888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7889 END_PROFILE(SMBtranss2);
7890 return;
7893 for (state = conn->pending_trans; state != NULL;
7894 state = state->next) {
7895 if (state->mid == req->mid) {
7896 break;
7900 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7902 END_PROFILE(SMBtranss2);
7903 return;
7906 /* Revise state->total_param and state->total_data in case they have
7907 changed downwards */
7909 if (SVAL(req->vwv+0, 0) < state->total_param)
7910 state->total_param = SVAL(req->vwv+0, 0);
7911 if (SVAL(req->vwv+1, 0) < state->total_data)
7912 state->total_data = SVAL(req->vwv+1, 0);
7914 pcnt = SVAL(req->vwv+2, 0);
7915 poff = SVAL(req->vwv+3, 0);
7916 pdisp = SVAL(req->vwv+4, 0);
7918 dcnt = SVAL(req->vwv+5, 0);
7919 doff = SVAL(req->vwv+6, 0);
7920 ddisp = SVAL(req->vwv+7, 0);
7922 state->received_param += pcnt;
7923 state->received_data += dcnt;
7925 if ((state->received_data > state->total_data) ||
7926 (state->received_param > state->total_param))
7927 goto bad_param;
7929 if (pcnt) {
7930 if (trans_oob(state->total_param, pdisp, pcnt)
7931 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7932 goto bad_param;
7934 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7937 if (dcnt) {
7938 if (trans_oob(state->total_data, ddisp, dcnt)
7939 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7940 goto bad_param;
7942 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7945 if ((state->received_param < state->total_param) ||
7946 (state->received_data < state->total_data)) {
7947 END_PROFILE(SMBtranss2);
7948 return;
7951 handle_trans2(conn, req, state);
7953 DLIST_REMOVE(conn->pending_trans, state);
7954 SAFE_FREE(state->data);
7955 SAFE_FREE(state->param);
7956 TALLOC_FREE(state);
7958 END_PROFILE(SMBtranss2);
7959 return;
7961 bad_param:
7963 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7964 DLIST_REMOVE(conn->pending_trans, state);
7965 SAFE_FREE(state->data);
7966 SAFE_FREE(state->param);
7967 TALLOC_FREE(state);
7968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7969 END_PROFILE(SMBtranss2);
7970 return;