s3-swat: Fix typo.
[Samba.git] / source3 / smbd / trans2.c
blobe6d2b0ab8d2170515dfd0391aeb73cc4f846eed8
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
35 char *pdata,
36 files_struct *fsp,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
40 char *pdata,
41 files_struct *fsp,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
58 return val;
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name)
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
74 NULL
77 int i;
79 for (i = 0; prohibited_ea_names[i]; i++) {
80 if (strequal( prohibited_ea_names[i], unix_ea_name))
81 return true;
83 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
85 return true;
87 return false;
90 /****************************************************************************
91 Get one EA value. Fill in a struct ea_struct.
92 ****************************************************************************/
94 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
95 files_struct *fsp, const char *fname,
96 const char *ea_name, struct ea_struct *pea)
98 /* Get the value of this xattr. Max size is 64k. */
99 size_t attr_size = 256;
100 char *val = NULL;
101 ssize_t sizeret;
103 again:
105 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
106 if (!val) {
107 return NT_STATUS_NO_MEMORY;
110 if (fsp && fsp->fh->fd != -1) {
111 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
112 } else {
113 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
116 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
117 attr_size = 65536;
118 goto again;
121 if (sizeret == -1) {
122 return map_nt_error_from_unix(errno);
125 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
126 dump_data(10, (uint8 *)val, sizeret);
128 pea->flags = 0;
129 if (strnequal(ea_name, "user.", 5)) {
130 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
131 } else {
132 pea->name = talloc_strdup(mem_ctx, ea_name);
134 if (pea->name == NULL) {
135 TALLOC_FREE(val);
136 return NT_STATUS_NO_MEMORY;
138 pea->value.data = (unsigned char *)val;
139 pea->value.length = (size_t)sizeret;
140 return NT_STATUS_OK;
143 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
144 files_struct *fsp, const char *fname,
145 char ***pnames, size_t *pnum_names)
147 /* Get a list of all xattrs. Max namesize is 64k. */
148 size_t ea_namelist_size = 1024;
149 char *ea_namelist = NULL;
151 char *p;
152 char **names, **tmp;
153 size_t num_names;
154 ssize_t sizeret = -1;
156 if (!lp_ea_support(SNUM(conn))) {
157 *pnames = NULL;
158 *pnum_names = 0;
159 return NT_STATUS_OK;
163 * TALLOC the result early to get the talloc hierarchy right.
166 names = TALLOC_ARRAY(mem_ctx, char *, 1);
167 if (names == NULL) {
168 DEBUG(0, ("talloc failed\n"));
169 return NT_STATUS_NO_MEMORY;
172 while (ea_namelist_size <= 65536) {
174 ea_namelist = TALLOC_REALLOC_ARRAY(
175 names, ea_namelist, char, ea_namelist_size);
176 if (ea_namelist == NULL) {
177 DEBUG(0, ("talloc failed\n"));
178 TALLOC_FREE(names);
179 return NT_STATUS_NO_MEMORY;
182 if (fsp && fsp->fh->fd != -1) {
183 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
184 ea_namelist_size);
185 } else {
186 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
187 ea_namelist_size);
190 if ((sizeret == -1) && (errno == ERANGE)) {
191 ea_namelist_size *= 2;
193 else {
194 break;
198 if (sizeret == -1) {
199 TALLOC_FREE(names);
200 return map_nt_error_from_unix(errno);
203 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
204 (unsigned int)sizeret));
206 if (sizeret == 0) {
207 TALLOC_FREE(names);
208 *pnames = NULL;
209 *pnum_names = 0;
210 return NT_STATUS_OK;
214 * Ensure the result is 0-terminated
217 if (ea_namelist[sizeret-1] != '\0') {
218 TALLOC_FREE(names);
219 return NT_STATUS_INTERNAL_ERROR;
223 * count the names
225 num_names = 0;
227 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
228 num_names += 1;
231 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
232 if (tmp == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 names = tmp;
239 num_names = 0;
241 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
242 names[num_names++] = p;
245 *pnames = names;
246 *pnum_names = num_names;
247 return NT_STATUS_OK;
250 /****************************************************************************
251 Return a linked list of the total EA's. Plus the total size
252 ****************************************************************************/
254 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
255 const char *fname, size_t *pea_total_len)
257 /* Get a list of all xattrs. Max namesize is 64k. */
258 size_t i, num_names;
259 char **names;
260 struct ea_list *ea_list_head = NULL;
261 NTSTATUS status;
263 *pea_total_len = 0;
265 if (!lp_ea_support(SNUM(conn))) {
266 return NULL;
269 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
270 &names, &num_names);
272 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
273 return NULL;
276 for (i=0; i<num_names; i++) {
277 struct ea_list *listp;
278 fstring dos_ea_name;
280 if (strnequal(names[i], "system.", 7)
281 || samba_private_attr_name(names[i]))
282 continue;
284 listp = TALLOC_P(mem_ctx, struct ea_list);
285 if (listp == NULL) {
286 return NULL;
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
290 fname, names[i],
291 &listp->ea))) {
292 return NULL;
295 push_ascii_fstring(dos_ea_name, listp->ea.name);
297 *pea_total_len +=
298 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
300 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
301 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
302 (unsigned int)listp->ea.value.length));
304 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
308 /* Add on 4 for total length. */
309 if (*pea_total_len) {
310 *pea_total_len += 4;
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len));
316 return ea_list_head;
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
321 that was filled.
322 ****************************************************************************/
324 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
325 connection_struct *conn, struct ea_list *ea_list)
327 unsigned int ret_data_size = 4;
328 char *p = pdata;
330 SMB_ASSERT(total_data_size >= 4);
332 if (!lp_ea_support(SNUM(conn))) {
333 SIVAL(pdata,4,0);
334 return 4;
337 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
338 size_t dos_namelen;
339 fstring dos_ea_name;
340 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
341 dos_namelen = strlen(dos_ea_name);
342 if (dos_namelen > 255 || dos_namelen == 0) {
343 break;
345 if (ea_list->ea.value.length > 65535) {
346 break;
348 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
349 break;
352 /* We know we have room. */
353 SCVAL(p,0,ea_list->ea.flags);
354 SCVAL(p,1,dos_namelen);
355 SSVAL(p,2,ea_list->ea.value.length);
356 fstrcpy(p+4, dos_ea_name);
357 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
359 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
360 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
363 ret_data_size = PTR_DIFF(p, pdata);
364 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
365 SIVAL(pdata,0,ret_data_size);
366 return ret_data_size;
369 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
371 size_t total_ea_len = 0;
372 TALLOC_CTX *mem_ctx = NULL;
374 if (!lp_ea_support(SNUM(conn))) {
375 return 0;
377 mem_ctx = talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
379 return total_ea_len;
382 /****************************************************************************
383 Ensure the EA name is case insensitive by matching any existing EA name.
384 ****************************************************************************/
386 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
388 size_t total_ea_len;
389 TALLOC_CTX *mem_ctx = talloc_tos();
390 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
392 for (; ea_list; ea_list = ea_list->next) {
393 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
394 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
395 &unix_ea_name[5], ea_list->ea.name));
396 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
397 break;
402 /****************************************************************************
403 Set or delete an extended attribute.
404 ****************************************************************************/
406 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
408 if (!lp_ea_support(SNUM(conn))) {
409 return NT_STATUS_EAS_NOT_SUPPORTED;
412 for (;ea_list; ea_list = ea_list->next) {
413 int ret;
414 fstring unix_ea_name;
416 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
417 fstrcat(unix_ea_name, ea_list->ea.name);
419 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
421 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
423 if (samba_private_attr_name(unix_ea_name)) {
424 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
425 return NT_STATUS_ACCESS_DENIED;
428 if (ea_list->ea.value.length == 0) {
429 /* Remove the attribute. */
430 if (fsp && (fsp->fh->fd != -1)) {
431 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
432 unix_ea_name, fsp->fsp_name));
433 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
434 } else {
435 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
436 unix_ea_name, fname));
437 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
439 #ifdef ENOATTR
440 /* Removing a non existent attribute always succeeds. */
441 if (ret == -1 && errno == ENOATTR) {
442 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
443 unix_ea_name));
444 ret = 0;
446 #endif
447 } else {
448 if (fsp && (fsp->fh->fd != -1)) {
449 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
450 unix_ea_name, fsp->fsp_name));
451 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
452 ea_list->ea.value.data, ea_list->ea.value.length, 0);
453 } else {
454 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
455 unix_ea_name, fname));
456 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
457 ea_list->ea.value.data, ea_list->ea.value.length, 0);
461 if (ret == -1) {
462 #ifdef ENOTSUP
463 if (errno == ENOTSUP) {
464 return NT_STATUS_EAS_NOT_SUPPORTED;
466 #endif
467 return map_nt_error_from_unix(errno);
471 return NT_STATUS_OK;
473 /****************************************************************************
474 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
475 ****************************************************************************/
477 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
479 struct ea_list *ea_list_head = NULL;
480 size_t converted_size, offset = 0;
482 while (offset + 2 < data_size) {
483 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
484 unsigned int namelen = CVAL(pdata,offset);
486 offset++; /* Go past the namelen byte. */
488 /* integer wrap paranioa. */
489 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
490 (offset > data_size) || (namelen > data_size) ||
491 (offset + namelen >= data_size)) {
492 break;
494 /* Ensure the name is null terminated. */
495 if (pdata[offset + namelen] != '\0') {
496 return NULL;
498 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
499 &converted_size)) {
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno)));
503 if (!eal->ea.name) {
504 return NULL;
507 offset += (namelen + 1); /* Go past the name + terminating zero. */
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
512 return ea_list_head;
515 /****************************************************************************
516 Read one EA list entry from the buffer.
517 ****************************************************************************/
519 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
521 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
522 uint16 val_len;
523 unsigned int namelen;
524 size_t converted_size;
526 if (!eal) {
527 return NULL;
530 if (data_size < 6) {
531 return NULL;
534 eal->ea.flags = CVAL(pdata,0);
535 namelen = CVAL(pdata,1);
536 val_len = SVAL(pdata,2);
538 if (4 + namelen + 1 + val_len > data_size) {
539 return NULL;
542 /* Ensure the name is null terminated. */
543 if (pdata[namelen + 4] != '\0') {
544 return NULL;
546 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
547 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
548 strerror(errno)));
550 if (!eal->ea.name) {
551 return NULL;
554 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
555 if (!eal->ea.value.data) {
556 return NULL;
559 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
561 /* Ensure we're null terminated just in case we print the value. */
562 eal->ea.value.data[val_len] = '\0';
563 /* But don't count the null. */
564 eal->ea.value.length--;
566 if (pbytes_used) {
567 *pbytes_used = 4 + namelen + 1 + val_len;
570 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
571 dump_data(10, eal->ea.value.data, eal->ea.value.length);
573 return eal;
576 /****************************************************************************
577 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
578 ****************************************************************************/
580 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
582 struct ea_list *ea_list_head = NULL;
583 size_t offset = 0;
584 size_t bytes_used = 0;
586 while (offset < data_size) {
587 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
589 if (!eal) {
590 return NULL;
593 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
594 offset += bytes_used;
597 return ea_list_head;
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
604 static size_t ea_list_size(struct ea_list *ealist)
606 fstring dos_ea_name;
607 struct ea_list *listp;
608 size_t ret = 0;
610 for (listp = ealist; listp; listp = listp->next) {
611 push_ascii_fstring(dos_ea_name, listp->ea.name);
612 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
614 /* Add on 4 for total length. */
615 if (ret) {
616 ret += 4;
619 return ret;
622 /****************************************************************************
623 Return a union of EA's from a file list and a list of names.
624 The TALLOC context for the two lists *MUST* be identical as we steal
625 memory from one list to add to another. JRA.
626 ****************************************************************************/
628 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
630 struct ea_list *nlistp, *flistp;
632 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
633 for (flistp = file_list; flistp; flistp = flistp->next) {
634 if (strequal(nlistp->ea.name, flistp->ea.name)) {
635 break;
639 if (flistp) {
640 /* Copy the data from this entry. */
641 nlistp->ea.flags = flistp->ea.flags;
642 nlistp->ea.value = flistp->ea.value;
643 } else {
644 /* Null entry. */
645 nlistp->ea.flags = 0;
646 ZERO_STRUCT(nlistp->ea.value);
650 *total_ea_len = ea_list_size(name_list);
651 return name_list;
654 /****************************************************************************
655 Send the required number of replies back.
656 We assume all fields other than the data fields are
657 set correctly for the type of call.
658 HACK ! Always assumes smb_setup field is zero.
659 ****************************************************************************/
661 void send_trans2_replies(connection_struct *conn,
662 struct smb_request *req,
663 const char *params,
664 int paramsize,
665 const char *pdata,
666 int datasize,
667 int max_data_bytes)
669 /* As we are using a protocol > LANMAN1 then the max_send
670 variable must have been set in the sessetupX call.
671 This takes precedence over the max_xmit field in the
672 global struct. These different max_xmit variables should
673 be merged as this is now too confusing */
675 int data_to_send = datasize;
676 int params_to_send = paramsize;
677 int useable_space;
678 const char *pp = params;
679 const char *pd = pdata;
680 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
681 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
682 int data_alignment_offset = 0;
683 bool overflow = False;
685 /* Modify the data_to_send and datasize and set the error if
686 we're trying to send more than max_data_bytes. We still send
687 the part of the packet(s) that fit. Strange, but needed
688 for OS/2. */
690 if (max_data_bytes > 0 && datasize > max_data_bytes) {
691 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
692 max_data_bytes, datasize ));
693 datasize = data_to_send = max_data_bytes;
694 overflow = True;
697 /* If there genuinely are no parameters or data to send just send the empty packet */
699 if(params_to_send == 0 && data_to_send == 0) {
700 reply_outbuf(req, 10, 0);
701 show_msg((char *)req->outbuf);
702 return;
705 /* When sending params and data ensure that both are nicely aligned */
706 /* Only do this alignment when there is also data to send - else
707 can cause NT redirector problems. */
709 if (((params_to_send % 4) != 0) && (data_to_send != 0))
710 data_alignment_offset = 4 - (params_to_send % 4);
712 /* Space is bufsize minus Netbios over TCP header minus SMB header */
713 /* The alignment_offset is to align the param bytes on an even byte
714 boundary. NT 4.0 Beta needs this to work correctly. */
716 useable_space = max_send - (smb_size
717 + 2 * 10 /* wct */
718 + alignment_offset
719 + data_alignment_offset);
721 if (useable_space < 0) {
722 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
723 "= %d!!!", useable_space));
724 exit_server_cleanly("send_trans2_replies: Not enough space");
727 while (params_to_send || data_to_send) {
728 /* Calculate whether we will totally or partially fill this packet */
730 total_sent_thistime = params_to_send + data_to_send;
732 /* We can never send more than useable_space */
734 * Note that 'useable_space' does not include the alignment offsets,
735 * but we must include the alignment offsets in the calculation of
736 * the length of the data we send over the wire, as the alignment offsets
737 * are sent here. Fix from Marc_Jacobsen@hp.com.
740 total_sent_thistime = MIN(total_sent_thistime, useable_space);
742 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
743 + data_alignment_offset);
746 * We might have SMBtrans2s in req which was transferred to
747 * the outbuf, fix that.
749 SCVAL(req->outbuf, smb_com, SMBtrans2);
751 /* Set total params and data to be sent */
752 SSVAL(req->outbuf,smb_tprcnt,paramsize);
753 SSVAL(req->outbuf,smb_tdrcnt,datasize);
755 /* Calculate how many parameters and data we can fit into
756 * this packet. Parameters get precedence
759 params_sent_thistime = MIN(params_to_send,useable_space);
760 data_sent_thistime = useable_space - params_sent_thistime;
761 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
763 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
765 /* smb_proff is the offset from the start of the SMB header to the
766 parameter bytes, however the first 4 bytes of outbuf are
767 the Netbios over TCP header. Thus use smb_base() to subtract
768 them from the calculation */
770 SSVAL(req->outbuf,smb_proff,
771 ((smb_buf(req->outbuf)+alignment_offset)
772 - smb_base(req->outbuf)));
774 if(params_sent_thistime == 0)
775 SSVAL(req->outbuf,smb_prdisp,0);
776 else
777 /* Absolute displacement of param bytes sent in this packet */
778 SSVAL(req->outbuf,smb_prdisp,pp - params);
780 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
781 if(data_sent_thistime == 0) {
782 SSVAL(req->outbuf,smb_droff,0);
783 SSVAL(req->outbuf,smb_drdisp, 0);
784 } else {
785 /* The offset of the data bytes is the offset of the
786 parameter bytes plus the number of parameters being sent this time */
787 SSVAL(req->outbuf, smb_droff,
788 ((smb_buf(req->outbuf)+alignment_offset)
789 - smb_base(req->outbuf))
790 + params_sent_thistime + data_alignment_offset);
791 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
794 /* Initialize the padding for alignment */
796 if (alignment_offset != 0) {
797 memset(smb_buf(req->outbuf), 0, alignment_offset);
800 /* Copy the param bytes into the packet */
802 if(params_sent_thistime) {
803 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
804 params_sent_thistime);
807 /* Copy in the data bytes */
808 if(data_sent_thistime) {
809 if (data_alignment_offset != 0) {
810 memset((smb_buf(req->outbuf)+alignment_offset+
811 params_sent_thistime), 0,
812 data_alignment_offset);
814 memcpy(smb_buf(req->outbuf)+alignment_offset
815 +params_sent_thistime+data_alignment_offset,
816 pd,data_sent_thistime);
819 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
820 params_sent_thistime, data_sent_thistime, useable_space));
821 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
822 params_to_send, data_to_send, paramsize, datasize));
824 if (overflow) {
825 error_packet_set((char *)req->outbuf,
826 ERRDOS,ERRbufferoverflow,
827 STATUS_BUFFER_OVERFLOW,
828 __LINE__,__FILE__);
831 /* Send the packet */
832 show_msg((char *)req->outbuf);
833 if (!srv_send_smb(smbd_server_fd(),
834 (char *)req->outbuf,
835 IS_CONN_ENCRYPTED(conn),
836 &req->pcd))
837 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
839 TALLOC_FREE(req->outbuf);
841 pp += params_sent_thistime;
842 pd += data_sent_thistime;
844 params_to_send -= params_sent_thistime;
845 data_to_send -= data_sent_thistime;
847 /* Sanity check */
848 if(params_to_send < 0 || data_to_send < 0) {
849 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
850 params_to_send, data_to_send));
851 return;
855 return;
858 /****************************************************************************
859 Reply to a TRANSACT2_OPEN.
860 ****************************************************************************/
862 static void call_trans2open(connection_struct *conn,
863 struct smb_request *req,
864 char **pparams, int total_params,
865 char **ppdata, int total_data,
866 unsigned int max_data_bytes)
868 char *params = *pparams;
869 char *pdata = *ppdata;
870 int deny_mode;
871 int32 open_attr;
872 bool oplock_request;
873 #if 0
874 bool return_additional_info;
875 int16 open_sattr;
876 time_t open_time;
877 #endif
878 int open_ofun;
879 uint32 open_size;
880 char *pname;
881 char *fname = NULL;
882 SMB_OFF_T size=0;
883 int fattr=0,mtime=0;
884 SMB_INO_T inode = 0;
885 SMB_STRUCT_STAT sbuf;
886 int smb_action = 0;
887 files_struct *fsp;
888 struct ea_list *ea_list = NULL;
889 uint16 flags = 0;
890 NTSTATUS status;
891 uint32 access_mask;
892 uint32 share_mode;
893 uint32 create_disposition;
894 uint32 create_options = 0;
895 TALLOC_CTX *ctx = talloc_tos();
897 SET_STAT_INVALID(sbuf);
900 * Ensure we have enough parameters to perform the operation.
903 if (total_params < 29) {
904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
905 return;
908 flags = SVAL(params, 0);
909 deny_mode = SVAL(params, 2);
910 open_attr = SVAL(params,6);
911 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
912 if (oplock_request) {
913 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
916 #if 0
917 return_additional_info = BITSETW(params,0);
918 open_sattr = SVAL(params, 4);
919 open_time = make_unix_date3(params+8);
920 #endif
921 open_ofun = SVAL(params,12);
922 open_size = IVAL(params,14);
923 pname = &params[28];
925 if (IS_IPC(conn)) {
926 reply_doserror(req, ERRSRV, ERRaccess);
927 return;
930 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
931 total_params - 28, STR_TERMINATE,
932 &status);
933 if (!NT_STATUS_IS_OK(status)) {
934 reply_nterror(req, status);
935 return;
938 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
939 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
940 (unsigned int)open_ofun, open_size));
942 if (open_ofun == 0) {
943 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
944 return;
947 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
948 &access_mask,
949 &share_mode,
950 &create_disposition,
951 &create_options)) {
952 reply_doserror(req, ERRDOS, ERRbadaccess);
953 return;
956 /* Any data in this call is an EA list. */
957 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
958 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
959 return;
962 if (total_data != 4) {
963 if (total_data < 10) {
964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
965 return;
968 if (IVAL(pdata,0) > total_data) {
969 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
970 IVAL(pdata,0), (unsigned int)total_data));
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 return;
975 ea_list = read_ea_list(talloc_tos(), pdata + 4,
976 total_data - 4);
977 if (!ea_list) {
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 return;
981 } else if (IVAL(pdata,0) != 4) {
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 return;
986 status = SMB_VFS_CREATE_FILE(
987 conn, /* conn */
988 req, /* req */
989 0, /* root_dir_fid */
990 fname, /* fname */
991 CFF_DOS_PATH, /* create_file_flags */
992 access_mask, /* access_mask */
993 share_mode, /* share_access */
994 create_disposition, /* create_disposition*/
995 create_options, /* create_options */
996 open_attr, /* file_attributes */
997 oplock_request, /* oplock_request */
998 open_size, /* allocation_size */
999 NULL, /* sd */
1000 ea_list, /* ea_list */
1001 &fsp, /* result */
1002 &smb_action, /* pinfo */
1003 &sbuf); /* psbuf */
1005 if (!NT_STATUS_IS_OK(status)) {
1006 if (open_was_deferred(req->mid)) {
1007 /* We have re-scheduled this call. */
1008 return;
1010 reply_openerror(req, status);
1011 return;
1014 size = get_file_size_stat(&sbuf);
1015 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1016 mtime = sbuf.st_mtime;
1017 inode = sbuf.st_ino;
1018 if (fattr & aDIR) {
1019 close_file(req, fsp, ERROR_CLOSE);
1020 reply_doserror(req, ERRDOS,ERRnoaccess);
1021 return;
1024 /* Realloc the size of parameters and data we will return */
1025 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1026 if(*pparams == NULL ) {
1027 reply_nterror(req, NT_STATUS_NO_MEMORY);
1028 return;
1030 params = *pparams;
1032 SSVAL(params,0,fsp->fnum);
1033 SSVAL(params,2,fattr);
1034 srv_put_dos_date2(params,4, mtime);
1035 SIVAL(params,8, (uint32)size);
1036 SSVAL(params,12,deny_mode);
1037 SSVAL(params,14,0); /* open_type - file or directory. */
1038 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1040 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1041 smb_action |= EXTENDED_OPLOCK_GRANTED;
1044 SSVAL(params,18,smb_action);
1047 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1049 SIVAL(params,20,inode);
1050 SSVAL(params,24,0); /* Padding. */
1051 if (flags & 8) {
1052 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1053 SIVAL(params, 26, ea_size);
1054 } else {
1055 SIVAL(params, 26, 0);
1058 /* Send the required number of replies */
1059 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1062 /*********************************************************
1063 Routine to check if a given string matches exactly.
1064 as a special case a mask of "." does NOT match. That
1065 is required for correct wildcard semantics
1066 Case can be significant or not.
1067 **********************************************************/
1069 static bool exact_match(connection_struct *conn,
1070 const char *str,
1071 const char *mask)
1073 if (mask[0] == '.' && mask[1] == 0)
1074 return False;
1075 if (dptr_has_wild(conn->dirptr)) {
1076 return False;
1078 if (conn->case_sensitive)
1079 return strcmp(str,mask)==0;
1080 else
1081 return StrCaseCmp(str,mask) == 0;
1084 /****************************************************************************
1085 Return the filetype for UNIX extensions.
1086 ****************************************************************************/
1088 static uint32 unix_filetype(mode_t mode)
1090 if(S_ISREG(mode))
1091 return UNIX_TYPE_FILE;
1092 else if(S_ISDIR(mode))
1093 return UNIX_TYPE_DIR;
1094 #ifdef S_ISLNK
1095 else if(S_ISLNK(mode))
1096 return UNIX_TYPE_SYMLINK;
1097 #endif
1098 #ifdef S_ISCHR
1099 else if(S_ISCHR(mode))
1100 return UNIX_TYPE_CHARDEV;
1101 #endif
1102 #ifdef S_ISBLK
1103 else if(S_ISBLK(mode))
1104 return UNIX_TYPE_BLKDEV;
1105 #endif
1106 #ifdef S_ISFIFO
1107 else if(S_ISFIFO(mode))
1108 return UNIX_TYPE_FIFO;
1109 #endif
1110 #ifdef S_ISSOCK
1111 else if(S_ISSOCK(mode))
1112 return UNIX_TYPE_SOCKET;
1113 #endif
1115 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1116 return UNIX_TYPE_UNKNOWN;
1119 /****************************************************************************
1120 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1121 ****************************************************************************/
1123 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1125 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1126 SMB_STRUCT_STAT *psbuf,
1127 uint32 perms,
1128 enum perm_type ptype,
1129 mode_t *ret_perms)
1131 mode_t ret = 0;
1133 if (perms == SMB_MODE_NO_CHANGE) {
1134 if (!VALID_STAT(*psbuf)) {
1135 return NT_STATUS_INVALID_PARAMETER;
1136 } else {
1137 *ret_perms = psbuf->st_mode;
1138 return NT_STATUS_OK;
1142 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1143 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1144 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1145 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1146 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1147 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1148 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1149 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1150 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1151 #ifdef S_ISVTX
1152 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1153 #endif
1154 #ifdef S_ISGID
1155 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1156 #endif
1157 #ifdef S_ISUID
1158 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1159 #endif
1161 switch (ptype) {
1162 case PERM_NEW_FILE:
1163 /* Apply mode mask */
1164 ret &= lp_create_mask(SNUM(conn));
1165 /* Add in force bits */
1166 ret |= lp_force_create_mode(SNUM(conn));
1167 break;
1168 case PERM_NEW_DIR:
1169 ret &= lp_dir_mask(SNUM(conn));
1170 /* Add in force bits */
1171 ret |= lp_force_dir_mode(SNUM(conn));
1172 break;
1173 case PERM_EXISTING_FILE:
1174 /* Apply mode mask */
1175 ret &= lp_security_mask(SNUM(conn));
1176 /* Add in force bits */
1177 ret |= lp_force_security_mode(SNUM(conn));
1178 break;
1179 case PERM_EXISTING_DIR:
1180 /* Apply mode mask */
1181 ret &= lp_dir_security_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_dir_security_mode(SNUM(conn));
1184 break;
1187 *ret_perms = ret;
1188 return NT_STATUS_OK;
1191 /****************************************************************************
1192 Needed to show the msdfs symlinks as directories. Modifies psbuf
1193 to be a directory if it's a msdfs link.
1194 ****************************************************************************/
1196 static bool check_msdfs_link(connection_struct *conn,
1197 const char *pathname,
1198 SMB_STRUCT_STAT *psbuf)
1200 int saved_errno = errno;
1201 if(lp_host_msdfs() &&
1202 lp_msdfs_root(SNUM(conn)) &&
1203 is_msdfs_link(conn, pathname, psbuf)) {
1205 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1206 "as a directory\n",
1207 pathname));
1208 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1209 errno = saved_errno;
1210 return true;
1212 errno = saved_errno;
1213 return false;
1217 /****************************************************************************
1218 Get a level dependent lanman2 dir entry.
1219 ****************************************************************************/
1221 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1222 connection_struct *conn,
1223 uint16 flags2,
1224 const char *path_mask,
1225 uint32 dirtype,
1226 int info_level,
1227 int requires_resume_key,
1228 bool dont_descend,
1229 bool ask_sharemode,
1230 char **ppdata,
1231 char *base_data,
1232 char *end_data,
1233 int space_remaining,
1234 bool *out_of_space,
1235 bool *got_exact_match,
1236 int *last_entry_off,
1237 struct ea_list *name_list)
1239 char *dname;
1240 bool found = False;
1241 SMB_STRUCT_STAT sbuf;
1242 const char *mask = NULL;
1243 char *pathreal = NULL;
1244 char *fname = NULL;
1245 char *p, *q, *pdata = *ppdata;
1246 uint32 reskey=0;
1247 long prev_dirpos=0;
1248 uint32 mode=0;
1249 SMB_OFF_T file_size = 0;
1250 uint64_t allocation_size = 0;
1251 uint32 len;
1252 struct timespec mdate_ts, adate_ts, create_date_ts;
1253 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1254 char *nameptr;
1255 char *last_entry_ptr;
1256 bool was_8_3;
1257 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1258 bool check_mangled_names = lp_manglednames(conn->params);
1259 char mangled_name[13]; /* mangled 8.3 name. */
1261 *out_of_space = False;
1262 *got_exact_match = False;
1264 ZERO_STRUCT(mdate_ts);
1265 ZERO_STRUCT(adate_ts);
1266 ZERO_STRUCT(create_date_ts);
1268 if (!conn->dirptr) {
1269 return(False);
1272 p = strrchr_m(path_mask,'/');
1273 if(p != NULL) {
1274 if(p[1] == '\0') {
1275 mask = talloc_strdup(ctx,"*.*");
1276 } else {
1277 mask = p+1;
1279 } else {
1280 mask = path_mask;
1283 while (!found) {
1284 bool got_match;
1285 bool ms_dfs_link = False;
1287 /* Needed if we run out of space */
1288 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1289 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1292 * Due to bugs in NT client redirectors we are not using
1293 * resume keys any more - set them to zero.
1294 * Check out the related comments in findfirst/findnext.
1295 * JRA.
1298 reskey = 0;
1300 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1301 (long)conn->dirptr,curr_dirpos));
1303 if (!dname) {
1304 return(False);
1308 * fname may get mangled, dname is never mangled.
1309 * Whenever we're accessing the filesystem we use
1310 * pathreal which is composed from dname.
1313 pathreal = NULL;
1314 fname = dname;
1316 /* Mangle fname if it's an illegal name. */
1317 if (mangle_must_mangle(dname,conn->params)) {
1318 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1319 TALLOC_FREE(fname);
1320 continue; /* Error - couldn't mangle. */
1322 fname = talloc_strdup(ctx, mangled_name);
1323 if (!fname) {
1324 return False;
1328 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1329 got_match = mask_match(fname, mask, conn->case_sensitive);
1332 if(!got_match && check_mangled_names &&
1333 !mangle_is_8_3(fname, False, conn->params)) {
1335 * It turns out that NT matches wildcards against
1336 * both long *and* short names. This may explain some
1337 * of the wildcard wierdness from old DOS clients
1338 * that some people have been seeing.... JRA.
1340 /* Force the mangling into 8.3. */
1341 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1342 TALLOC_FREE(fname);
1343 continue; /* Error - couldn't mangle. */
1346 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1347 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1351 if (got_match) {
1352 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1354 if (dont_descend && !isdots) {
1355 TALLOC_FREE(fname);
1356 continue;
1359 if (needslash) {
1360 pathreal = NULL;
1361 pathreal = talloc_asprintf(ctx,
1362 "%s/%s",
1363 conn->dirpath,
1364 dname);
1365 } else {
1366 pathreal = talloc_asprintf(ctx,
1367 "%s%s",
1368 conn->dirpath,
1369 dname);
1372 if (!pathreal) {
1373 TALLOC_FREE(fname);
1374 return False;
1377 if (INFO_LEVEL_IS_UNIX(info_level)) {
1378 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1379 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1380 pathreal,strerror(errno)));
1381 TALLOC_FREE(pathreal);
1382 TALLOC_FREE(fname);
1383 continue;
1385 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1386 /* Needed to show the msdfs symlinks as
1387 * directories */
1389 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1390 if (!ms_dfs_link) {
1391 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1392 pathreal,strerror(errno)));
1393 TALLOC_FREE(pathreal);
1394 TALLOC_FREE(fname);
1395 continue;
1399 if (ms_dfs_link) {
1400 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1401 } else {
1402 mode = dos_mode(conn,pathreal,&sbuf);
1405 if (!dir_check_ftype(conn,mode,dirtype)) {
1406 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1407 TALLOC_FREE(pathreal);
1408 TALLOC_FREE(fname);
1409 continue;
1412 if (!(mode & aDIR)) {
1413 file_size = get_file_size_stat(&sbuf);
1415 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1417 mdate_ts = get_mtimespec(&sbuf);
1418 adate_ts = get_atimespec(&sbuf);
1419 create_date_ts = get_create_timespec(&sbuf,
1420 lp_fake_dir_create_times(SNUM(conn)));
1422 if (ask_sharemode) {
1423 struct timespec write_time_ts;
1424 struct file_id fileid;
1426 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1427 get_file_infos(fileid, NULL, &write_time_ts);
1428 if (!null_timespec(write_time_ts)) {
1429 mdate_ts = write_time_ts;
1433 if (lp_dos_filetime_resolution(SNUM(conn))) {
1434 dos_filetime_timespec(&create_date_ts);
1435 dos_filetime_timespec(&mdate_ts);
1436 dos_filetime_timespec(&adate_ts);
1439 create_date = convert_timespec_to_time_t(create_date_ts);
1440 mdate = convert_timespec_to_time_t(mdate_ts);
1441 adate = convert_timespec_to_time_t(adate_ts);
1443 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1444 pathreal,fname));
1446 found = True;
1448 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1451 if (!found)
1452 TALLOC_FREE(fname);
1455 p = pdata;
1456 last_entry_ptr = p;
1458 switch (info_level) {
1459 case SMB_FIND_INFO_STANDARD:
1460 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1461 if(requires_resume_key) {
1462 SIVAL(p,0,reskey);
1463 p += 4;
1465 srv_put_dos_date2(p,0,create_date);
1466 srv_put_dos_date2(p,4,adate);
1467 srv_put_dos_date2(p,8,mdate);
1468 SIVAL(p,12,(uint32)file_size);
1469 SIVAL(p,16,(uint32)allocation_size);
1470 SSVAL(p,20,mode);
1471 p += 23;
1472 nameptr = p;
1473 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1474 p += ucs2_align(base_data, p, 0);
1476 len = srvstr_push(base_data, flags2, p,
1477 fname, PTR_DIFF(end_data, p),
1478 STR_TERMINATE);
1479 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1480 if (len > 2) {
1481 SCVAL(nameptr, -1, len - 2);
1482 } else {
1483 SCVAL(nameptr, -1, 0);
1485 } else {
1486 if (len > 1) {
1487 SCVAL(nameptr, -1, len - 1);
1488 } else {
1489 SCVAL(nameptr, -1, 0);
1492 p += len;
1493 break;
1495 case SMB_FIND_EA_SIZE:
1496 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1497 if(requires_resume_key) {
1498 SIVAL(p,0,reskey);
1499 p += 4;
1501 srv_put_dos_date2(p,0,create_date);
1502 srv_put_dos_date2(p,4,adate);
1503 srv_put_dos_date2(p,8,mdate);
1504 SIVAL(p,12,(uint32)file_size);
1505 SIVAL(p,16,(uint32)allocation_size);
1506 SSVAL(p,20,mode);
1508 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1509 SIVAL(p,22,ea_size); /* Extended attributes */
1511 p += 27;
1512 nameptr = p - 1;
1513 len = srvstr_push(base_data, flags2,
1514 p, fname, PTR_DIFF(end_data, p),
1515 STR_TERMINATE | STR_NOALIGN);
1516 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1517 if (len > 2) {
1518 len -= 2;
1519 } else {
1520 len = 0;
1522 } else {
1523 if (len > 1) {
1524 len -= 1;
1525 } else {
1526 len = 0;
1529 SCVAL(nameptr,0,len);
1530 p += len;
1531 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1532 break;
1534 case SMB_FIND_EA_LIST:
1536 struct ea_list *file_list = NULL;
1537 size_t ea_len = 0;
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1540 if (!name_list) {
1541 return False;
1543 if(requires_resume_key) {
1544 SIVAL(p,0,reskey);
1545 p += 4;
1547 srv_put_dos_date2(p,0,create_date);
1548 srv_put_dos_date2(p,4,adate);
1549 srv_put_dos_date2(p,8,mdate);
1550 SIVAL(p,12,(uint32)file_size);
1551 SIVAL(p,16,(uint32)allocation_size);
1552 SSVAL(p,20,mode);
1553 p += 22; /* p now points to the EA area. */
1555 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1556 name_list = ea_list_union(name_list, file_list, &ea_len);
1558 /* We need to determine if this entry will fit in the space available. */
1559 /* Max string size is 255 bytes. */
1560 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1561 /* Move the dirptr back to prev_dirpos */
1562 dptr_SeekDir(conn->dirptr, prev_dirpos);
1563 *out_of_space = True;
1564 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1565 return False; /* Not finished - just out of space */
1568 /* Push the ea_data followed by the name. */
1569 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1570 nameptr = p;
1571 len = srvstr_push(base_data, flags2,
1572 p + 1, fname, PTR_DIFF(end_data, p+1),
1573 STR_TERMINATE | STR_NOALIGN);
1574 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1575 if (len > 2) {
1576 len -= 2;
1577 } else {
1578 len = 0;
1580 } else {
1581 if (len > 1) {
1582 len -= 1;
1583 } else {
1584 len = 0;
1587 SCVAL(nameptr,0,len);
1588 p += len + 1;
1589 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1590 break;
1593 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1594 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1595 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1596 p += 4;
1597 SIVAL(p,0,reskey); p += 4;
1598 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1599 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1600 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1601 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1602 SOFF_T(p,0,file_size); p += 8;
1603 SOFF_T(p,0,allocation_size); p += 8;
1604 SIVAL(p,0,mode); p += 4;
1605 q = p; p += 4; /* q is placeholder for name length. */
1607 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1608 SIVAL(p,0,ea_size); /* Extended attributes */
1609 p += 4;
1611 /* Clear the short name buffer. This is
1612 * IMPORTANT as not doing so will trigger
1613 * a Win2k client bug. JRA.
1615 if (!was_8_3 && check_mangled_names) {
1616 if (!name_to_8_3(fname,mangled_name,True,
1617 conn->params)) {
1618 /* Error - mangle failed ! */
1619 memset(mangled_name,'\0',12);
1621 mangled_name[12] = 0;
1622 len = srvstr_push(base_data, flags2,
1623 p+2, mangled_name, 24,
1624 STR_UPPER|STR_UNICODE);
1625 if (len < 24) {
1626 memset(p + 2 + len,'\0',24 - len);
1628 SSVAL(p, 0, len);
1629 } else {
1630 memset(p,'\0',26);
1632 p += 2 + 24;
1633 len = srvstr_push(base_data, flags2, p,
1634 fname, PTR_DIFF(end_data, p),
1635 STR_TERMINATE_ASCII);
1636 SIVAL(q,0,len);
1637 p += len;
1638 SIVAL(p,0,0); /* Ensure any padding is null. */
1639 len = PTR_DIFF(p, pdata);
1640 len = (len + 3) & ~3;
1641 SIVAL(pdata,0,len);
1642 p = pdata + len;
1643 break;
1645 case SMB_FIND_FILE_DIRECTORY_INFO:
1646 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1647 p += 4;
1648 SIVAL(p,0,reskey); p += 4;
1649 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1650 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1651 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1652 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1653 SOFF_T(p,0,file_size); p += 8;
1654 SOFF_T(p,0,allocation_size); p += 8;
1655 SIVAL(p,0,mode); p += 4;
1656 len = srvstr_push(base_data, flags2,
1657 p + 4, fname, PTR_DIFF(end_data, p+4),
1658 STR_TERMINATE_ASCII);
1659 SIVAL(p,0,len);
1660 p += 4 + len;
1661 SIVAL(p,0,0); /* Ensure any padding is null. */
1662 len = PTR_DIFF(p, pdata);
1663 len = (len + 3) & ~3;
1664 SIVAL(pdata,0,len);
1665 p = pdata + len;
1666 break;
1668 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1669 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1670 p += 4;
1671 SIVAL(p,0,reskey); p += 4;
1672 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1673 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1674 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1675 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1676 SOFF_T(p,0,file_size); p += 8;
1677 SOFF_T(p,0,allocation_size); p += 8;
1678 SIVAL(p,0,mode); p += 4;
1679 q = p; p += 4; /* q is placeholder for name length. */
1681 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1682 SIVAL(p,0,ea_size); /* Extended attributes */
1683 p +=4;
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE_ASCII);
1688 SIVAL(q, 0, len);
1689 p += len;
1691 SIVAL(p,0,0); /* Ensure any padding is null. */
1692 len = PTR_DIFF(p, pdata);
1693 len = (len + 3) & ~3;
1694 SIVAL(pdata,0,len);
1695 p = pdata + len;
1696 break;
1698 case SMB_FIND_FILE_NAMES_INFO:
1699 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1700 p += 4;
1701 SIVAL(p,0,reskey); p += 4;
1702 p += 4;
1703 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1704 acl on a dir (tridge) */
1705 len = srvstr_push(base_data, flags2, p,
1706 fname, PTR_DIFF(end_data, p),
1707 STR_TERMINATE_ASCII);
1708 SIVAL(p, -4, len);
1709 p += len;
1710 SIVAL(p,0,0); /* Ensure any padding is null. */
1711 len = PTR_DIFF(p, pdata);
1712 len = (len + 3) & ~3;
1713 SIVAL(pdata,0,len);
1714 p = pdata + len;
1715 break;
1717 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1718 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1719 p += 4;
1720 SIVAL(p,0,reskey); p += 4;
1721 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1722 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1723 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1724 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1725 SOFF_T(p,0,file_size); p += 8;
1726 SOFF_T(p,0,allocation_size); p += 8;
1727 SIVAL(p,0,mode); p += 4;
1728 q = p; p += 4; /* q is placeholder for name length. */
1730 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1731 SIVAL(p,0,ea_size); /* Extended attributes */
1732 p +=4;
1734 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1735 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1736 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1737 len = srvstr_push(base_data, flags2, p,
1738 fname, PTR_DIFF(end_data, p),
1739 STR_TERMINATE_ASCII);
1740 SIVAL(q, 0, len);
1741 p += len;
1742 SIVAL(p,0,0); /* Ensure any padding is null. */
1743 len = PTR_DIFF(p, pdata);
1744 len = (len + 3) & ~3;
1745 SIVAL(pdata,0,len);
1746 p = pdata + len;
1747 break;
1749 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1750 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1751 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1752 p += 4;
1753 SIVAL(p,0,reskey); p += 4;
1754 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1755 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1758 SOFF_T(p,0,file_size); p += 8;
1759 SOFF_T(p,0,allocation_size); p += 8;
1760 SIVAL(p,0,mode); p += 4;
1761 q = p; p += 4; /* q is placeholder for name length */
1763 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1764 SIVAL(p,0,ea_size); /* Extended attributes */
1765 p +=4;
1767 /* Clear the short name buffer. This is
1768 * IMPORTANT as not doing so will trigger
1769 * a Win2k client bug. JRA.
1771 if (!was_8_3 && check_mangled_names) {
1772 if (!name_to_8_3(fname,mangled_name,True,
1773 conn->params)) {
1774 /* Error - mangle failed ! */
1775 memset(mangled_name,'\0',12);
1777 mangled_name[12] = 0;
1778 len = srvstr_push(base_data, flags2,
1779 p+2, mangled_name, 24,
1780 STR_UPPER|STR_UNICODE);
1781 SSVAL(p, 0, len);
1782 if (len < 24) {
1783 memset(p + 2 + len,'\0',24 - len);
1785 SSVAL(p, 0, len);
1786 } else {
1787 memset(p,'\0',26);
1789 p += 26;
1790 SSVAL(p,0,0); p += 2; /* Reserved ? */
1791 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1792 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1793 len = srvstr_push(base_data, flags2, p,
1794 fname, PTR_DIFF(end_data, p),
1795 STR_TERMINATE_ASCII);
1796 SIVAL(q,0,len);
1797 p += len;
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1799 len = PTR_DIFF(p, pdata);
1800 len = (len + 3) & ~3;
1801 SIVAL(pdata,0,len);
1802 p = pdata + len;
1803 break;
1805 /* CIFS UNIX Extension. */
1807 case SMB_FIND_FILE_UNIX:
1808 case SMB_FIND_FILE_UNIX_INFO2:
1809 p+= 4;
1810 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1812 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1814 if (info_level == SMB_FIND_FILE_UNIX) {
1815 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1816 p = store_file_unix_basic(conn, p,
1817 NULL, &sbuf);
1818 len = srvstr_push(base_data, flags2, p,
1819 fname, PTR_DIFF(end_data, p),
1820 STR_TERMINATE);
1821 } else {
1822 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1823 p = store_file_unix_basic_info2(conn, p,
1824 NULL, &sbuf);
1825 nameptr = p;
1826 p += 4;
1827 len = srvstr_push(base_data, flags2, p, fname,
1828 PTR_DIFF(end_data, p), 0);
1829 SIVAL(nameptr, 0, len);
1832 p += len;
1833 SIVAL(p,0,0); /* Ensure any padding is null. */
1835 len = PTR_DIFF(p, pdata);
1836 len = (len + 3) & ~3;
1837 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1838 p = pdata + len;
1839 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1841 break;
1843 default:
1844 TALLOC_FREE(fname);
1845 return(False);
1848 TALLOC_FREE(fname);
1849 if (PTR_DIFF(p,pdata) > space_remaining) {
1850 /* Move the dirptr back to prev_dirpos */
1851 dptr_SeekDir(conn->dirptr, prev_dirpos);
1852 *out_of_space = True;
1853 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1854 return False; /* Not finished - just out of space */
1857 /* Setup the last entry pointer, as an offset from base_data */
1858 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1859 /* Advance the data pointer to the next slot */
1860 *ppdata = p;
1862 return(found);
1865 /****************************************************************************
1866 Reply to a TRANS2_FINDFIRST.
1867 ****************************************************************************/
1869 static void call_trans2findfirst(connection_struct *conn,
1870 struct smb_request *req,
1871 char **pparams, int total_params,
1872 char **ppdata, int total_data,
1873 unsigned int max_data_bytes)
1875 /* We must be careful here that we don't return more than the
1876 allowed number of data bytes. If this means returning fewer than
1877 maxentries then so be it. We assume that the redirector has
1878 enough room for the fixed number of parameter bytes it has
1879 requested. */
1880 char *params = *pparams;
1881 char *pdata = *ppdata;
1882 char *data_end;
1883 uint32 dirtype;
1884 int maxentries;
1885 uint16 findfirst_flags;
1886 bool close_after_first;
1887 bool close_if_end;
1888 bool requires_resume_key;
1889 int info_level;
1890 char *directory = NULL;
1891 char *mask = NULL;
1892 char *p;
1893 int last_entry_off=0;
1894 int dptr_num = -1;
1895 int numentries = 0;
1896 int i;
1897 bool finished = False;
1898 bool dont_descend = False;
1899 bool out_of_space = False;
1900 int space_remaining;
1901 bool mask_contains_wcard = False;
1902 SMB_STRUCT_STAT sbuf;
1903 struct ea_list *ea_list = NULL;
1904 NTSTATUS ntstatus = NT_STATUS_OK;
1905 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1906 TALLOC_CTX *ctx = talloc_tos();
1908 if (total_params < 13) {
1909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1910 return;
1913 dirtype = SVAL(params,0);
1914 maxentries = SVAL(params,2);
1915 findfirst_flags = SVAL(params,4);
1916 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1917 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1918 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1919 info_level = SVAL(params,6);
1921 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1922 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1923 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1924 info_level, max_data_bytes));
1926 if (!maxentries) {
1927 /* W2K3 seems to treat zero as 1. */
1928 maxentries = 1;
1931 switch (info_level) {
1932 case SMB_FIND_INFO_STANDARD:
1933 case SMB_FIND_EA_SIZE:
1934 case SMB_FIND_EA_LIST:
1935 case SMB_FIND_FILE_DIRECTORY_INFO:
1936 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1937 case SMB_FIND_FILE_NAMES_INFO:
1938 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1939 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1940 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1941 break;
1942 case SMB_FIND_FILE_UNIX:
1943 case SMB_FIND_FILE_UNIX_INFO2:
1944 /* Always use filesystem for UNIX mtime query. */
1945 ask_sharemode = false;
1946 if (!lp_unix_extensions()) {
1947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1948 return;
1950 break;
1951 default:
1952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1953 return;
1956 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1957 params+12, total_params - 12,
1958 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1959 if (!NT_STATUS_IS_OK(ntstatus)) {
1960 reply_nterror(req, ntstatus);
1961 return;
1964 ntstatus = resolve_dfspath_wcard(ctx, conn,
1965 req->flags2 & FLAGS2_DFS_PATHNAMES,
1966 directory,
1967 &directory,
1968 &mask_contains_wcard);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1971 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1972 ERRSRV, ERRbadpath);
1973 return;
1975 reply_nterror(req, ntstatus);
1976 return;
1979 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1980 if (!NT_STATUS_IS_OK(ntstatus)) {
1981 reply_nterror(req, ntstatus);
1982 return;
1985 ntstatus = check_name(conn, directory);
1986 if (!NT_STATUS_IS_OK(ntstatus)) {
1987 reply_nterror(req, ntstatus);
1988 return;
1991 p = strrchr_m(directory,'/');
1992 if(p == NULL) {
1993 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1994 if((directory[0] == '.') && (directory[1] == '\0')) {
1995 mask = talloc_strdup(ctx,"*");
1996 if (!mask) {
1997 reply_nterror(req, NT_STATUS_NO_MEMORY);
1998 return;
2000 mask_contains_wcard = True;
2002 directory = talloc_strdup(talloc_tos(), "./");
2003 if (!directory) {
2004 reply_nterror(req, NT_STATUS_NO_MEMORY);
2005 return;
2007 } else {
2008 *p = 0;
2011 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2013 if (info_level == SMB_FIND_EA_LIST) {
2014 uint32 ea_size;
2016 if (total_data < 4) {
2017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2018 return;
2021 ea_size = IVAL(pdata,0);
2022 if (ea_size != total_data) {
2023 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2024 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2026 return;
2029 if (!lp_ea_support(SNUM(conn))) {
2030 reply_doserror(req, ERRDOS, ERReasnotsupported);
2031 return;
2034 /* Pull out the list of names. */
2035 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2036 if (!ea_list) {
2037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2038 return;
2042 *ppdata = (char *)SMB_REALLOC(
2043 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2044 if(*ppdata == NULL ) {
2045 reply_nterror(req, NT_STATUS_NO_MEMORY);
2046 return;
2048 pdata = *ppdata;
2049 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2051 /* Realloc the params space */
2052 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2053 if (*pparams == NULL) {
2054 reply_nterror(req, NT_STATUS_NO_MEMORY);
2055 return;
2057 params = *pparams;
2059 /* Save the wildcard match and attribs we are using on this directory -
2060 needed as lanman2 assumes these are being saved between calls */
2062 ntstatus = dptr_create(conn,
2063 directory,
2064 False,
2065 True,
2066 req->smbpid,
2067 mask,
2068 mask_contains_wcard,
2069 dirtype,
2070 &conn->dirptr);
2072 if (!NT_STATUS_IS_OK(ntstatus)) {
2073 reply_nterror(req, ntstatus);
2074 return;
2077 dptr_num = dptr_dnum(conn->dirptr);
2078 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2080 /* Initialize per TRANS2_FIND_FIRST operation data */
2081 dptr_init_search_op(conn->dirptr);
2083 /* We don't need to check for VOL here as this is returned by
2084 a different TRANS2 call. */
2086 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2087 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2088 dont_descend = True;
2090 p = pdata;
2091 space_remaining = max_data_bytes;
2092 out_of_space = False;
2094 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2095 bool got_exact_match = False;
2097 /* this is a heuristic to avoid seeking the dirptr except when
2098 absolutely necessary. It allows for a filename of about 40 chars */
2099 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2100 out_of_space = True;
2101 finished = False;
2102 } else {
2103 finished = !get_lanman2_dir_entry(ctx,
2104 conn,
2105 req->flags2,
2106 mask,dirtype,info_level,
2107 requires_resume_key,dont_descend,
2108 ask_sharemode,
2109 &p,pdata,data_end,
2110 space_remaining, &out_of_space,
2111 &got_exact_match,
2112 &last_entry_off, ea_list);
2115 if (finished && out_of_space)
2116 finished = False;
2118 if (!finished && !out_of_space)
2119 numentries++;
2122 * As an optimisation if we know we aren't looking
2123 * for a wildcard name (ie. the name matches the wildcard exactly)
2124 * then we can finish on any (first) match.
2125 * This speeds up large directory searches. JRA.
2128 if(got_exact_match)
2129 finished = True;
2131 /* Ensure space_remaining never goes -ve. */
2132 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2133 space_remaining = 0;
2134 out_of_space = true;
2135 } else {
2136 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2140 /* Check if we can close the dirptr */
2141 if(close_after_first || (finished && close_if_end)) {
2142 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2143 dptr_close(&dptr_num);
2147 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2148 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2149 * the protocol level is less than NT1. Tested with smbclient. JRA.
2150 * This should fix the OS/2 client bug #2335.
2153 if(numentries == 0) {
2154 dptr_close(&dptr_num);
2155 if (Protocol < PROTOCOL_NT1) {
2156 reply_doserror(req, ERRDOS, ERRnofiles);
2157 return;
2158 } else {
2159 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2160 ERRDOS, ERRbadfile);
2161 return;
2165 /* At this point pdata points to numentries directory entries. */
2167 /* Set up the return parameter block */
2168 SSVAL(params,0,dptr_num);
2169 SSVAL(params,2,numentries);
2170 SSVAL(params,4,finished);
2171 SSVAL(params,6,0); /* Never an EA error */
2172 SSVAL(params,8,last_entry_off);
2174 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2175 max_data_bytes);
2177 if ((! *directory) && dptr_path(dptr_num)) {
2178 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2179 if (!directory) {
2180 reply_nterror(req, NT_STATUS_NO_MEMORY);
2184 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2185 smb_fn_name(req->cmd),
2186 mask, directory, dirtype, numentries ) );
2189 * Force a name mangle here to ensure that the
2190 * mask as an 8.3 name is top of the mangled cache.
2191 * The reasons for this are subtle. Don't remove
2192 * this code unless you know what you are doing
2193 * (see PR#13758). JRA.
2196 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2197 char mangled_name[13];
2198 name_to_8_3(mask, mangled_name, True, conn->params);
2201 return;
2204 /****************************************************************************
2205 Reply to a TRANS2_FINDNEXT.
2206 ****************************************************************************/
2208 static void call_trans2findnext(connection_struct *conn,
2209 struct smb_request *req,
2210 char **pparams, int total_params,
2211 char **ppdata, int total_data,
2212 unsigned int max_data_bytes)
2214 /* We must be careful here that we don't return more than the
2215 allowed number of data bytes. If this means returning fewer than
2216 maxentries then so be it. We assume that the redirector has
2217 enough room for the fixed number of parameter bytes it has
2218 requested. */
2219 char *params = *pparams;
2220 char *pdata = *ppdata;
2221 char *data_end;
2222 int dptr_num;
2223 int maxentries;
2224 uint16 info_level;
2225 uint32 resume_key;
2226 uint16 findnext_flags;
2227 bool close_after_request;
2228 bool close_if_end;
2229 bool requires_resume_key;
2230 bool continue_bit;
2231 bool mask_contains_wcard = False;
2232 char *resume_name = NULL;
2233 const char *mask = NULL;
2234 const char *directory = NULL;
2235 char *p = NULL;
2236 uint16 dirtype;
2237 int numentries = 0;
2238 int i, last_entry_off=0;
2239 bool finished = False;
2240 bool dont_descend = False;
2241 bool out_of_space = False;
2242 int space_remaining;
2243 struct ea_list *ea_list = NULL;
2244 NTSTATUS ntstatus = NT_STATUS_OK;
2245 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2246 TALLOC_CTX *ctx = talloc_tos();
2248 if (total_params < 13) {
2249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2250 return;
2253 dptr_num = SVAL(params,0);
2254 maxentries = SVAL(params,2);
2255 info_level = SVAL(params,4);
2256 resume_key = IVAL(params,6);
2257 findnext_flags = SVAL(params,10);
2258 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2259 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2260 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2261 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2263 if (!continue_bit) {
2264 /* We only need resume_name if continue_bit is zero. */
2265 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2266 params+12,
2267 total_params - 12, STR_TERMINATE, &ntstatus,
2268 &mask_contains_wcard);
2269 if (!NT_STATUS_IS_OK(ntstatus)) {
2270 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2271 complain (it thinks we're asking for the directory above the shared
2272 path or an invalid name). Catch this as the resume name is only compared, never used in
2273 a file access. JRA. */
2274 srvstr_pull_talloc(ctx, params, req->flags2,
2275 &resume_name, params+12,
2276 total_params - 12,
2277 STR_TERMINATE);
2279 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2280 reply_nterror(req, ntstatus);
2281 return;
2286 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2287 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2288 resume_key = %d resume name = %s continue=%d level = %d\n",
2289 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2290 requires_resume_key, resume_key,
2291 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2293 if (!maxentries) {
2294 /* W2K3 seems to treat zero as 1. */
2295 maxentries = 1;
2298 switch (info_level) {
2299 case SMB_FIND_INFO_STANDARD:
2300 case SMB_FIND_EA_SIZE:
2301 case SMB_FIND_EA_LIST:
2302 case SMB_FIND_FILE_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2304 case SMB_FIND_FILE_NAMES_INFO:
2305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2306 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2308 break;
2309 case SMB_FIND_FILE_UNIX:
2310 case SMB_FIND_FILE_UNIX_INFO2:
2311 /* Always use filesystem for UNIX mtime query. */
2312 ask_sharemode = false;
2313 if (!lp_unix_extensions()) {
2314 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 return;
2317 break;
2318 default:
2319 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2320 return;
2323 if (info_level == SMB_FIND_EA_LIST) {
2324 uint32 ea_size;
2326 if (total_data < 4) {
2327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2328 return;
2331 ea_size = IVAL(pdata,0);
2332 if (ea_size != total_data) {
2333 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2334 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 return;
2339 if (!lp_ea_support(SNUM(conn))) {
2340 reply_doserror(req, ERRDOS, ERReasnotsupported);
2341 return;
2344 /* Pull out the list of names. */
2345 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2346 if (!ea_list) {
2347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2348 return;
2352 *ppdata = (char *)SMB_REALLOC(
2353 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2354 if(*ppdata == NULL) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 return;
2359 pdata = *ppdata;
2360 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2362 /* Realloc the params space */
2363 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2364 if(*pparams == NULL ) {
2365 reply_nterror(req, NT_STATUS_NO_MEMORY);
2366 return;
2369 params = *pparams;
2371 /* Check that the dptr is valid */
2372 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2373 reply_doserror(req, ERRDOS, ERRnofiles);
2374 return;
2377 string_set(&conn->dirpath,dptr_path(dptr_num));
2379 /* Get the wildcard mask from the dptr */
2380 if((p = dptr_wcard(dptr_num))== NULL) {
2381 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2382 reply_doserror(req, ERRDOS, ERRnofiles);
2383 return;
2386 mask = p;
2387 directory = conn->dirpath;
2389 /* Get the attr mask from the dptr */
2390 dirtype = dptr_attr(dptr_num);
2392 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2393 dptr_num, mask, dirtype,
2394 (long)conn->dirptr,
2395 dptr_TellDir(conn->dirptr)));
2397 /* Initialize per TRANS2_FIND_NEXT operation data */
2398 dptr_init_search_op(conn->dirptr);
2400 /* We don't need to check for VOL here as this is returned by
2401 a different TRANS2 call. */
2403 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2404 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2405 dont_descend = True;
2407 p = pdata;
2408 space_remaining = max_data_bytes;
2409 out_of_space = False;
2412 * Seek to the correct position. We no longer use the resume key but
2413 * depend on the last file name instead.
2416 if(!continue_bit && resume_name && *resume_name) {
2417 SMB_STRUCT_STAT st;
2419 long current_pos = 0;
2421 * Remember, name_to_8_3 is called by
2422 * get_lanman2_dir_entry(), so the resume name
2423 * could be mangled. Ensure we check the unmangled name.
2426 if (mangle_is_mangled(resume_name, conn->params)) {
2427 char *new_resume_name = NULL;
2428 mangle_lookup_name_from_8_3(ctx,
2429 resume_name,
2430 &new_resume_name,
2431 conn->params);
2432 if (new_resume_name) {
2433 resume_name = new_resume_name;
2438 * Fix for NT redirector problem triggered by resume key indexes
2439 * changing between directory scans. We now return a resume key of 0
2440 * and instead look for the filename to continue from (also given
2441 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2442 * findfirst/findnext (as is usual) then the directory pointer
2443 * should already be at the correct place.
2446 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2447 } /* end if resume_name && !continue_bit */
2449 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2450 bool got_exact_match = False;
2452 /* this is a heuristic to avoid seeking the dirptr except when
2453 absolutely necessary. It allows for a filename of about 40 chars */
2454 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2455 out_of_space = True;
2456 finished = False;
2457 } else {
2458 finished = !get_lanman2_dir_entry(ctx,
2459 conn,
2460 req->flags2,
2461 mask,dirtype,info_level,
2462 requires_resume_key,dont_descend,
2463 ask_sharemode,
2464 &p,pdata,data_end,
2465 space_remaining, &out_of_space,
2466 &got_exact_match,
2467 &last_entry_off, ea_list);
2470 if (finished && out_of_space)
2471 finished = False;
2473 if (!finished && !out_of_space)
2474 numentries++;
2477 * As an optimisation if we know we aren't looking
2478 * for a wildcard name (ie. the name matches the wildcard exactly)
2479 * then we can finish on any (first) match.
2480 * This speeds up large directory searches. JRA.
2483 if(got_exact_match)
2484 finished = True;
2486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2489 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2490 smb_fn_name(req->cmd),
2491 mask, directory, dirtype, numentries ) );
2493 /* Check if we can close the dirptr */
2494 if(close_after_request || (finished && close_if_end)) {
2495 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2496 dptr_close(&dptr_num); /* This frees up the saved mask */
2499 /* Set up the return parameter block */
2500 SSVAL(params,0,numentries);
2501 SSVAL(params,2,finished);
2502 SSVAL(params,4,0); /* Never an EA error */
2503 SSVAL(params,6,last_entry_off);
2505 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2506 max_data_bytes);
2508 return;
2511 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2513 E_md4hash(lp_servicename(SNUM(conn)),objid);
2514 return objid;
2517 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2519 SMB_ASSERT(extended_info != NULL);
2521 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2522 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2523 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2524 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2525 #ifdef SAMBA_VERSION_REVISION
2526 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2527 #endif
2528 extended_info->samba_subversion = 0;
2529 #ifdef SAMBA_VERSION_RC_RELEASE
2530 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2531 #else
2532 #ifdef SAMBA_VERSION_PRE_RELEASE
2533 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2534 #endif
2535 #endif
2536 #ifdef SAMBA_VERSION_VENDOR_PATCH
2537 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2538 #endif
2539 extended_info->samba_gitcommitdate = 0;
2540 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2541 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2542 #endif
2544 memset(extended_info->samba_version_string, 0,
2545 sizeof(extended_info->samba_version_string));
2547 snprintf (extended_info->samba_version_string,
2548 sizeof(extended_info->samba_version_string),
2549 "%s", samba_version_string());
2552 /****************************************************************************
2553 Reply to a TRANS2_QFSINFO (query filesystem info).
2554 ****************************************************************************/
2556 static void call_trans2qfsinfo(connection_struct *conn,
2557 struct smb_request *req,
2558 char **pparams, int total_params,
2559 char **ppdata, int total_data,
2560 unsigned int max_data_bytes)
2562 char *pdata, *end_data;
2563 char *params = *pparams;
2564 uint16 info_level;
2565 int data_len, len;
2566 SMB_STRUCT_STAT st;
2567 const char *vname = volume_label(SNUM(conn));
2568 int snum = SNUM(conn);
2569 char *fstype = lp_fstype(SNUM(conn));
2570 uint32 additional_flags = 0;
2572 if (total_params < 2) {
2573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2574 return;
2577 info_level = SVAL(params,0);
2579 if (IS_IPC(conn)) {
2580 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2581 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2582 "info level (0x%x) on IPC$.\n",
2583 (unsigned int)info_level));
2584 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2585 return;
2589 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2590 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2591 DEBUG(0,("call_trans2qfsinfo: encryption required "
2592 "and info level 0x%x sent.\n",
2593 (unsigned int)info_level));
2594 exit_server_cleanly("encryption required "
2595 "on connection");
2596 return;
2600 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2602 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2603 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2604 reply_doserror(req, ERRSRV, ERRinvdevice);
2605 return;
2608 *ppdata = (char *)SMB_REALLOC(
2609 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2610 if (*ppdata == NULL ) {
2611 reply_nterror(req, NT_STATUS_NO_MEMORY);
2612 return;
2615 pdata = *ppdata;
2616 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2617 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2619 switch (info_level) {
2620 case SMB_INFO_ALLOCATION:
2622 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2623 data_len = 18;
2624 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2625 reply_unixerror(req, ERRHRD, ERRgeneral);
2626 return;
2629 block_size = lp_block_size(snum);
2630 if (bsize < block_size) {
2631 uint64_t factor = block_size/bsize;
2632 bsize = block_size;
2633 dsize /= factor;
2634 dfree /= factor;
2636 if (bsize > block_size) {
2637 uint64_t factor = bsize/block_size;
2638 bsize = block_size;
2639 dsize *= factor;
2640 dfree *= factor;
2642 bytes_per_sector = 512;
2643 sectors_per_unit = bsize/bytes_per_sector;
2645 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2647 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2649 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2650 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2651 SIVAL(pdata,l1_cUnit,dsize);
2652 SIVAL(pdata,l1_cUnitAvail,dfree);
2653 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2654 break;
2657 case SMB_INFO_VOLUME:
2658 /* Return volume name */
2660 * Add volume serial number - hash of a combination of
2661 * the called hostname and the service name.
2663 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2665 * Win2k3 and previous mess this up by sending a name length
2666 * one byte short. I believe only older clients (OS/2 Win9x) use
2667 * this call so try fixing this by adding a terminating null to
2668 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2670 len = srvstr_push(
2671 pdata, req->flags2,
2672 pdata+l2_vol_szVolLabel, vname,
2673 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2674 STR_NOALIGN|STR_TERMINATE);
2675 SCVAL(pdata,l2_vol_cch,len);
2676 data_len = l2_vol_szVolLabel + len;
2677 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2678 (unsigned)st.st_ctime, len, vname));
2679 break;
2681 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2682 case SMB_FS_ATTRIBUTE_INFORMATION:
2684 additional_flags = 0;
2685 #if defined(HAVE_SYS_QUOTAS)
2686 additional_flags |= FILE_VOLUME_QUOTAS;
2687 #endif
2689 if(lp_nt_acl_support(SNUM(conn))) {
2690 additional_flags |= FILE_PERSISTENT_ACLS;
2693 /* Capabilities are filled in at connection time through STATVFS call */
2694 additional_flags |= conn->fs_capabilities;
2695 additional_flags |= lp_parm_int(conn->params->service,
2696 "share", "fake_fscaps",
2699 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2700 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2701 additional_flags); /* FS ATTRIBUTES */
2703 SIVAL(pdata,4,255); /* Max filename component length */
2704 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2705 and will think we can't do long filenames */
2706 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2707 PTR_DIFF(end_data, pdata+12),
2708 STR_UNICODE);
2709 SIVAL(pdata,8,len);
2710 data_len = 12 + len;
2711 break;
2713 case SMB_QUERY_FS_LABEL_INFO:
2714 case SMB_FS_LABEL_INFORMATION:
2715 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2716 PTR_DIFF(end_data, pdata+4), 0);
2717 data_len = 4 + len;
2718 SIVAL(pdata,0,len);
2719 break;
2721 case SMB_QUERY_FS_VOLUME_INFO:
2722 case SMB_FS_VOLUME_INFORMATION:
2725 * Add volume serial number - hash of a combination of
2726 * the called hostname and the service name.
2728 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2729 (str_checksum(get_local_machine_name())<<16));
2731 /* Max label len is 32 characters. */
2732 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2733 PTR_DIFF(end_data, pdata+18),
2734 STR_UNICODE);
2735 SIVAL(pdata,12,len);
2736 data_len = 18+len;
2738 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2739 (int)strlen(vname),vname, lp_servicename(snum)));
2740 break;
2742 case SMB_QUERY_FS_SIZE_INFO:
2743 case SMB_FS_SIZE_INFORMATION:
2745 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2746 data_len = 24;
2747 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2748 reply_unixerror(req, ERRHRD, ERRgeneral);
2749 return;
2751 block_size = lp_block_size(snum);
2752 if (bsize < block_size) {
2753 uint64_t factor = block_size/bsize;
2754 bsize = block_size;
2755 dsize /= factor;
2756 dfree /= factor;
2758 if (bsize > block_size) {
2759 uint64_t factor = bsize/block_size;
2760 bsize = block_size;
2761 dsize *= factor;
2762 dfree *= factor;
2764 bytes_per_sector = 512;
2765 sectors_per_unit = bsize/bytes_per_sector;
2766 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2767 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2768 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2769 SBIG_UINT(pdata,0,dsize);
2770 SBIG_UINT(pdata,8,dfree);
2771 SIVAL(pdata,16,sectors_per_unit);
2772 SIVAL(pdata,20,bytes_per_sector);
2773 break;
2776 case SMB_FS_FULL_SIZE_INFORMATION:
2778 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2779 data_len = 32;
2780 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2781 reply_unixerror(req, ERRHRD, ERRgeneral);
2782 return;
2784 block_size = lp_block_size(snum);
2785 if (bsize < block_size) {
2786 uint64_t factor = block_size/bsize;
2787 bsize = block_size;
2788 dsize /= factor;
2789 dfree /= factor;
2791 if (bsize > block_size) {
2792 uint64_t factor = bsize/block_size;
2793 bsize = block_size;
2794 dsize *= factor;
2795 dfree *= factor;
2797 bytes_per_sector = 512;
2798 sectors_per_unit = bsize/bytes_per_sector;
2799 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2800 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2801 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2802 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2803 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2804 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2805 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2806 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2807 break;
2810 case SMB_QUERY_FS_DEVICE_INFO:
2811 case SMB_FS_DEVICE_INFORMATION:
2812 data_len = 8;
2813 SIVAL(pdata,0,0); /* dev type */
2814 SIVAL(pdata,4,0); /* characteristics */
2815 break;
2817 #ifdef HAVE_SYS_QUOTAS
2818 case SMB_FS_QUOTA_INFORMATION:
2820 * what we have to send --metze:
2822 * Unknown1: 24 NULL bytes
2823 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2824 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2825 * Quota Flags: 2 byte :
2826 * Unknown3: 6 NULL bytes
2828 * 48 bytes total
2830 * details for Quota Flags:
2832 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2833 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2834 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2835 * 0x0001 Enable Quotas: enable quota for this fs
2839 /* we need to fake up a fsp here,
2840 * because its not send in this call
2842 files_struct fsp;
2843 SMB_NTQUOTA_STRUCT quotas;
2845 ZERO_STRUCT(fsp);
2846 ZERO_STRUCT(quotas);
2848 fsp.conn = conn;
2849 fsp.fnum = -1;
2851 /* access check */
2852 if (conn->server_info->utok.uid != 0) {
2853 DEBUG(0,("set_user_quota: access_denied "
2854 "service [%s] user [%s]\n",
2855 lp_servicename(SNUM(conn)),
2856 conn->server_info->unix_name));
2857 reply_doserror(req, ERRDOS, ERRnoaccess);
2858 return;
2861 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2862 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2863 reply_doserror(req, ERRSRV, ERRerror);
2864 return;
2867 data_len = 48;
2869 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2871 /* Unknown1 24 NULL bytes*/
2872 SBIG_UINT(pdata,0,(uint64_t)0);
2873 SBIG_UINT(pdata,8,(uint64_t)0);
2874 SBIG_UINT(pdata,16,(uint64_t)0);
2876 /* Default Soft Quota 8 bytes */
2877 SBIG_UINT(pdata,24,quotas.softlim);
2879 /* Default Hard Quota 8 bytes */
2880 SBIG_UINT(pdata,32,quotas.hardlim);
2882 /* Quota flag 2 bytes */
2883 SSVAL(pdata,40,quotas.qflags);
2885 /* Unknown3 6 NULL bytes */
2886 SSVAL(pdata,42,0);
2887 SIVAL(pdata,44,0);
2889 break;
2891 #endif /* HAVE_SYS_QUOTAS */
2892 case SMB_FS_OBJECTID_INFORMATION:
2894 unsigned char objid[16];
2895 struct smb_extended_info extended_info;
2896 memcpy(pdata,create_volume_objectid(conn, objid),16);
2897 samba_extended_info_version (&extended_info);
2898 SIVAL(pdata,16,extended_info.samba_magic);
2899 SIVAL(pdata,20,extended_info.samba_version);
2900 SIVAL(pdata,24,extended_info.samba_subversion);
2901 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2902 memcpy(pdata+36,extended_info.samba_version_string,28);
2903 data_len = 64;
2904 break;
2908 * Query the version and capabilities of the CIFS UNIX extensions
2909 * in use.
2912 case SMB_QUERY_CIFS_UNIX_INFO:
2914 bool large_write = lp_min_receive_file_size() &&
2915 !srv_is_signing_active();
2916 bool large_read = !srv_is_signing_active();
2917 int encrypt_caps = 0;
2919 if (!lp_unix_extensions()) {
2920 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2921 return;
2924 switch (conn->encrypt_level) {
2925 case 0:
2926 encrypt_caps = 0;
2927 break;
2928 case 1:
2929 case Auto:
2930 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2931 break;
2932 case Required:
2933 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2934 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2935 large_write = false;
2936 large_read = false;
2937 break;
2940 data_len = 12;
2941 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2942 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2944 /* We have POSIX ACLs, pathname, encryption,
2945 * large read/write, and locking capability. */
2947 SBIG_UINT(pdata,4,((uint64_t)(
2948 CIFS_UNIX_POSIX_ACLS_CAP|
2949 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2950 CIFS_UNIX_FCNTL_LOCKS_CAP|
2951 CIFS_UNIX_EXTATTR_CAP|
2952 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2953 encrypt_caps|
2954 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2955 (large_write ?
2956 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2957 break;
2960 case SMB_QUERY_POSIX_FS_INFO:
2962 int rc;
2963 vfs_statvfs_struct svfs;
2965 if (!lp_unix_extensions()) {
2966 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2967 return;
2970 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2972 if (!rc) {
2973 data_len = 56;
2974 SIVAL(pdata,0,svfs.OptimalTransferSize);
2975 SIVAL(pdata,4,svfs.BlockSize);
2976 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2977 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2978 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2979 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2980 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2981 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2982 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2983 #ifdef EOPNOTSUPP
2984 } else if (rc == EOPNOTSUPP) {
2985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2986 return;
2987 #endif /* EOPNOTSUPP */
2988 } else {
2989 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2990 reply_doserror(req, ERRSRV, ERRerror);
2991 return;
2993 break;
2996 case SMB_QUERY_POSIX_WHOAMI:
2998 uint32_t flags = 0;
2999 uint32_t sid_bytes;
3000 int i;
3002 if (!lp_unix_extensions()) {
3003 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3004 return;
3007 if (max_data_bytes < 40) {
3008 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3009 return;
3012 /* We ARE guest if global_sid_Builtin_Guests is
3013 * in our list of SIDs.
3015 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3016 conn->server_info->ptok)) {
3017 flags |= SMB_WHOAMI_GUEST;
3020 /* We are NOT guest if global_sid_Authenticated_Users
3021 * is in our list of SIDs.
3023 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3024 conn->server_info->ptok)) {
3025 flags &= ~SMB_WHOAMI_GUEST;
3028 /* NOTE: 8 bytes for UID/GID, irrespective of native
3029 * platform size. This matches
3030 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3032 data_len = 4 /* flags */
3033 + 4 /* flag mask */
3034 + 8 /* uid */
3035 + 8 /* gid */
3036 + 4 /* ngroups */
3037 + 4 /* num_sids */
3038 + 4 /* SID bytes */
3039 + 4 /* pad/reserved */
3040 + (conn->server_info->utok.ngroups * 8)
3041 /* groups list */
3042 + (conn->server_info->ptok->num_sids *
3043 SID_MAX_SIZE)
3044 /* SID list */;
3046 SIVAL(pdata, 0, flags);
3047 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3048 SBIG_UINT(pdata, 8,
3049 (uint64_t)conn->server_info->utok.uid);
3050 SBIG_UINT(pdata, 16,
3051 (uint64_t)conn->server_info->utok.gid);
3054 if (data_len >= max_data_bytes) {
3055 /* Potential overflow, skip the GIDs and SIDs. */
3057 SIVAL(pdata, 24, 0); /* num_groups */
3058 SIVAL(pdata, 28, 0); /* num_sids */
3059 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3060 SIVAL(pdata, 36, 0); /* reserved */
3062 data_len = 40;
3063 break;
3066 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3067 SIVAL(pdata, 28, conn->server_info->num_sids);
3069 /* We walk the SID list twice, but this call is fairly
3070 * infrequent, and I don't expect that it's performance
3071 * sensitive -- jpeach
3073 for (i = 0, sid_bytes = 0;
3074 i < conn->server_info->ptok->num_sids; ++i) {
3075 sid_bytes += ndr_size_dom_sid(
3076 &conn->server_info->ptok->user_sids[i],
3077 NULL,
3081 /* SID list byte count */
3082 SIVAL(pdata, 32, sid_bytes);
3084 /* 4 bytes pad/reserved - must be zero */
3085 SIVAL(pdata, 36, 0);
3086 data_len = 40;
3088 /* GID list */
3089 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3090 SBIG_UINT(pdata, data_len,
3091 (uint64_t)conn->server_info->utok.groups[i]);
3092 data_len += 8;
3095 /* SID list */
3096 for (i = 0;
3097 i < conn->server_info->ptok->num_sids; ++i) {
3098 int sid_len = ndr_size_dom_sid(
3099 &conn->server_info->ptok->user_sids[i],
3100 NULL,
3103 sid_linearize(pdata + data_len, sid_len,
3104 &conn->server_info->ptok->user_sids[i]);
3105 data_len += sid_len;
3108 break;
3111 case SMB_MAC_QUERY_FS_INFO:
3113 * Thursby MAC extension... ONLY on NTFS filesystems
3114 * once we do streams then we don't need this
3116 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3117 data_len = 88;
3118 SIVAL(pdata,84,0x100); /* Don't support mac... */
3119 break;
3121 /* drop through */
3122 default:
3123 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3124 return;
3128 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3129 max_data_bytes);
3131 DEBUG( 4, ( "%s info_level = %d\n",
3132 smb_fn_name(req->cmd), info_level) );
3134 return;
3137 /****************************************************************************
3138 Reply to a TRANS2_SETFSINFO (set filesystem info).
3139 ****************************************************************************/
3141 static void call_trans2setfsinfo(connection_struct *conn,
3142 struct smb_request *req,
3143 char **pparams, int total_params,
3144 char **ppdata, int total_data,
3145 unsigned int max_data_bytes)
3147 char *pdata = *ppdata;
3148 char *params = *pparams;
3149 uint16 info_level;
3151 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3153 /* */
3154 if (total_params < 4) {
3155 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3156 total_params));
3157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3158 return;
3161 info_level = SVAL(params,2);
3163 if (IS_IPC(conn)) {
3164 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3165 info_level != SMB_SET_CIFS_UNIX_INFO) {
3166 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3167 "info level (0x%x) on IPC$.\n",
3168 (unsigned int)info_level));
3169 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3170 return;
3174 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3175 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3176 DEBUG(0,("call_trans2setfsinfo: encryption required "
3177 "and info level 0x%x sent.\n",
3178 (unsigned int)info_level));
3179 exit_server_cleanly("encryption required "
3180 "on connection");
3181 return;
3185 switch(info_level) {
3186 case SMB_SET_CIFS_UNIX_INFO:
3188 uint16 client_unix_major;
3189 uint16 client_unix_minor;
3190 uint32 client_unix_cap_low;
3191 uint32 client_unix_cap_high;
3193 if (!lp_unix_extensions()) {
3194 reply_nterror(req,
3195 NT_STATUS_INVALID_LEVEL);
3196 return;
3199 /* There should be 12 bytes of capabilities set. */
3200 if (total_data < 8) {
3201 reply_nterror(
3202 req,
3203 NT_STATUS_INVALID_PARAMETER);
3204 return;
3206 client_unix_major = SVAL(pdata,0);
3207 client_unix_minor = SVAL(pdata,2);
3208 client_unix_cap_low = IVAL(pdata,4);
3209 client_unix_cap_high = IVAL(pdata,8);
3210 /* Just print these values for now. */
3211 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3212 cap_low = 0x%x, cap_high = 0x%x\n",
3213 (unsigned int)client_unix_major,
3214 (unsigned int)client_unix_minor,
3215 (unsigned int)client_unix_cap_low,
3216 (unsigned int)client_unix_cap_high ));
3218 /* Here is where we must switch to posix pathname processing... */
3219 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3220 lp_set_posix_pathnames();
3221 mangle_change_to_posix();
3224 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3225 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3226 /* Client that knows how to do posix locks,
3227 * but not posix open/mkdir operations. Set a
3228 * default type for read/write checks. */
3230 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3233 break;
3236 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3238 NTSTATUS status;
3239 size_t param_len = 0;
3240 size_t data_len = total_data;
3242 if (!lp_unix_extensions()) {
3243 reply_nterror(
3244 req,
3245 NT_STATUS_INVALID_LEVEL);
3246 return;
3249 if (lp_smb_encrypt(SNUM(conn)) == false) {
3250 reply_nterror(
3251 req,
3252 NT_STATUS_NOT_SUPPORTED);
3253 return;
3256 DEBUG( 4,("call_trans2setfsinfo: "
3257 "request transport encryption.\n"));
3259 status = srv_request_encryption_setup(conn,
3260 (unsigned char **)ppdata,
3261 &data_len,
3262 (unsigned char **)pparams,
3263 &param_len);
3265 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3266 !NT_STATUS_IS_OK(status)) {
3267 reply_nterror(req, status);
3268 return;
3271 send_trans2_replies(conn, req,
3272 *pparams,
3273 param_len,
3274 *ppdata,
3275 data_len,
3276 max_data_bytes);
3278 if (NT_STATUS_IS_OK(status)) {
3279 /* Server-side transport
3280 * encryption is now *on*. */
3281 status = srv_encryption_start(conn);
3282 if (!NT_STATUS_IS_OK(status)) {
3283 exit_server_cleanly(
3284 "Failure in setting "
3285 "up encrypted transport");
3288 return;
3291 case SMB_FS_QUOTA_INFORMATION:
3293 files_struct *fsp = NULL;
3294 SMB_NTQUOTA_STRUCT quotas;
3296 ZERO_STRUCT(quotas);
3298 /* access check */
3299 if ((conn->server_info->utok.uid != 0)
3300 ||!CAN_WRITE(conn)) {
3301 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3302 lp_servicename(SNUM(conn)),
3303 conn->server_info->unix_name));
3304 reply_doserror(req, ERRSRV, ERRaccess);
3305 return;
3308 /* note: normaly there're 48 bytes,
3309 * but we didn't use the last 6 bytes for now
3310 * --metze
3312 fsp = file_fsp(req, SVAL(params,0));
3314 if (!check_fsp_ntquota_handle(conn, req,
3315 fsp)) {
3316 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3317 reply_nterror(
3318 req, NT_STATUS_INVALID_HANDLE);
3319 return;
3322 if (total_data < 42) {
3323 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3324 total_data));
3325 reply_nterror(
3326 req,
3327 NT_STATUS_INVALID_PARAMETER);
3328 return;
3331 /* unknown_1 24 NULL bytes in pdata*/
3333 /* the soft quotas 8 bytes (uint64_t)*/
3334 quotas.softlim = (uint64_t)IVAL(pdata,24);
3335 #ifdef LARGE_SMB_OFF_T
3336 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3337 #else /* LARGE_SMB_OFF_T */
3338 if ((IVAL(pdata,28) != 0)&&
3339 ((quotas.softlim != 0xFFFFFFFF)||
3340 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3341 /* more than 32 bits? */
3342 reply_nterror(
3343 req,
3344 NT_STATUS_INVALID_PARAMETER);
3345 return;
3347 #endif /* LARGE_SMB_OFF_T */
3349 /* the hard quotas 8 bytes (uint64_t)*/
3350 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3351 #ifdef LARGE_SMB_OFF_T
3352 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3353 #else /* LARGE_SMB_OFF_T */
3354 if ((IVAL(pdata,36) != 0)&&
3355 ((quotas.hardlim != 0xFFFFFFFF)||
3356 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3357 /* more than 32 bits? */
3358 reply_nterror(
3359 req,
3360 NT_STATUS_INVALID_PARAMETER);
3361 return;
3363 #endif /* LARGE_SMB_OFF_T */
3365 /* quota_flags 2 bytes **/
3366 quotas.qflags = SVAL(pdata,40);
3368 /* unknown_2 6 NULL bytes follow*/
3370 /* now set the quotas */
3371 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3372 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3373 reply_doserror(req, ERRSRV, ERRerror);
3374 return;
3377 break;
3379 default:
3380 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3381 info_level));
3382 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3383 return;
3384 break;
3388 * sending this reply works fine,
3389 * but I'm not sure it's the same
3390 * like windows do...
3391 * --metze
3393 reply_outbuf(req, 10, 0);
3396 #if defined(HAVE_POSIX_ACLS)
3397 /****************************************************************************
3398 Utility function to count the number of entries in a POSIX acl.
3399 ****************************************************************************/
3401 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3403 unsigned int ace_count = 0;
3404 int entry_id = SMB_ACL_FIRST_ENTRY;
3405 SMB_ACL_ENTRY_T entry;
3407 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3408 /* get_next... */
3409 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3410 entry_id = SMB_ACL_NEXT_ENTRY;
3412 ace_count++;
3414 return ace_count;
3417 /****************************************************************************
3418 Utility function to marshall a POSIX acl into wire format.
3419 ****************************************************************************/
3421 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3423 int entry_id = SMB_ACL_FIRST_ENTRY;
3424 SMB_ACL_ENTRY_T entry;
3426 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3427 SMB_ACL_TAG_T tagtype;
3428 SMB_ACL_PERMSET_T permset;
3429 unsigned char perms = 0;
3430 unsigned int own_grp;
3432 /* get_next... */
3433 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3434 entry_id = SMB_ACL_NEXT_ENTRY;
3437 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3438 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3439 return False;
3442 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3443 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3444 return False;
3447 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3448 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3449 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3451 SCVAL(pdata,1,perms);
3453 switch (tagtype) {
3454 case SMB_ACL_USER_OBJ:
3455 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3456 own_grp = (unsigned int)pst->st_uid;
3457 SIVAL(pdata,2,own_grp);
3458 SIVAL(pdata,6,0);
3459 break;
3460 case SMB_ACL_USER:
3462 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3463 if (!puid) {
3464 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3465 return False;
3467 own_grp = (unsigned int)*puid;
3468 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3469 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3470 SIVAL(pdata,2,own_grp);
3471 SIVAL(pdata,6,0);
3472 break;
3474 case SMB_ACL_GROUP_OBJ:
3475 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3476 own_grp = (unsigned int)pst->st_gid;
3477 SIVAL(pdata,2,own_grp);
3478 SIVAL(pdata,6,0);
3479 break;
3480 case SMB_ACL_GROUP:
3482 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3483 if (!pgid) {
3484 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3485 return False;
3487 own_grp = (unsigned int)*pgid;
3488 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3489 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3490 SIVAL(pdata,2,own_grp);
3491 SIVAL(pdata,6,0);
3492 break;
3494 case SMB_ACL_MASK:
3495 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3496 SIVAL(pdata,2,0xFFFFFFFF);
3497 SIVAL(pdata,6,0xFFFFFFFF);
3498 break;
3499 case SMB_ACL_OTHER:
3500 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3501 SIVAL(pdata,2,0xFFFFFFFF);
3502 SIVAL(pdata,6,0xFFFFFFFF);
3503 break;
3504 default:
3505 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3506 return False;
3508 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3511 return True;
3513 #endif
3515 /****************************************************************************
3516 Store the FILE_UNIX_BASIC info.
3517 ****************************************************************************/
3519 static char *store_file_unix_basic(connection_struct *conn,
3520 char *pdata,
3521 files_struct *fsp,
3522 const SMB_STRUCT_STAT *psbuf)
3524 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3525 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3527 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3528 pdata += 8;
3530 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3531 pdata += 8;
3533 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3534 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3535 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3536 pdata += 24;
3538 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3539 SIVAL(pdata,4,0);
3540 pdata += 8;
3542 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3543 SIVAL(pdata,4,0);
3544 pdata += 8;
3546 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3547 pdata += 4;
3549 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3550 SIVAL(pdata,4,0);
3551 pdata += 8;
3553 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3554 SIVAL(pdata,4,0);
3555 pdata += 8;
3557 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3558 pdata += 8;
3560 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3561 SIVAL(pdata,4,0);
3562 pdata += 8;
3564 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3565 SIVAL(pdata,4,0);
3566 pdata += 8;
3568 return pdata;
3571 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3572 * the chflags(2) (or equivalent) flags.
3574 * XXX: this really should be behind the VFS interface. To do this, we would
3575 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3576 * Each VFS module could then implement its own mapping as appropriate for the
3577 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3579 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3580 info2_flags_map[] =
3582 #ifdef UF_NODUMP
3583 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3584 #endif
3586 #ifdef UF_IMMUTABLE
3587 { UF_IMMUTABLE, EXT_IMMUTABLE },
3588 #endif
3590 #ifdef UF_APPEND
3591 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3592 #endif
3594 #ifdef UF_HIDDEN
3595 { UF_HIDDEN, EXT_HIDDEN },
3596 #endif
3598 /* Do not remove. We need to guarantee that this array has at least one
3599 * entry to build on HP-UX.
3601 { 0, 0 }
3605 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3606 uint32 *smb_fflags, uint32 *smb_fmask)
3608 #ifdef HAVE_STAT_ST_FLAGS
3609 int i;
3611 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3612 *smb_fmask |= info2_flags_map[i].smb_fflag;
3613 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3614 *smb_fflags |= info2_flags_map[i].smb_fflag;
3617 #endif /* HAVE_STAT_ST_FLAGS */
3620 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3621 const uint32 smb_fflags,
3622 const uint32 smb_fmask,
3623 int *stat_fflags)
3625 #ifdef HAVE_STAT_ST_FLAGS
3626 uint32 max_fmask = 0;
3627 int i;
3629 *stat_fflags = psbuf->st_flags;
3631 /* For each flags requested in smb_fmask, check the state of the
3632 * corresponding flag in smb_fflags and set or clear the matching
3633 * stat flag.
3636 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3637 max_fmask |= info2_flags_map[i].smb_fflag;
3638 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3639 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3640 *stat_fflags |= info2_flags_map[i].stat_fflag;
3641 } else {
3642 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3647 /* If smb_fmask is asking to set any bits that are not supported by
3648 * our flag mappings, we should fail.
3650 if ((smb_fmask & max_fmask) != smb_fmask) {
3651 return False;
3654 return True;
3655 #else
3656 return False;
3657 #endif /* HAVE_STAT_ST_FLAGS */
3661 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3662 * of file flags and birth (create) time.
3664 static char *store_file_unix_basic_info2(connection_struct *conn,
3665 char *pdata,
3666 files_struct *fsp,
3667 const SMB_STRUCT_STAT *psbuf)
3669 uint32 file_flags = 0;
3670 uint32 flags_mask = 0;
3672 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3674 /* Create (birth) time 64 bit */
3675 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, get_create_timespec(psbuf, False));
3676 pdata += 8;
3678 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3679 SIVAL(pdata, 0, file_flags); /* flags */
3680 SIVAL(pdata, 4, flags_mask); /* mask */
3681 pdata += 8;
3683 return pdata;
3686 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3687 const struct stream_struct *streams,
3688 char *data,
3689 unsigned int max_data_bytes,
3690 unsigned int *data_size)
3692 unsigned int i;
3693 unsigned int ofs = 0;
3695 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3696 unsigned int next_offset;
3697 size_t namelen;
3698 smb_ucs2_t *namebuf;
3700 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3701 streams[i].name, &namelen) ||
3702 namelen <= 2)
3704 return NT_STATUS_INVALID_PARAMETER;
3708 * name_buf is now null-terminated, we need to marshall as not
3709 * terminated
3712 namelen -= 2;
3714 SIVAL(data, ofs+4, namelen);
3715 SOFF_T(data, ofs+8, streams[i].size);
3716 SOFF_T(data, ofs+16, streams[i].alloc_size);
3717 memcpy(data+ofs+24, namebuf, namelen);
3718 TALLOC_FREE(namebuf);
3720 next_offset = ofs + 24 + namelen;
3722 if (i == num_streams-1) {
3723 SIVAL(data, ofs, 0);
3725 else {
3726 unsigned int align = ndr_align_size(next_offset, 8);
3728 memset(data+next_offset, 0, align);
3729 next_offset += align;
3731 SIVAL(data, ofs, next_offset - ofs);
3732 ofs = next_offset;
3735 ofs = next_offset;
3738 *data_size = ofs;
3740 return NT_STATUS_OK;
3743 /****************************************************************************
3744 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3745 ****************************************************************************/
3747 static void call_trans2qpipeinfo(connection_struct *conn,
3748 struct smb_request *req,
3749 unsigned int tran_call,
3750 char **pparams, int total_params,
3751 char **ppdata, int total_data,
3752 unsigned int max_data_bytes)
3754 char *params = *pparams;
3755 char *pdata = *ppdata;
3756 unsigned int data_size = 0;
3757 unsigned int param_size = 2;
3758 uint16 info_level;
3759 files_struct *fsp;
3761 if (!params) {
3762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3763 return;
3766 if (total_params < 4) {
3767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3768 return;
3771 fsp = file_fsp(req, SVAL(params,0));
3772 if (!fsp_is_np(fsp)) {
3773 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3774 return;
3777 info_level = SVAL(params,2);
3779 *pparams = (char *)SMB_REALLOC(*pparams,2);
3780 if (*pparams == NULL) {
3781 reply_nterror(req, NT_STATUS_NO_MEMORY);
3782 return;
3784 params = *pparams;
3785 SSVAL(params,0,0);
3786 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3787 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3788 if (*ppdata == NULL ) {
3789 reply_nterror(req, NT_STATUS_NO_MEMORY);
3790 return;
3792 pdata = *ppdata;
3794 switch (info_level) {
3795 case SMB_FILE_STANDARD_INFORMATION:
3796 memset(pdata,0,24);
3797 SOFF_T(pdata,0,4096LL);
3798 SIVAL(pdata,16,1);
3799 SIVAL(pdata,20,1);
3800 data_size = 24;
3801 break;
3803 default:
3804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3805 return;
3808 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3809 max_data_bytes);
3811 return;
3814 /****************************************************************************
3815 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3816 file name or file id).
3817 ****************************************************************************/
3819 static void call_trans2qfilepathinfo(connection_struct *conn,
3820 struct smb_request *req,
3821 unsigned int tran_call,
3822 char **pparams, int total_params,
3823 char **ppdata, int total_data,
3824 unsigned int max_data_bytes)
3826 char *params = *pparams;
3827 char *pdata = *ppdata;
3828 char *dstart, *dend;
3829 uint16 info_level;
3830 int mode=0;
3831 int nlink;
3832 SMB_OFF_T file_size=0;
3833 uint64_t allocation_size=0;
3834 unsigned int data_size = 0;
3835 unsigned int param_size = 2;
3836 SMB_STRUCT_STAT sbuf;
3837 char *dos_fname = NULL;
3838 char *fname = NULL;
3839 char *fullpathname;
3840 char *base_name;
3841 char *p;
3842 SMB_OFF_T pos = 0;
3843 bool delete_pending = False;
3844 int len;
3845 time_t create_time, mtime, atime;
3846 struct timespec create_time_ts, mtime_ts, atime_ts;
3847 struct timespec write_time_ts;
3848 files_struct *fsp = NULL;
3849 struct file_id fileid;
3850 struct ea_list *ea_list = NULL;
3851 char *lock_data = NULL;
3852 bool ms_dfs_link = false;
3853 TALLOC_CTX *ctx = talloc_tos();
3855 if (!params) {
3856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3857 return;
3860 ZERO_STRUCT(sbuf);
3861 ZERO_STRUCT(write_time_ts);
3863 if (tran_call == TRANSACT2_QFILEINFO) {
3864 if (total_params < 4) {
3865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3866 return;
3869 if (IS_IPC(conn)) {
3870 call_trans2qpipeinfo(conn, req, tran_call,
3871 pparams, total_params,
3872 ppdata, total_data,
3873 max_data_bytes);
3874 return;
3877 fsp = file_fsp(req, SVAL(params,0));
3878 info_level = SVAL(params,2);
3880 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3882 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3883 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3884 return;
3887 /* Initial check for valid fsp ptr. */
3888 if (!check_fsp_open(conn, req, fsp)) {
3889 return;
3892 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3893 if (!fname) {
3894 reply_nterror(req, NT_STATUS_NO_MEMORY);
3895 return;
3898 if(fsp->fake_file_handle) {
3900 * This is actually for the QUOTA_FAKE_FILE --metze
3903 /* We know this name is ok, it's already passed the checks. */
3905 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3907 * This is actually a QFILEINFO on a directory
3908 * handle (returned from an NT SMB). NT5.0 seems
3909 * to do this call. JRA.
3912 if (INFO_LEVEL_IS_UNIX(info_level)) {
3913 /* Always do lstat for UNIX calls. */
3914 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3915 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3916 reply_unixerror(req,ERRDOS,ERRbadpath);
3917 return;
3919 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3920 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3921 reply_unixerror(req, ERRDOS, ERRbadpath);
3922 return;
3925 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3926 get_file_infos(fileid, &delete_pending, &write_time_ts);
3927 } else {
3929 * Original code - this is an open file.
3931 if (!check_fsp(conn, req, fsp)) {
3932 return;
3935 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3936 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3937 reply_unixerror(req, ERRDOS, ERRbadfid);
3938 return;
3940 pos = fsp->fh->position_information;
3941 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3942 get_file_infos(fileid, &delete_pending, &write_time_ts);
3945 } else {
3946 NTSTATUS status = NT_STATUS_OK;
3948 /* qpathinfo */
3949 if (total_params < 7) {
3950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3951 return;
3954 info_level = SVAL(params,0);
3956 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3958 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3960 return;
3963 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3964 total_params - 6,
3965 STR_TERMINATE, &status);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 reply_nterror(req, status);
3968 return;
3971 status = resolve_dfspath(ctx,
3972 conn,
3973 req->flags2 & FLAGS2_DFS_PATHNAMES,
3974 fname,
3975 &fname);
3976 if (!NT_STATUS_IS_OK(status)) {
3977 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3978 reply_botherror(req,
3979 NT_STATUS_PATH_NOT_COVERED,
3980 ERRSRV, ERRbadpath);
3982 reply_nterror(req, status);
3983 return;
3986 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3987 if (!NT_STATUS_IS_OK(status)) {
3988 reply_nterror(req, status);
3989 return;
3991 status = check_name(conn, fname);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3994 reply_nterror(req, status);
3995 return;
3998 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3999 && is_ntfs_stream_name(fname)) {
4000 char *base;
4001 SMB_STRUCT_STAT bsbuf;
4003 status = split_ntfs_stream_name(talloc_tos(), fname,
4004 &base, NULL);
4005 if (!NT_STATUS_IS_OK(status)) {
4006 DEBUG(10, ("create_file_unixpath: "
4007 "split_ntfs_stream_name failed: %s\n",
4008 nt_errstr(status)));
4009 reply_nterror(req, status);
4010 return;
4013 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4015 if (INFO_LEVEL_IS_UNIX(info_level)) {
4016 /* Always do lstat for UNIX calls. */
4017 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4018 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4019 reply_unixerror(req,ERRDOS,ERRbadpath);
4020 return;
4022 } else {
4023 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4024 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4025 reply_unixerror(req,ERRDOS,ERRbadpath);
4026 return;
4030 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4031 get_file_infos(fileid, &delete_pending, NULL);
4032 if (delete_pending) {
4033 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4034 return;
4038 if (INFO_LEVEL_IS_UNIX(info_level)) {
4039 /* Always do lstat for UNIX calls. */
4040 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4041 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4042 reply_unixerror(req, ERRDOS, ERRbadpath);
4043 return;
4046 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4047 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4049 if (!ms_dfs_link) {
4050 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4051 reply_unixerror(req, ERRDOS, ERRbadpath);
4052 return;
4056 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4057 get_file_infos(fileid, &delete_pending, &write_time_ts);
4058 if (delete_pending) {
4059 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4060 return;
4064 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4065 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4066 return;
4069 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4070 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4072 p = strrchr_m(fname,'/');
4073 if (!p)
4074 base_name = fname;
4075 else
4076 base_name = p+1;
4078 if (ms_dfs_link) {
4079 mode = dos_mode_msdfs(conn,fname,&sbuf);
4080 } else {
4081 mode = dos_mode(conn,fname,&sbuf);
4084 nlink = sbuf.st_nlink;
4086 if (nlink && (mode&aDIR)) {
4087 nlink = 1;
4090 if ((nlink > 0) && delete_pending) {
4091 nlink -= 1;
4094 fullpathname = fname;
4095 if (!(mode & aDIR))
4096 file_size = get_file_size_stat(&sbuf);
4098 /* Pull out any data sent here before we realloc. */
4099 switch (info_level) {
4100 case SMB_INFO_QUERY_EAS_FROM_LIST:
4102 /* Pull any EA list from the data portion. */
4103 uint32 ea_size;
4105 if (total_data < 4) {
4106 reply_nterror(
4107 req, NT_STATUS_INVALID_PARAMETER);
4108 return;
4110 ea_size = IVAL(pdata,0);
4112 if (total_data > 0 && ea_size != total_data) {
4113 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4114 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4115 reply_nterror(
4116 req, NT_STATUS_INVALID_PARAMETER);
4117 return;
4120 if (!lp_ea_support(SNUM(conn))) {
4121 reply_doserror(req, ERRDOS,
4122 ERReasnotsupported);
4123 return;
4126 /* Pull out the list of names. */
4127 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4128 if (!ea_list) {
4129 reply_nterror(
4130 req, NT_STATUS_INVALID_PARAMETER);
4131 return;
4133 break;
4136 case SMB_QUERY_POSIX_LOCK:
4138 if (fsp == NULL || fsp->fh->fd == -1) {
4139 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4140 return;
4143 if (total_data != POSIX_LOCK_DATA_SIZE) {
4144 reply_nterror(
4145 req, NT_STATUS_INVALID_PARAMETER);
4146 return;
4149 /* Copy the lock range data. */
4150 lock_data = (char *)TALLOC_MEMDUP(
4151 ctx, pdata, total_data);
4152 if (!lock_data) {
4153 reply_nterror(req, NT_STATUS_NO_MEMORY);
4154 return;
4157 default:
4158 break;
4161 *pparams = (char *)SMB_REALLOC(*pparams,2);
4162 if (*pparams == NULL) {
4163 reply_nterror(req, NT_STATUS_NO_MEMORY);
4164 return;
4166 params = *pparams;
4167 SSVAL(params,0,0);
4168 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4169 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4170 if (*ppdata == NULL ) {
4171 reply_nterror(req, NT_STATUS_NO_MEMORY);
4172 return;
4174 pdata = *ppdata;
4175 dstart = pdata;
4176 dend = dstart + data_size - 1;
4178 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4179 mtime_ts = get_mtimespec(&sbuf);
4180 atime_ts = get_atimespec(&sbuf);
4182 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4184 if (!fsp) {
4185 /* Do we have this path open ? */
4186 files_struct *fsp1;
4187 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4188 fsp1 = file_find_di_first(fileid);
4189 if (fsp1 && fsp1->initial_allocation_size) {
4190 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4194 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4195 mtime_ts = write_time_ts;
4198 if (lp_dos_filetime_resolution(SNUM(conn))) {
4199 dos_filetime_timespec(&create_time_ts);
4200 dos_filetime_timespec(&mtime_ts);
4201 dos_filetime_timespec(&atime_ts);
4204 create_time = convert_timespec_to_time_t(create_time_ts);
4205 mtime = convert_timespec_to_time_t(mtime_ts);
4206 atime = convert_timespec_to_time_t(atime_ts);
4208 /* NT expects the name to be in an exact form of the *full*
4209 filename. See the trans2 torture test */
4210 if (ISDOT(base_name)) {
4211 dos_fname = talloc_strdup(ctx, "\\");
4212 if (!dos_fname) {
4213 reply_nterror(req, NT_STATUS_NO_MEMORY);
4214 return;
4216 } else {
4217 dos_fname = talloc_asprintf(ctx,
4218 "\\%s",
4219 fname);
4220 if (!dos_fname) {
4221 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222 return;
4224 string_replace(dos_fname, '/', '\\');
4227 switch (info_level) {
4228 case SMB_INFO_STANDARD:
4229 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4230 data_size = 22;
4231 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4232 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4233 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4234 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4235 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4236 SSVAL(pdata,l1_attrFile,mode);
4237 break;
4239 case SMB_INFO_QUERY_EA_SIZE:
4241 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4242 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4243 data_size = 26;
4244 srv_put_dos_date2(pdata,0,create_time);
4245 srv_put_dos_date2(pdata,4,atime);
4246 srv_put_dos_date2(pdata,8,mtime); /* write time */
4247 SIVAL(pdata,12,(uint32)file_size);
4248 SIVAL(pdata,16,(uint32)allocation_size);
4249 SSVAL(pdata,20,mode);
4250 SIVAL(pdata,22,ea_size);
4251 break;
4254 case SMB_INFO_IS_NAME_VALID:
4255 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4256 if (tran_call == TRANSACT2_QFILEINFO) {
4257 /* os/2 needs this ? really ?*/
4258 reply_doserror(req, ERRDOS, ERRbadfunc);
4259 return;
4261 data_size = 0;
4262 param_size = 0;
4263 break;
4265 case SMB_INFO_QUERY_EAS_FROM_LIST:
4267 size_t total_ea_len = 0;
4268 struct ea_list *ea_file_list = NULL;
4270 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4272 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4273 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4275 if (!ea_list || (total_ea_len > data_size)) {
4276 data_size = 4;
4277 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4278 break;
4281 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4282 break;
4285 case SMB_INFO_QUERY_ALL_EAS:
4287 /* We have data_size bytes to put EA's into. */
4288 size_t total_ea_len = 0;
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4292 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4293 if (!ea_list || (total_ea_len > data_size)) {
4294 data_size = 4;
4295 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4296 break;
4299 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4300 break;
4303 case SMB_FILE_BASIC_INFORMATION:
4304 case SMB_QUERY_FILE_BASIC_INFO:
4306 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4307 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4308 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4309 } else {
4310 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4311 data_size = 40;
4312 SIVAL(pdata,36,0);
4314 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4315 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4316 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4317 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4318 SIVAL(pdata,32,mode);
4320 DEBUG(5,("SMB_QFBI - "));
4321 DEBUG(5,("create: %s ", ctime(&create_time)));
4322 DEBUG(5,("access: %s ", ctime(&atime)));
4323 DEBUG(5,("write: %s ", ctime(&mtime)));
4324 DEBUG(5,("change: %s ", ctime(&mtime)));
4325 DEBUG(5,("mode: %x\n", mode));
4326 break;
4328 case SMB_FILE_STANDARD_INFORMATION:
4329 case SMB_QUERY_FILE_STANDARD_INFO:
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4332 data_size = 24;
4333 SOFF_T(pdata,0,allocation_size);
4334 SOFF_T(pdata,8,file_size);
4335 SIVAL(pdata,16,nlink);
4336 SCVAL(pdata,20,delete_pending?1:0);
4337 SCVAL(pdata,21,(mode&aDIR)?1:0);
4338 SSVAL(pdata,22,0); /* Padding. */
4339 break;
4341 case SMB_FILE_EA_INFORMATION:
4342 case SMB_QUERY_FILE_EA_INFO:
4344 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4345 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4346 data_size = 4;
4347 SIVAL(pdata,0,ea_size);
4348 break;
4351 /* Get the 8.3 name - used if NT SMB was negotiated. */
4352 case SMB_QUERY_FILE_ALT_NAME_INFO:
4353 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4355 char mangled_name[13];
4356 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4357 if (!name_to_8_3(base_name,mangled_name,
4358 True,conn->params)) {
4359 reply_nterror(
4360 req,
4361 NT_STATUS_NO_MEMORY);
4363 len = srvstr_push(dstart, req->flags2,
4364 pdata+4, mangled_name,
4365 PTR_DIFF(dend, pdata+4),
4366 STR_UNICODE);
4367 data_size = 4 + len;
4368 SIVAL(pdata,0,len);
4369 break;
4372 case SMB_QUERY_FILE_NAME_INFO:
4374 this must be *exactly* right for ACLs on mapped drives to work
4376 len = srvstr_push(dstart, req->flags2,
4377 pdata+4, dos_fname,
4378 PTR_DIFF(dend, pdata+4),
4379 STR_UNICODE);
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4381 data_size = 4 + len;
4382 SIVAL(pdata,0,len);
4383 break;
4385 case SMB_FILE_ALLOCATION_INFORMATION:
4386 case SMB_QUERY_FILE_ALLOCATION_INFO:
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4388 data_size = 8;
4389 SOFF_T(pdata,0,allocation_size);
4390 break;
4392 case SMB_FILE_END_OF_FILE_INFORMATION:
4393 case SMB_QUERY_FILE_END_OF_FILEINFO:
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4395 data_size = 8;
4396 SOFF_T(pdata,0,file_size);
4397 break;
4399 case SMB_QUERY_FILE_ALL_INFO:
4400 case SMB_FILE_ALL_INFORMATION:
4402 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4403 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4404 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4405 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4406 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4407 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4408 SIVAL(pdata,32,mode);
4409 SIVAL(pdata,36,0); /* padding. */
4410 pdata += 40;
4411 SOFF_T(pdata,0,allocation_size);
4412 SOFF_T(pdata,8,file_size);
4413 SIVAL(pdata,16,nlink);
4414 SCVAL(pdata,20,delete_pending);
4415 SCVAL(pdata,21,(mode&aDIR)?1:0);
4416 SSVAL(pdata,22,0);
4417 pdata += 24;
4418 SIVAL(pdata,0,ea_size);
4419 pdata += 4; /* EA info */
4420 len = srvstr_push(dstart, req->flags2,
4421 pdata+4, dos_fname,
4422 PTR_DIFF(dend, pdata+4),
4423 STR_UNICODE);
4424 SIVAL(pdata,0,len);
4425 pdata += 4 + len;
4426 data_size = PTR_DIFF(pdata,(*ppdata));
4427 break;
4429 case SMB_FILE_INTERNAL_INFORMATION:
4430 /* This should be an index number - looks like
4431 dev/ino to me :-)
4433 I think this causes us to fail the IFSKIT
4434 BasicFileInformationTest. -tpot */
4436 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4437 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4438 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4439 data_size = 8;
4440 break;
4442 case SMB_FILE_ACCESS_INFORMATION:
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4444 if (fsp) {
4445 SIVAL(pdata,0,fsp->access_mask);
4446 } else {
4447 /* GENERIC_EXECUTE mapping from Windows */
4448 SIVAL(pdata,0,0x12019F);
4450 data_size = 4;
4451 break;
4453 case SMB_FILE_NAME_INFORMATION:
4454 /* Pathname with leading '\'. */
4456 size_t byte_len;
4457 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4459 SIVAL(pdata,0,byte_len);
4460 data_size = 4 + byte_len;
4461 break;
4464 case SMB_FILE_DISPOSITION_INFORMATION:
4465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4466 data_size = 1;
4467 SCVAL(pdata,0,delete_pending);
4468 break;
4470 case SMB_FILE_POSITION_INFORMATION:
4471 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4472 data_size = 8;
4473 SOFF_T(pdata,0,pos);
4474 break;
4476 case SMB_FILE_MODE_INFORMATION:
4477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4478 SIVAL(pdata,0,mode);
4479 data_size = 4;
4480 break;
4482 case SMB_FILE_ALIGNMENT_INFORMATION:
4483 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4484 SIVAL(pdata,0,0); /* No alignment needed. */
4485 data_size = 4;
4486 break;
4489 * NT4 server just returns "invalid query" to this - if we try
4490 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4491 * want this. JRA.
4493 /* The first statement above is false - verified using Thursby
4494 * client against NT4 -- gcolley.
4496 case SMB_QUERY_FILE_STREAM_INFO:
4497 case SMB_FILE_STREAM_INFORMATION: {
4498 unsigned int num_streams;
4499 struct stream_struct *streams;
4500 NTSTATUS status;
4502 DEBUG(10,("call_trans2qfilepathinfo: "
4503 "SMB_FILE_STREAM_INFORMATION\n"));
4505 status = SMB_VFS_STREAMINFO(
4506 conn, fsp, fname, talloc_tos(),
4507 &num_streams, &streams);
4509 if (!NT_STATUS_IS_OK(status)) {
4510 DEBUG(10, ("could not get stream info: %s\n",
4511 nt_errstr(status)));
4512 reply_nterror(req, status);
4513 return;
4516 status = marshall_stream_info(num_streams, streams,
4517 pdata, max_data_bytes,
4518 &data_size);
4520 if (!NT_STATUS_IS_OK(status)) {
4521 DEBUG(10, ("marshall_stream_info failed: %s\n",
4522 nt_errstr(status)));
4523 reply_nterror(req, status);
4524 return;
4527 TALLOC_FREE(streams);
4529 break;
4531 case SMB_QUERY_COMPRESSION_INFO:
4532 case SMB_FILE_COMPRESSION_INFORMATION:
4533 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4534 SOFF_T(pdata,0,file_size);
4535 SIVAL(pdata,8,0); /* ??? */
4536 SIVAL(pdata,12,0); /* ??? */
4537 data_size = 16;
4538 break;
4540 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4542 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4543 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4544 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4545 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4546 SOFF_T(pdata,32,allocation_size);
4547 SOFF_T(pdata,40,file_size);
4548 SIVAL(pdata,48,mode);
4549 SIVAL(pdata,52,0); /* ??? */
4550 data_size = 56;
4551 break;
4553 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4554 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4555 SIVAL(pdata,0,mode);
4556 SIVAL(pdata,4,0);
4557 data_size = 8;
4558 break;
4561 * CIFS UNIX Extensions.
4564 case SMB_QUERY_FILE_UNIX_BASIC:
4566 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4567 data_size = PTR_DIFF(pdata,(*ppdata));
4570 int i;
4571 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4573 for (i=0; i<100; i++)
4574 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4575 DEBUG(4,("\n"));
4578 break;
4580 case SMB_QUERY_FILE_UNIX_INFO2:
4582 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4583 data_size = PTR_DIFF(pdata,(*ppdata));
4586 int i;
4587 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4589 for (i=0; i<100; i++)
4590 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4591 DEBUG(4,("\n"));
4594 break;
4596 case SMB_QUERY_FILE_UNIX_LINK:
4598 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4600 if (!buffer) {
4601 reply_nterror(req, NT_STATUS_NO_MEMORY);
4602 return;
4605 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4606 #ifdef S_ISLNK
4607 if(!S_ISLNK(sbuf.st_mode)) {
4608 reply_unixerror(req, ERRSRV,
4609 ERRbadlink);
4610 return;
4612 #else
4613 reply_unixerror(req, ERRDOS, ERRbadlink);
4614 return;
4615 #endif
4616 len = SMB_VFS_READLINK(conn,fullpathname,
4617 buffer, PATH_MAX);
4618 if (len == -1) {
4619 reply_unixerror(req, ERRDOS,
4620 ERRnoaccess);
4621 return;
4623 buffer[len] = 0;
4624 len = srvstr_push(dstart, req->flags2,
4625 pdata, buffer,
4626 PTR_DIFF(dend, pdata),
4627 STR_TERMINATE);
4628 pdata += len;
4629 data_size = PTR_DIFF(pdata,(*ppdata));
4631 break;
4634 #if defined(HAVE_POSIX_ACLS)
4635 case SMB_QUERY_POSIX_ACL:
4637 SMB_ACL_T file_acl = NULL;
4638 SMB_ACL_T def_acl = NULL;
4639 uint16 num_file_acls = 0;
4640 uint16 num_def_acls = 0;
4642 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4643 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4644 } else {
4645 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4648 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4649 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4650 fname ));
4651 reply_nterror(
4652 req,
4653 NT_STATUS_NOT_IMPLEMENTED);
4654 return;
4657 if (S_ISDIR(sbuf.st_mode)) {
4658 if (fsp && fsp->is_directory) {
4659 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4660 } else {
4661 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4663 def_acl = free_empty_sys_acl(conn, def_acl);
4666 num_file_acls = count_acl_entries(conn, file_acl);
4667 num_def_acls = count_acl_entries(conn, def_acl);
4669 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4670 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4671 data_size,
4672 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4673 SMB_POSIX_ACL_HEADER_SIZE) ));
4674 if (file_acl) {
4675 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4677 if (def_acl) {
4678 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4680 reply_nterror(
4681 req,
4682 NT_STATUS_BUFFER_TOO_SMALL);
4683 return;
4686 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4687 SSVAL(pdata,2,num_file_acls);
4688 SSVAL(pdata,4,num_def_acls);
4689 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4690 if (file_acl) {
4691 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4693 if (def_acl) {
4694 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4696 reply_nterror(
4697 req, NT_STATUS_INTERNAL_ERROR);
4698 return;
4700 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4701 if (file_acl) {
4702 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4704 if (def_acl) {
4705 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4707 reply_nterror(
4708 req,
4709 NT_STATUS_INTERNAL_ERROR);
4710 return;
4713 if (file_acl) {
4714 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4716 if (def_acl) {
4717 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4719 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4720 break;
4722 #endif
4725 case SMB_QUERY_POSIX_LOCK:
4727 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4728 uint64_t count;
4729 uint64_t offset;
4730 uint32 lock_pid;
4731 enum brl_type lock_type;
4733 if (total_data != POSIX_LOCK_DATA_SIZE) {
4734 reply_nterror(
4735 req, NT_STATUS_INVALID_PARAMETER);
4736 return;
4739 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4740 case POSIX_LOCK_TYPE_READ:
4741 lock_type = READ_LOCK;
4742 break;
4743 case POSIX_LOCK_TYPE_WRITE:
4744 lock_type = WRITE_LOCK;
4745 break;
4746 case POSIX_LOCK_TYPE_UNLOCK:
4747 default:
4748 /* There's no point in asking for an unlock... */
4749 reply_nterror(
4750 req,
4751 NT_STATUS_INVALID_PARAMETER);
4752 return;
4755 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4756 #if defined(HAVE_LONGLONG)
4757 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4758 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4759 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4760 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4761 #else /* HAVE_LONGLONG */
4762 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4763 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4764 #endif /* HAVE_LONGLONG */
4766 status = query_lock(fsp,
4767 &lock_pid,
4768 &count,
4769 &offset,
4770 &lock_type,
4771 POSIX_LOCK);
4773 if (ERROR_WAS_LOCK_DENIED(status)) {
4774 /* Here we need to report who has it locked... */
4775 data_size = POSIX_LOCK_DATA_SIZE;
4777 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4778 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4779 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4780 #if defined(HAVE_LONGLONG)
4781 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4782 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4783 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4784 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4785 #else /* HAVE_LONGLONG */
4786 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4787 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4788 #endif /* HAVE_LONGLONG */
4790 } else if (NT_STATUS_IS_OK(status)) {
4791 /* For success we just return a copy of what we sent
4792 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4793 data_size = POSIX_LOCK_DATA_SIZE;
4794 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4795 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4796 } else {
4797 reply_nterror(req, status);
4798 return;
4800 break;
4803 default:
4804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4805 return;
4808 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4809 max_data_bytes);
4811 return;
4814 /****************************************************************************
4815 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4816 code.
4817 ****************************************************************************/
4819 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4820 connection_struct *conn,
4821 const char *oldname_in,
4822 const char *newname_in)
4824 SMB_STRUCT_STAT sbuf1, sbuf2;
4825 char *last_component_oldname = NULL;
4826 char *last_component_newname = NULL;
4827 char *oldname = NULL;
4828 char *newname = NULL;
4829 NTSTATUS status = NT_STATUS_OK;
4831 ZERO_STRUCT(sbuf1);
4832 ZERO_STRUCT(sbuf2);
4834 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4835 &last_component_oldname, &sbuf1);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 return status;
4840 status = check_name(conn, oldname);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 return status;
4845 /* source must already exist. */
4846 if (!VALID_STAT(sbuf1)) {
4847 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4850 status = unix_convert(ctx, conn, newname_in, False, &newname,
4851 &last_component_newname, &sbuf2);
4852 if (!NT_STATUS_IS_OK(status)) {
4853 return status;
4856 status = check_name(conn, newname);
4857 if (!NT_STATUS_IS_OK(status)) {
4858 return status;
4861 /* Disallow if newname already exists. */
4862 if (VALID_STAT(sbuf2)) {
4863 return NT_STATUS_OBJECT_NAME_COLLISION;
4866 /* No links from a directory. */
4867 if (S_ISDIR(sbuf1.st_mode)) {
4868 return NT_STATUS_FILE_IS_A_DIRECTORY;
4871 /* Ensure this is within the share. */
4872 status = check_reduced_name(conn, oldname);
4873 if (!NT_STATUS_IS_OK(status)) {
4874 return status;
4877 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4879 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4880 status = map_nt_error_from_unix(errno);
4881 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4882 nt_errstr(status), newname, oldname));
4885 return status;
4888 /****************************************************************************
4889 Deal with setting the time from any of the setfilepathinfo functions.
4890 ****************************************************************************/
4892 NTSTATUS smb_set_file_time(connection_struct *conn,
4893 files_struct *fsp,
4894 const char *fname,
4895 const SMB_STRUCT_STAT *psbuf,
4896 struct smb_file_time *ft,
4897 bool setting_write_time)
4899 struct smb_file_time ft_stat;
4900 uint32 action =
4901 FILE_NOTIFY_CHANGE_LAST_ACCESS
4902 |FILE_NOTIFY_CHANGE_LAST_WRITE
4903 |FILE_NOTIFY_CHANGE_CREATION;
4905 if (!VALID_STAT(*psbuf)) {
4906 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4909 /* get some defaults (no modifications) if any info is zero or -1. */
4910 if (null_timespec(ft->create_time)) {
4911 ft->create_time = get_create_timespec(psbuf, lp_fake_dir_create_times(SNUM(conn)));
4912 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4915 if (null_timespec(ft->atime)) {
4916 ft->atime= get_atimespec(psbuf);
4917 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4920 if (null_timespec(ft->mtime)) {
4921 ft->mtime = get_mtimespec(psbuf);
4922 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4925 if (!setting_write_time) {
4926 /* ft->mtime comes from change time, not write time. */
4927 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4930 /* Ensure the resolution is the correct for
4931 * what we can store on this filesystem. */
4933 round_timespec(conn->ts_res, &ft->create_time);
4934 round_timespec(conn->ts_res, &ft->atime);
4935 round_timespec(conn->ts_res, &ft->mtime);
4937 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4938 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4939 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4940 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4941 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4942 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4944 if (setting_write_time) {
4946 * This was a Windows setfileinfo on an open file.
4947 * NT does this a lot. We also need to
4948 * set the time here, as it can be read by
4949 * FindFirst/FindNext and with the patch for bug #2045
4950 * in smbd/fileio.c it ensures that this timestamp is
4951 * kept sticky even after a write. We save the request
4952 * away and will set it on file close and after a write. JRA.
4955 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4956 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4958 if (fsp != NULL) {
4959 if (fsp->base_fsp) {
4960 set_sticky_write_time_fsp(fsp->base_fsp,
4961 ft->mtime);
4962 } else {
4963 set_sticky_write_time_fsp(fsp, ft->mtime);
4965 } else {
4966 set_sticky_write_time_path(conn, fname,
4967 vfs_file_id_from_sbuf(conn, psbuf),
4968 ft->mtime);
4972 ft_stat.create_time = get_create_timespec(psbuf,
4973 lp_fake_dir_create_times(SNUM(conn)));
4974 ft_stat.atime= get_atimespec(psbuf);
4975 ft_stat.mtime = get_mtimespec(psbuf);
4977 round_timespec(conn->ts_res, &ft_stat.create_time);
4978 round_timespec(conn->ts_res, &ft_stat.atime);
4979 round_timespec(conn->ts_res, &ft_stat.mtime);
4981 if (fsp && fsp->base_fsp) {
4982 fname = fsp->base_fsp->fsp_name;
4985 if (timespec_compare(&ft_stat.create_time, &ft->create_time) ||
4986 timespec_compare(&ft_stat.atime, &ft->atime) ||
4987 timespec_compare(&ft_stat.mtime, &ft->mtime)) {
4988 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4989 if(file_ntimes(conn, fname, ft)!=0) {
4990 return map_nt_error_from_unix(errno);
4993 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4995 return NT_STATUS_OK;
4998 /****************************************************************************
4999 Deal with setting the dosmode from any of the setfilepathinfo functions.
5000 ****************************************************************************/
5002 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5003 files_struct *fsp,
5004 const char *fname,
5005 SMB_STRUCT_STAT *psbuf,
5006 uint32 dosmode)
5008 if (!VALID_STAT(*psbuf)) {
5009 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5012 if (fsp) {
5013 if (fsp->base_fsp) {
5014 fname = fsp->base_fsp->fsp_name;
5015 } else {
5016 fname = fsp->fsp_name;
5020 if (dosmode) {
5021 if (S_ISDIR(psbuf->st_mode)) {
5022 dosmode |= aDIR;
5023 } else {
5024 dosmode &= ~aDIR;
5028 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5030 /* check the mode isn't different, before changing it */
5031 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5033 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5034 fname, (unsigned int)dosmode ));
5036 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5037 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5038 fname, strerror(errno)));
5039 return map_nt_error_from_unix(errno);
5042 return NT_STATUS_OK;
5045 /****************************************************************************
5046 Deal with setting the size from any of the setfilepathinfo functions.
5047 ****************************************************************************/
5049 static NTSTATUS smb_set_file_size(connection_struct *conn,
5050 struct smb_request *req,
5051 files_struct *fsp,
5052 const char *fname,
5053 SMB_STRUCT_STAT *psbuf,
5054 SMB_OFF_T size)
5056 NTSTATUS status = NT_STATUS_OK;
5057 files_struct *new_fsp = NULL;
5059 if (!VALID_STAT(*psbuf)) {
5060 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5063 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5065 if (size == get_file_size_stat(psbuf)) {
5066 return NT_STATUS_OK;
5069 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5070 fname, (double)size ));
5072 if (fsp && fsp->fh->fd != -1) {
5073 /* Handle based call. */
5074 if (vfs_set_filelen(fsp, size) == -1) {
5075 return map_nt_error_from_unix(errno);
5077 trigger_write_time_update_immediate(fsp);
5078 return NT_STATUS_OK;
5081 status = SMB_VFS_CREATE_FILE(
5082 conn, /* conn */
5083 req, /* req */
5084 0, /* root_dir_fid */
5085 fname, /* fname */
5086 0, /* create_file_flags */
5087 FILE_WRITE_ATTRIBUTES, /* access_mask */
5088 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5089 FILE_SHARE_DELETE),
5090 FILE_OPEN, /* create_disposition*/
5091 0, /* create_options */
5092 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5093 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5094 0, /* allocation_size */
5095 NULL, /* sd */
5096 NULL, /* ea_list */
5097 &new_fsp, /* result */
5098 NULL, /* pinfo */
5099 psbuf); /* psbuf */
5101 if (!NT_STATUS_IS_OK(status)) {
5102 /* NB. We check for open_was_deferred in the caller. */
5103 return status;
5106 if (vfs_set_filelen(new_fsp, size) == -1) {
5107 status = map_nt_error_from_unix(errno);
5108 close_file(req, new_fsp,NORMAL_CLOSE);
5109 return status;
5112 trigger_write_time_update_immediate(new_fsp);
5113 close_file(req, new_fsp,NORMAL_CLOSE);
5114 return NT_STATUS_OK;
5117 /****************************************************************************
5118 Deal with SMB_INFO_SET_EA.
5119 ****************************************************************************/
5121 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5122 const char *pdata,
5123 int total_data,
5124 files_struct *fsp,
5125 const char *fname)
5127 struct ea_list *ea_list = NULL;
5128 TALLOC_CTX *ctx = NULL;
5129 NTSTATUS status = NT_STATUS_OK;
5131 if (total_data < 10) {
5133 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5134 length. They seem to have no effect. Bug #3212. JRA */
5136 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5137 /* We're done. We only get EA info in this call. */
5138 return NT_STATUS_OK;
5141 return NT_STATUS_INVALID_PARAMETER;
5144 if (IVAL(pdata,0) > total_data) {
5145 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5146 IVAL(pdata,0), (unsigned int)total_data));
5147 return NT_STATUS_INVALID_PARAMETER;
5150 ctx = talloc_tos();
5151 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5152 if (!ea_list) {
5153 return NT_STATUS_INVALID_PARAMETER;
5155 status = set_ea(conn, fsp, fname, ea_list);
5157 return status;
5160 /****************************************************************************
5161 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5162 ****************************************************************************/
5164 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5165 const char *pdata,
5166 int total_data,
5167 files_struct *fsp,
5168 const char *fname,
5169 SMB_STRUCT_STAT *psbuf)
5171 NTSTATUS status = NT_STATUS_OK;
5172 bool delete_on_close;
5173 uint32 dosmode = 0;
5175 if (total_data < 1) {
5176 return NT_STATUS_INVALID_PARAMETER;
5179 if (fsp == NULL) {
5180 return NT_STATUS_INVALID_HANDLE;
5183 delete_on_close = (CVAL(pdata,0) ? True : False);
5184 dosmode = dos_mode(conn, fname, psbuf);
5186 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5187 "delete_on_close = %u\n",
5188 fsp->fsp_name,
5189 (unsigned int)dosmode,
5190 (unsigned int)delete_on_close ));
5192 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 return status;
5198 /* The set is across all open files on this dev/inode pair. */
5199 if (!set_delete_on_close(fsp, delete_on_close,
5200 &conn->server_info->utok)) {
5201 return NT_STATUS_ACCESS_DENIED;
5203 return NT_STATUS_OK;
5206 /****************************************************************************
5207 Deal with SMB_FILE_POSITION_INFORMATION.
5208 ****************************************************************************/
5210 static NTSTATUS smb_file_position_information(connection_struct *conn,
5211 const char *pdata,
5212 int total_data,
5213 files_struct *fsp)
5215 uint64_t position_information;
5217 if (total_data < 8) {
5218 return NT_STATUS_INVALID_PARAMETER;
5221 if (fsp == NULL) {
5222 /* Ignore on pathname based set. */
5223 return NT_STATUS_OK;
5226 position_information = (uint64_t)IVAL(pdata,0);
5227 #ifdef LARGE_SMB_OFF_T
5228 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5229 #else /* LARGE_SMB_OFF_T */
5230 if (IVAL(pdata,4) != 0) {
5231 /* more than 32 bits? */
5232 return NT_STATUS_INVALID_PARAMETER;
5234 #endif /* LARGE_SMB_OFF_T */
5236 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5237 fsp->fsp_name, (double)position_information ));
5238 fsp->fh->position_information = position_information;
5239 return NT_STATUS_OK;
5242 /****************************************************************************
5243 Deal with SMB_FILE_MODE_INFORMATION.
5244 ****************************************************************************/
5246 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5247 const char *pdata,
5248 int total_data)
5250 uint32 mode;
5252 if (total_data < 4) {
5253 return NT_STATUS_INVALID_PARAMETER;
5255 mode = IVAL(pdata,0);
5256 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5257 return NT_STATUS_INVALID_PARAMETER;
5259 return NT_STATUS_OK;
5262 /****************************************************************************
5263 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5264 ****************************************************************************/
5266 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5267 struct smb_request *req,
5268 const char *pdata,
5269 int total_data,
5270 const char *fname)
5272 char *link_target = NULL;
5273 const char *newname = fname;
5274 TALLOC_CTX *ctx = talloc_tos();
5276 /* Set a symbolic link. */
5277 /* Don't allow this if follow links is false. */
5279 if (total_data == 0) {
5280 return NT_STATUS_INVALID_PARAMETER;
5283 if (!lp_symlinks(SNUM(conn))) {
5284 return NT_STATUS_ACCESS_DENIED;
5287 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5288 total_data, STR_TERMINATE);
5290 if (!link_target) {
5291 return NT_STATUS_INVALID_PARAMETER;
5294 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5295 newname, link_target ));
5297 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5298 return map_nt_error_from_unix(errno);
5301 return NT_STATUS_OK;
5304 /****************************************************************************
5305 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5306 ****************************************************************************/
5308 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5309 struct smb_request *req,
5310 const char *pdata, int total_data,
5311 const char *fname)
5313 char *oldname = NULL;
5314 TALLOC_CTX *ctx = talloc_tos();
5315 NTSTATUS status = NT_STATUS_OK;
5317 /* Set a hard link. */
5318 if (total_data == 0) {
5319 return NT_STATUS_INVALID_PARAMETER;
5322 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5323 total_data, STR_TERMINATE, &status);
5324 if (!NT_STATUS_IS_OK(status)) {
5325 return status;
5328 status = resolve_dfspath(ctx, conn,
5329 req->flags2 & FLAGS2_DFS_PATHNAMES,
5330 oldname,
5331 &oldname);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 return status;
5336 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5337 fname, oldname));
5339 return hardlink_internals(ctx, conn, oldname, fname);
5342 /****************************************************************************
5343 Deal with SMB_FILE_RENAME_INFORMATION.
5344 ****************************************************************************/
5346 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5347 struct smb_request *req,
5348 const char *pdata,
5349 int total_data,
5350 files_struct *fsp,
5351 const char *fname)
5353 bool overwrite;
5354 uint32 root_fid;
5355 uint32 len;
5356 char *newname = NULL;
5357 char *base_name = NULL;
5358 bool dest_has_wcard = False;
5359 SMB_STRUCT_STAT sbuf;
5360 char *newname_last_component = NULL;
5361 NTSTATUS status = NT_STATUS_OK;
5362 char *p;
5363 TALLOC_CTX *ctx = talloc_tos();
5365 if (total_data < 13) {
5366 return NT_STATUS_INVALID_PARAMETER;
5369 ZERO_STRUCT(sbuf);
5371 overwrite = (CVAL(pdata,0) ? True : False);
5372 root_fid = IVAL(pdata,4);
5373 len = IVAL(pdata,8);
5375 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5376 return NT_STATUS_INVALID_PARAMETER;
5379 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5380 len, 0, &status,
5381 &dest_has_wcard);
5382 if (!NT_STATUS_IS_OK(status)) {
5383 return status;
5386 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5387 newname));
5389 status = resolve_dfspath_wcard(ctx, conn,
5390 req->flags2 & FLAGS2_DFS_PATHNAMES,
5391 newname,
5392 &newname,
5393 &dest_has_wcard);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 return status;
5398 /* Check the new name has no '/' characters. */
5399 if (strchr_m(newname, '/')) {
5400 return NT_STATUS_NOT_SUPPORTED;
5403 if (fsp && fsp->base_fsp) {
5404 /* newname must be a stream name. */
5405 if (newname[0] != ':') {
5406 return NT_STATUS_NOT_SUPPORTED;
5408 base_name = talloc_asprintf(ctx, "%s%s",
5409 fsp->base_fsp->fsp_name,
5410 newname);
5411 if (!base_name) {
5412 return NT_STATUS_NO_MEMORY;
5414 } else {
5415 /* newname must *not* be a stream name. */
5416 if (is_ntfs_stream_name(newname)) {
5417 return NT_STATUS_NOT_SUPPORTED;
5420 /* Create the base directory. */
5421 base_name = talloc_strdup(ctx, fname);
5422 if (!base_name) {
5423 return NT_STATUS_NO_MEMORY;
5425 p = strrchr_m(base_name, '/');
5426 if (p) {
5427 p[1] = '\0';
5428 } else {
5429 base_name = talloc_strdup(ctx, "./");
5430 if (!base_name) {
5431 return NT_STATUS_NO_MEMORY;
5434 /* Append the new name. */
5435 base_name = talloc_asprintf_append(base_name,
5436 "%s",
5437 newname);
5438 if (!base_name) {
5439 return NT_STATUS_NO_MEMORY;
5442 status = unix_convert(ctx, conn, newname, False,
5443 &newname,
5444 &newname_last_component,
5445 &sbuf);
5447 /* If an error we expect this to be
5448 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5450 if (!NT_STATUS_IS_OK(status)
5451 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5452 status)) {
5453 return status;
5457 if (fsp) {
5458 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5459 fsp->fnum, fsp->fsp_name, base_name ));
5460 status = rename_internals_fsp(conn, fsp, base_name,
5461 newname_last_component, 0,
5462 overwrite);
5463 } else {
5464 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5465 fname, base_name ));
5466 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5467 overwrite, False, dest_has_wcard,
5468 FILE_WRITE_ATTRIBUTES);
5471 return status;
5474 /****************************************************************************
5475 Deal with SMB_SET_POSIX_ACL.
5476 ****************************************************************************/
5478 #if defined(HAVE_POSIX_ACLS)
5479 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5480 const char *pdata,
5481 int total_data,
5482 files_struct *fsp,
5483 const char *fname,
5484 SMB_STRUCT_STAT *psbuf)
5486 uint16 posix_acl_version;
5487 uint16 num_file_acls;
5488 uint16 num_def_acls;
5489 bool valid_file_acls = True;
5490 bool valid_def_acls = True;
5492 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5493 return NT_STATUS_INVALID_PARAMETER;
5495 posix_acl_version = SVAL(pdata,0);
5496 num_file_acls = SVAL(pdata,2);
5497 num_def_acls = SVAL(pdata,4);
5499 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5500 valid_file_acls = False;
5501 num_file_acls = 0;
5504 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5505 valid_def_acls = False;
5506 num_def_acls = 0;
5509 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5510 return NT_STATUS_INVALID_PARAMETER;
5513 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5514 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5515 return NT_STATUS_INVALID_PARAMETER;
5518 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5519 fname ? fname : fsp->fsp_name,
5520 (unsigned int)num_file_acls,
5521 (unsigned int)num_def_acls));
5523 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5524 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5525 return map_nt_error_from_unix(errno);
5528 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5529 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5530 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5531 return map_nt_error_from_unix(errno);
5533 return NT_STATUS_OK;
5535 #endif
5537 /****************************************************************************
5538 Deal with SMB_SET_POSIX_LOCK.
5539 ****************************************************************************/
5541 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5542 struct smb_request *req,
5543 const char *pdata,
5544 int total_data,
5545 files_struct *fsp)
5547 uint64_t count;
5548 uint64_t offset;
5549 uint32 lock_pid;
5550 bool blocking_lock = False;
5551 enum brl_type lock_type;
5553 NTSTATUS status = NT_STATUS_OK;
5555 if (fsp == NULL || fsp->fh->fd == -1) {
5556 return NT_STATUS_INVALID_HANDLE;
5559 if (total_data != POSIX_LOCK_DATA_SIZE) {
5560 return NT_STATUS_INVALID_PARAMETER;
5563 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5564 case POSIX_LOCK_TYPE_READ:
5565 lock_type = READ_LOCK;
5566 break;
5567 case POSIX_LOCK_TYPE_WRITE:
5568 /* Return the right POSIX-mappable error code for files opened read-only. */
5569 if (!fsp->can_write) {
5570 return NT_STATUS_INVALID_HANDLE;
5572 lock_type = WRITE_LOCK;
5573 break;
5574 case POSIX_LOCK_TYPE_UNLOCK:
5575 lock_type = UNLOCK_LOCK;
5576 break;
5577 default:
5578 return NT_STATUS_INVALID_PARAMETER;
5581 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5582 blocking_lock = False;
5583 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5584 blocking_lock = True;
5585 } else {
5586 return NT_STATUS_INVALID_PARAMETER;
5589 if (!lp_blocking_locks(SNUM(conn))) {
5590 blocking_lock = False;
5593 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5594 #if defined(HAVE_LONGLONG)
5595 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5596 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5597 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5598 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5599 #else /* HAVE_LONGLONG */
5600 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5601 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5602 #endif /* HAVE_LONGLONG */
5604 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5605 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5606 fsp->fsp_name,
5607 (unsigned int)lock_type,
5608 (unsigned int)lock_pid,
5609 (double)count,
5610 (double)offset ));
5612 if (lock_type == UNLOCK_LOCK) {
5613 status = do_unlock(smbd_messaging_context(),
5614 fsp,
5615 lock_pid,
5616 count,
5617 offset,
5618 POSIX_LOCK);
5619 } else {
5620 uint32 block_smbpid;
5622 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5623 fsp,
5624 lock_pid,
5625 count,
5626 offset,
5627 lock_type,
5628 POSIX_LOCK,
5629 blocking_lock,
5630 &status,
5631 &block_smbpid,
5632 NULL);
5634 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5636 * A blocking lock was requested. Package up
5637 * this smb into a queued request and push it
5638 * onto the blocking lock queue.
5640 if(push_blocking_lock_request(br_lck,
5641 req,
5642 fsp,
5643 -1, /* infinite timeout. */
5645 lock_pid,
5646 lock_type,
5647 POSIX_LOCK,
5648 offset,
5649 count,
5650 block_smbpid)) {
5651 TALLOC_FREE(br_lck);
5652 return status;
5655 TALLOC_FREE(br_lck);
5658 return status;
5661 /****************************************************************************
5662 Deal with SMB_INFO_STANDARD.
5663 ****************************************************************************/
5665 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5666 const char *pdata,
5667 int total_data,
5668 files_struct *fsp,
5669 const char *fname,
5670 const SMB_STRUCT_STAT *psbuf)
5672 struct smb_file_time ft;
5673 ZERO_STRUCT(ft);
5675 if (total_data < 12) {
5676 return NT_STATUS_INVALID_PARAMETER;
5679 /* create time */
5680 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
5682 /* access time */
5683 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
5685 /* write time */
5686 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
5688 DEBUG(10,("smb_set_info_standard: file %s\n",
5689 fname ? fname : fsp->fsp_name ));
5691 return smb_set_file_time(conn,
5692 fsp,
5693 fname,
5694 psbuf,
5695 &ft,
5696 true);
5699 /****************************************************************************
5700 Deal with SMB_SET_FILE_BASIC_INFO.
5701 ****************************************************************************/
5703 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5704 const char *pdata,
5705 int total_data,
5706 files_struct *fsp,
5707 const char *fname,
5708 SMB_STRUCT_STAT *psbuf)
5710 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5711 struct timespec write_time;
5712 struct timespec changed_time;
5713 struct smb_file_time ft;
5714 uint32 dosmode = 0;
5715 NTSTATUS status = NT_STATUS_OK;
5716 bool setting_write_time = true;
5718 ZERO_STRUCT(ft);
5720 if (total_data < 36) {
5721 return NT_STATUS_INVALID_PARAMETER;
5724 /* Set the attributes */
5725 dosmode = IVAL(pdata,32);
5726 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5727 if (!NT_STATUS_IS_OK(status)) {
5728 return status;
5731 /* access time */
5732 ft.atime = interpret_long_date(pdata+8);
5734 write_time = interpret_long_date(pdata+16);
5735 changed_time = interpret_long_date(pdata+24);
5737 /* mtime */
5738 ft.mtime = timespec_min(&write_time, &changed_time);
5740 /* create time */
5741 ft.create_time = interpret_long_date(pdata);
5743 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5744 !null_timespec(write_time)) {
5745 ft.mtime = write_time;
5748 /* Prefer a defined time to an undefined one. */
5749 if (null_timespec(ft.mtime)) {
5750 if (null_timespec(write_time)) {
5751 ft.mtime = changed_time;
5752 setting_write_time = false;
5753 } else {
5754 ft.mtime = write_time;
5758 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5759 fname ? fname : fsp->fsp_name ));
5761 return smb_set_file_time(conn,
5762 fsp,
5763 fname,
5764 psbuf,
5765 &ft,
5766 setting_write_time);
5769 /****************************************************************************
5770 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5771 ****************************************************************************/
5773 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5774 struct smb_request *req,
5775 const char *pdata,
5776 int total_data,
5777 files_struct *fsp,
5778 const char *fname,
5779 SMB_STRUCT_STAT *psbuf)
5781 uint64_t allocation_size = 0;
5782 NTSTATUS status = NT_STATUS_OK;
5783 files_struct *new_fsp = NULL;
5785 if (!VALID_STAT(*psbuf)) {
5786 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5789 if (total_data < 8) {
5790 return NT_STATUS_INVALID_PARAMETER;
5793 allocation_size = (uint64_t)IVAL(pdata,0);
5794 #ifdef LARGE_SMB_OFF_T
5795 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5796 #else /* LARGE_SMB_OFF_T */
5797 if (IVAL(pdata,4) != 0) {
5798 /* more than 32 bits? */
5799 return NT_STATUS_INVALID_PARAMETER;
5801 #endif /* LARGE_SMB_OFF_T */
5803 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5804 fname, (double)allocation_size ));
5806 if (allocation_size) {
5807 allocation_size = smb_roundup(conn, allocation_size);
5810 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5811 fname, (double)allocation_size ));
5813 if (fsp && fsp->fh->fd != -1) {
5814 /* Open file handle. */
5815 /* Only change if needed. */
5816 if (allocation_size != get_file_size_stat(psbuf)) {
5817 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5818 return map_nt_error_from_unix(errno);
5821 /* But always update the time. */
5823 * This is equivalent to a write. Ensure it's seen immediately
5824 * if there are no pending writes.
5826 trigger_write_time_update_immediate(fsp);
5827 return NT_STATUS_OK;
5830 /* Pathname or stat or directory file. */
5832 status = SMB_VFS_CREATE_FILE(
5833 conn, /* conn */
5834 req, /* req */
5835 0, /* root_dir_fid */
5836 fname, /* fname */
5837 0, /* create_file_flags */
5838 FILE_WRITE_DATA, /* access_mask */
5839 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5840 FILE_SHARE_DELETE),
5841 FILE_OPEN, /* create_disposition*/
5842 0, /* create_options */
5843 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5844 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5845 0, /* allocation_size */
5846 NULL, /* sd */
5847 NULL, /* ea_list */
5848 &new_fsp, /* result */
5849 NULL, /* pinfo */
5850 psbuf); /* psbuf */
5852 if (!NT_STATUS_IS_OK(status)) {
5853 /* NB. We check for open_was_deferred in the caller. */
5854 return status;
5857 /* Only change if needed. */
5858 if (allocation_size != get_file_size_stat(psbuf)) {
5859 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5860 status = map_nt_error_from_unix(errno);
5861 close_file(req, new_fsp, NORMAL_CLOSE);
5862 return status;
5866 /* Changing the allocation size should set the last mod time. */
5868 * This is equivalent to a write. Ensure it's seen immediately
5869 * if there are no pending writes.
5871 trigger_write_time_update_immediate(new_fsp);
5873 close_file(req, new_fsp, NORMAL_CLOSE);
5874 return NT_STATUS_OK;
5877 /****************************************************************************
5878 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5879 ****************************************************************************/
5881 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5882 struct smb_request *req,
5883 const char *pdata,
5884 int total_data,
5885 files_struct *fsp,
5886 const char *fname,
5887 SMB_STRUCT_STAT *psbuf)
5889 SMB_OFF_T size;
5891 if (total_data < 8) {
5892 return NT_STATUS_INVALID_PARAMETER;
5895 size = IVAL(pdata,0);
5896 #ifdef LARGE_SMB_OFF_T
5897 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5898 #else /* LARGE_SMB_OFF_T */
5899 if (IVAL(pdata,4) != 0) {
5900 /* more than 32 bits? */
5901 return NT_STATUS_INVALID_PARAMETER;
5903 #endif /* LARGE_SMB_OFF_T */
5904 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5905 "file %s to %.0f\n", fname, (double)size ));
5907 return smb_set_file_size(conn, req,
5908 fsp,
5909 fname,
5910 psbuf,
5911 size);
5914 /****************************************************************************
5915 Allow a UNIX info mknod.
5916 ****************************************************************************/
5918 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5919 const char *pdata,
5920 int total_data,
5921 const char *fname,
5922 SMB_STRUCT_STAT *psbuf)
5924 uint32 file_type = IVAL(pdata,56);
5925 #if defined(HAVE_MAKEDEV)
5926 uint32 dev_major = IVAL(pdata,60);
5927 uint32 dev_minor = IVAL(pdata,68);
5928 #endif
5929 SMB_DEV_T dev = (SMB_DEV_T)0;
5930 uint32 raw_unixmode = IVAL(pdata,84);
5931 NTSTATUS status;
5932 mode_t unixmode;
5934 if (total_data < 100) {
5935 return NT_STATUS_INVALID_PARAMETER;
5938 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5939 if (!NT_STATUS_IS_OK(status)) {
5940 return status;
5943 #if defined(HAVE_MAKEDEV)
5944 dev = makedev(dev_major, dev_minor);
5945 #endif
5947 switch (file_type) {
5948 #if defined(S_IFIFO)
5949 case UNIX_TYPE_FIFO:
5950 unixmode |= S_IFIFO;
5951 break;
5952 #endif
5953 #if defined(S_IFSOCK)
5954 case UNIX_TYPE_SOCKET:
5955 unixmode |= S_IFSOCK;
5956 break;
5957 #endif
5958 #if defined(S_IFCHR)
5959 case UNIX_TYPE_CHARDEV:
5960 unixmode |= S_IFCHR;
5961 break;
5962 #endif
5963 #if defined(S_IFBLK)
5964 case UNIX_TYPE_BLKDEV:
5965 unixmode |= S_IFBLK;
5966 break;
5967 #endif
5968 default:
5969 return NT_STATUS_INVALID_PARAMETER;
5972 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5973 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5975 /* Ok - do the mknod. */
5976 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5977 return map_nt_error_from_unix(errno);
5980 /* If any of the other "set" calls fail we
5981 * don't want to end up with a half-constructed mknod.
5984 if (lp_inherit_perms(SNUM(conn))) {
5985 char *parent;
5986 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5987 return NT_STATUS_NO_MEMORY;
5989 inherit_access_posix_acl(conn, parent, fname, unixmode);
5990 TALLOC_FREE(parent);
5993 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5994 status = map_nt_error_from_unix(errno);
5995 SMB_VFS_UNLINK(conn,fname);
5996 return status;
5998 return NT_STATUS_OK;
6001 /****************************************************************************
6002 Deal with SMB_SET_FILE_UNIX_BASIC.
6003 ****************************************************************************/
6005 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6006 struct smb_request *req,
6007 const char *pdata,
6008 int total_data,
6009 files_struct *fsp,
6010 const char *fname,
6011 SMB_STRUCT_STAT *psbuf)
6013 struct smb_file_time ft;
6014 uint32 raw_unixmode;
6015 mode_t unixmode;
6016 SMB_OFF_T size = 0;
6017 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6018 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6019 NTSTATUS status = NT_STATUS_OK;
6020 bool delete_on_fail = False;
6021 enum perm_type ptype;
6022 files_struct *all_fsps = NULL;
6023 bool modify_mtime = true;
6024 struct file_id id;
6026 ZERO_STRUCT(ft);
6028 if (total_data < 100) {
6029 return NT_STATUS_INVALID_PARAMETER;
6032 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6033 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6034 size=IVAL(pdata,0); /* first 8 Bytes are size */
6035 #ifdef LARGE_SMB_OFF_T
6036 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6037 #else /* LARGE_SMB_OFF_T */
6038 if (IVAL(pdata,4) != 0) {
6039 /* more than 32 bits? */
6040 return NT_STATUS_INVALID_PARAMETER;
6042 #endif /* LARGE_SMB_OFF_T */
6045 ft.atime = interpret_long_date(pdata+24); /* access_time */
6046 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6047 set_owner = (uid_t)IVAL(pdata,40);
6048 set_grp = (gid_t)IVAL(pdata,48);
6049 raw_unixmode = IVAL(pdata,84);
6051 if (VALID_STAT(*psbuf)) {
6052 if (S_ISDIR(psbuf->st_mode)) {
6053 ptype = PERM_EXISTING_DIR;
6054 } else {
6055 ptype = PERM_EXISTING_FILE;
6057 } else {
6058 ptype = PERM_NEW_FILE;
6061 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6062 if (!NT_STATUS_IS_OK(status)) {
6063 return status;
6066 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6067 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6068 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6070 if (!VALID_STAT(*psbuf)) {
6072 * The only valid use of this is to create character and block
6073 * devices, and named pipes. This is deprecated (IMHO) and
6074 * a new info level should be used for mknod. JRA.
6077 status = smb_unix_mknod(conn,
6078 pdata,
6079 total_data,
6080 fname,
6081 psbuf);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 return status;
6086 /* Ensure we don't try and change anything else. */
6087 raw_unixmode = SMB_MODE_NO_CHANGE;
6088 size = get_file_size_stat(psbuf);
6089 ft.atime = get_atimespec(psbuf);
6090 ft.mtime = get_mtimespec(psbuf);
6092 * We continue here as we might want to change the
6093 * owner uid/gid.
6095 delete_on_fail = True;
6098 #if 1
6099 /* Horrible backwards compatibility hack as an old server bug
6100 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6101 * */
6103 if (!size) {
6104 size = get_file_size_stat(psbuf);
6106 #endif
6109 * Deal with the UNIX specific mode set.
6112 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6113 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6114 (unsigned int)unixmode, fname ));
6115 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6116 return map_nt_error_from_unix(errno);
6121 * Deal with the UNIX specific uid set.
6124 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6125 int ret;
6127 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6128 (unsigned int)set_owner, fname ));
6130 if (S_ISLNK(psbuf->st_mode)) {
6131 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6132 } else {
6133 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6136 if (ret != 0) {
6137 status = map_nt_error_from_unix(errno);
6138 if (delete_on_fail) {
6139 SMB_VFS_UNLINK(conn,fname);
6141 return status;
6146 * Deal with the UNIX specific gid set.
6149 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6150 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6151 (unsigned int)set_owner, fname ));
6152 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6153 status = map_nt_error_from_unix(errno);
6154 if (delete_on_fail) {
6155 SMB_VFS_UNLINK(conn,fname);
6157 return status;
6161 /* Deal with any size changes. */
6163 status = smb_set_file_size(conn, req,
6164 fsp,
6165 fname,
6166 psbuf,
6167 size);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 return status;
6172 /* Deal with any time changes. */
6173 id = vfs_file_id_from_sbuf(conn, psbuf);
6174 for(all_fsps = file_find_di_first(id); all_fsps;
6175 all_fsps = file_find_di_next(all_fsps)) {
6177 * We're setting the time explicitly for UNIX.
6178 * Cancel any pending changes over all handles.
6180 all_fsps->update_write_time_on_close = false;
6181 TALLOC_FREE(all_fsps->update_write_time_event);
6185 * Override the "setting_write_time"
6186 * parameter here as it almost does what
6187 * we need. Just remember if we modified
6188 * mtime and send the notify ourselves.
6190 if (null_timespec(ft.mtime)) {
6191 modify_mtime = false;
6194 status = smb_set_file_time(conn,
6195 fsp,
6196 fname,
6197 psbuf,
6198 &ft,
6199 false);
6200 if (modify_mtime) {
6201 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6202 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6204 return status;
6207 /****************************************************************************
6208 Deal with SMB_SET_FILE_UNIX_INFO2.
6209 ****************************************************************************/
6211 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6212 struct smb_request *req,
6213 const char *pdata,
6214 int total_data,
6215 files_struct *fsp,
6216 const char *fname,
6217 SMB_STRUCT_STAT *psbuf)
6219 NTSTATUS status;
6220 uint32 smb_fflags;
6221 uint32 smb_fmask;
6223 if (total_data < 116) {
6224 return NT_STATUS_INVALID_PARAMETER;
6227 /* Start by setting all the fields that are common between UNIX_BASIC
6228 * and UNIX_INFO2.
6230 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6231 fsp, fname, psbuf);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 return status;
6236 smb_fflags = IVAL(pdata, 108);
6237 smb_fmask = IVAL(pdata, 112);
6239 /* NB: We should only attempt to alter the file flags if the client
6240 * sends a non-zero mask.
6242 if (smb_fmask != 0) {
6243 int stat_fflags = 0;
6245 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6246 &stat_fflags)) {
6247 /* Client asked to alter a flag we don't understand. */
6248 return NT_STATUS_INVALID_PARAMETER;
6251 if (fsp && fsp->fh->fd != -1) {
6252 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6253 return NT_STATUS_NOT_SUPPORTED;
6254 } else {
6255 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6256 return map_nt_error_from_unix(errno);
6261 /* XXX: need to add support for changing the create_time here. You
6262 * can do this for paths on Darwin with setattrlist(2). The right way
6263 * to hook this up is probably by extending the VFS utimes interface.
6266 return NT_STATUS_OK;
6269 /****************************************************************************
6270 Create a directory with POSIX semantics.
6271 ****************************************************************************/
6273 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6274 struct smb_request *req,
6275 char **ppdata,
6276 int total_data,
6277 const char *fname,
6278 SMB_STRUCT_STAT *psbuf,
6279 int *pdata_return_size)
6281 NTSTATUS status = NT_STATUS_OK;
6282 uint32 raw_unixmode = 0;
6283 uint32 mod_unixmode = 0;
6284 mode_t unixmode = (mode_t)0;
6285 files_struct *fsp = NULL;
6286 uint16 info_level_return = 0;
6287 int info;
6288 char *pdata = *ppdata;
6290 if (total_data < 18) {
6291 return NT_STATUS_INVALID_PARAMETER;
6294 raw_unixmode = IVAL(pdata,8);
6295 /* Next 4 bytes are not yet defined. */
6297 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6298 if (!NT_STATUS_IS_OK(status)) {
6299 return status;
6302 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6304 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6305 fname, (unsigned int)unixmode ));
6307 status = SMB_VFS_CREATE_FILE(
6308 conn, /* conn */
6309 req, /* req */
6310 0, /* root_dir_fid */
6311 fname, /* fname */
6312 0, /* create_file_flags */
6313 FILE_READ_ATTRIBUTES, /* access_mask */
6314 FILE_SHARE_NONE, /* share_access */
6315 FILE_CREATE, /* create_disposition*/
6316 FILE_DIRECTORY_FILE, /* create_options */
6317 mod_unixmode, /* file_attributes */
6318 0, /* oplock_request */
6319 0, /* allocation_size */
6320 NULL, /* sd */
6321 NULL, /* ea_list */
6322 &fsp, /* result */
6323 &info, /* pinfo */
6324 psbuf); /* psbuf */
6326 if (NT_STATUS_IS_OK(status)) {
6327 close_file(req, fsp, NORMAL_CLOSE);
6330 info_level_return = SVAL(pdata,16);
6332 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6333 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6334 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6335 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6336 } else {
6337 *pdata_return_size = 12;
6340 /* Realloc the data size */
6341 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6342 if (*ppdata == NULL) {
6343 *pdata_return_size = 0;
6344 return NT_STATUS_NO_MEMORY;
6346 pdata = *ppdata;
6348 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6349 SSVAL(pdata,2,0); /* No fnum. */
6350 SIVAL(pdata,4,info); /* Was directory created. */
6352 switch (info_level_return) {
6353 case SMB_QUERY_FILE_UNIX_BASIC:
6354 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6355 SSVAL(pdata,10,0); /* Padding. */
6356 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6357 break;
6358 case SMB_QUERY_FILE_UNIX_INFO2:
6359 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6360 SSVAL(pdata,10,0); /* Padding. */
6361 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6362 break;
6363 default:
6364 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6365 SSVAL(pdata,10,0); /* Padding. */
6366 break;
6369 return status;
6372 /****************************************************************************
6373 Open/Create a file with POSIX semantics.
6374 ****************************************************************************/
6376 static NTSTATUS smb_posix_open(connection_struct *conn,
6377 struct smb_request *req,
6378 char **ppdata,
6379 int total_data,
6380 const char *fname,
6381 SMB_STRUCT_STAT *psbuf,
6382 int *pdata_return_size)
6384 bool extended_oplock_granted = False;
6385 char *pdata = *ppdata;
6386 uint32 flags = 0;
6387 uint32 wire_open_mode = 0;
6388 uint32 raw_unixmode = 0;
6389 uint32 mod_unixmode = 0;
6390 uint32 create_disp = 0;
6391 uint32 access_mask = 0;
6392 uint32 create_options = 0;
6393 NTSTATUS status = NT_STATUS_OK;
6394 mode_t unixmode = (mode_t)0;
6395 files_struct *fsp = NULL;
6396 int oplock_request = 0;
6397 int info = 0;
6398 uint16 info_level_return = 0;
6400 if (total_data < 18) {
6401 return NT_STATUS_INVALID_PARAMETER;
6404 flags = IVAL(pdata,0);
6405 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6406 if (oplock_request) {
6407 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6410 wire_open_mode = IVAL(pdata,4);
6412 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6413 return smb_posix_mkdir(conn, req,
6414 ppdata,
6415 total_data,
6416 fname,
6417 psbuf,
6418 pdata_return_size);
6421 switch (wire_open_mode & SMB_ACCMODE) {
6422 case SMB_O_RDONLY:
6423 access_mask = FILE_READ_DATA;
6424 break;
6425 case SMB_O_WRONLY:
6426 access_mask = FILE_WRITE_DATA;
6427 break;
6428 case SMB_O_RDWR:
6429 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6430 break;
6431 default:
6432 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6433 (unsigned int)wire_open_mode ));
6434 return NT_STATUS_INVALID_PARAMETER;
6437 wire_open_mode &= ~SMB_ACCMODE;
6439 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6440 create_disp = FILE_CREATE;
6441 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6442 create_disp = FILE_OVERWRITE_IF;
6443 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6444 create_disp = FILE_OPEN_IF;
6445 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6446 create_disp = FILE_OPEN;
6447 } else {
6448 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6449 (unsigned int)wire_open_mode ));
6450 return NT_STATUS_INVALID_PARAMETER;
6453 raw_unixmode = IVAL(pdata,8);
6454 /* Next 4 bytes are not yet defined. */
6456 status = unix_perms_from_wire(conn,
6457 psbuf,
6458 raw_unixmode,
6459 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6460 &unixmode);
6462 if (!NT_STATUS_IS_OK(status)) {
6463 return status;
6466 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6468 if (wire_open_mode & SMB_O_SYNC) {
6469 create_options |= FILE_WRITE_THROUGH;
6471 if (wire_open_mode & SMB_O_APPEND) {
6472 access_mask |= FILE_APPEND_DATA;
6474 if (wire_open_mode & SMB_O_DIRECT) {
6475 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6478 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6479 fname,
6480 (unsigned int)wire_open_mode,
6481 (unsigned int)unixmode ));
6483 status = SMB_VFS_CREATE_FILE(
6484 conn, /* conn */
6485 req, /* req */
6486 0, /* root_dir_fid */
6487 fname, /* fname */
6488 0, /* create_file_flags */
6489 access_mask, /* access_mask */
6490 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6491 FILE_SHARE_DELETE),
6492 create_disp, /* create_disposition*/
6493 FILE_NON_DIRECTORY_FILE, /* create_options */
6494 mod_unixmode, /* file_attributes */
6495 oplock_request, /* oplock_request */
6496 0, /* allocation_size */
6497 NULL, /* sd */
6498 NULL, /* ea_list */
6499 &fsp, /* result */
6500 &info, /* pinfo */
6501 psbuf); /* psbuf */
6503 if (!NT_STATUS_IS_OK(status)) {
6504 return status;
6507 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6508 extended_oplock_granted = True;
6511 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6512 extended_oplock_granted = True;
6515 info_level_return = SVAL(pdata,16);
6517 /* Allocate the correct return size. */
6519 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6520 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6521 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6522 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6523 } else {
6524 *pdata_return_size = 12;
6527 /* Realloc the data size */
6528 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6529 if (*ppdata == NULL) {
6530 close_file(req, fsp, ERROR_CLOSE);
6531 *pdata_return_size = 0;
6532 return NT_STATUS_NO_MEMORY;
6534 pdata = *ppdata;
6536 if (extended_oplock_granted) {
6537 if (flags & REQUEST_BATCH_OPLOCK) {
6538 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6539 } else {
6540 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6542 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6543 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6544 } else {
6545 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6548 SSVAL(pdata,2,fsp->fnum);
6549 SIVAL(pdata,4,info); /* Was file created etc. */
6551 switch (info_level_return) {
6552 case SMB_QUERY_FILE_UNIX_BASIC:
6553 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6554 SSVAL(pdata,10,0); /* padding. */
6555 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6556 break;
6557 case SMB_QUERY_FILE_UNIX_INFO2:
6558 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6559 SSVAL(pdata,10,0); /* padding. */
6560 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6561 break;
6562 default:
6563 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6564 SSVAL(pdata,10,0); /* padding. */
6565 break;
6567 return NT_STATUS_OK;
6570 /****************************************************************************
6571 Delete a file with POSIX semantics.
6572 ****************************************************************************/
6574 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6575 struct smb_request *req,
6576 const char *pdata,
6577 int total_data,
6578 const char *fname,
6579 SMB_STRUCT_STAT *psbuf)
6581 NTSTATUS status = NT_STATUS_OK;
6582 files_struct *fsp = NULL;
6583 uint16 flags = 0;
6584 char del = 1;
6585 int info = 0;
6586 int create_options = 0;
6587 int i;
6588 struct share_mode_lock *lck = NULL;
6590 if (total_data < 2) {
6591 return NT_STATUS_INVALID_PARAMETER;
6594 flags = SVAL(pdata,0);
6596 if (!VALID_STAT(*psbuf)) {
6597 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6600 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6601 !VALID_STAT_OF_DIR(*psbuf)) {
6602 return NT_STATUS_NOT_A_DIRECTORY;
6605 DEBUG(10,("smb_posix_unlink: %s %s\n",
6606 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6607 fname));
6609 if (VALID_STAT_OF_DIR(*psbuf)) {
6610 create_options |= FILE_DIRECTORY_FILE;
6613 status = SMB_VFS_CREATE_FILE(
6614 conn, /* conn */
6615 req, /* req */
6616 0, /* root_dir_fid */
6617 fname, /* fname */
6618 0, /* create_file_flags */
6619 DELETE_ACCESS, /* access_mask */
6620 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6621 FILE_SHARE_DELETE),
6622 FILE_OPEN, /* create_disposition*/
6623 create_options, /* create_options */
6624 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6625 0, /* oplock_request */
6626 0, /* allocation_size */
6627 NULL, /* sd */
6628 NULL, /* ea_list */
6629 &fsp, /* result */
6630 &info, /* pinfo */
6631 psbuf); /* psbuf */
6633 if (!NT_STATUS_IS_OK(status)) {
6634 return status;
6638 * Don't lie to client. If we can't really delete due to
6639 * non-POSIX opens return SHARING_VIOLATION.
6642 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6643 NULL);
6644 if (lck == NULL) {
6645 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6646 "lock for file %s\n", fsp->fsp_name));
6647 close_file(req, fsp, NORMAL_CLOSE);
6648 return NT_STATUS_INVALID_PARAMETER;
6652 * See if others still have the file open. If this is the case, then
6653 * don't delete. If all opens are POSIX delete we can set the delete
6654 * on close disposition.
6656 for (i=0; i<lck->num_share_modes; i++) {
6657 struct share_mode_entry *e = &lck->share_modes[i];
6658 if (is_valid_share_mode_entry(e)) {
6659 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6660 continue;
6662 /* Fail with sharing violation. */
6663 close_file(req, fsp, NORMAL_CLOSE);
6664 TALLOC_FREE(lck);
6665 return NT_STATUS_SHARING_VIOLATION;
6670 * Set the delete on close.
6672 status = smb_set_file_disposition_info(conn,
6673 &del,
6675 fsp,
6676 fname,
6677 psbuf);
6679 if (!NT_STATUS_IS_OK(status)) {
6680 close_file(req, fsp, NORMAL_CLOSE);
6681 TALLOC_FREE(lck);
6682 return status;
6684 TALLOC_FREE(lck);
6685 return close_file(req, fsp, NORMAL_CLOSE);
6688 /****************************************************************************
6689 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6690 ****************************************************************************/
6692 static void call_trans2setfilepathinfo(connection_struct *conn,
6693 struct smb_request *req,
6694 unsigned int tran_call,
6695 char **pparams, int total_params,
6696 char **ppdata, int total_data,
6697 unsigned int max_data_bytes)
6699 char *params = *pparams;
6700 char *pdata = *ppdata;
6701 uint16 info_level;
6702 SMB_STRUCT_STAT sbuf;
6703 char *fname = NULL;
6704 files_struct *fsp = NULL;
6705 NTSTATUS status = NT_STATUS_OK;
6706 int data_return_size = 0;
6707 TALLOC_CTX *ctx = talloc_tos();
6709 if (!params) {
6710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6711 return;
6714 ZERO_STRUCT(sbuf);
6716 if (tran_call == TRANSACT2_SETFILEINFO) {
6717 if (total_params < 4) {
6718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6719 return;
6722 fsp = file_fsp(req, SVAL(params,0));
6723 /* Basic check for non-null fsp. */
6724 if (!check_fsp_open(conn, req, fsp)) {
6725 return;
6727 info_level = SVAL(params,2);
6729 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6730 if (!fname) {
6731 reply_nterror(req, NT_STATUS_NO_MEMORY);
6732 return;
6735 if(fsp->is_directory || fsp->fh->fd == -1) {
6737 * This is actually a SETFILEINFO on a directory
6738 * handle (returned from an NT SMB). NT5.0 seems
6739 * to do this call. JRA.
6741 if (INFO_LEVEL_IS_UNIX(info_level)) {
6742 /* Always do lstat for UNIX calls. */
6743 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6744 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6745 reply_unixerror(req,ERRDOS,ERRbadpath);
6746 return;
6748 } else {
6749 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6750 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6751 reply_unixerror(req,ERRDOS,ERRbadpath);
6752 return;
6755 } else if (fsp->print_file) {
6757 * Doing a DELETE_ON_CLOSE should cancel a print job.
6759 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6760 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6762 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6764 SSVAL(params,0,0);
6765 send_trans2_replies(conn, req, params, 2,
6766 *ppdata, 0,
6767 max_data_bytes);
6768 return;
6769 } else {
6770 reply_unixerror(req, ERRDOS, ERRbadpath);
6771 return;
6773 } else {
6775 * Original code - this is an open file.
6777 if (!check_fsp(conn, req, fsp)) {
6778 return;
6781 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6782 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6783 reply_unixerror(req, ERRDOS, ERRbadfid);
6784 return;
6787 } else {
6788 /* set path info */
6789 if (total_params < 7) {
6790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6791 return;
6794 info_level = SVAL(params,0);
6795 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6796 total_params - 6, STR_TERMINATE,
6797 &status);
6798 if (!NT_STATUS_IS_OK(status)) {
6799 reply_nterror(req, status);
6800 return;
6803 status = resolve_dfspath(ctx, conn,
6804 req->flags2 & FLAGS2_DFS_PATHNAMES,
6805 fname,
6806 &fname);
6807 if (!NT_STATUS_IS_OK(status)) {
6808 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6809 reply_botherror(req,
6810 NT_STATUS_PATH_NOT_COVERED,
6811 ERRSRV, ERRbadpath);
6812 return;
6814 reply_nterror(req, status);
6815 return;
6818 status = unix_convert(ctx, conn, fname, False,
6819 &fname, NULL, &sbuf);
6820 if (!NT_STATUS_IS_OK(status)) {
6821 reply_nterror(req, status);
6822 return;
6825 status = check_name(conn, fname);
6826 if (!NT_STATUS_IS_OK(status)) {
6827 reply_nterror(req, status);
6828 return;
6831 if (INFO_LEVEL_IS_UNIX(info_level)) {
6833 * For CIFS UNIX extensions the target name may not exist.
6836 /* Always do lstat for UNIX calls. */
6837 SMB_VFS_LSTAT(conn,fname,&sbuf);
6839 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6840 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6841 reply_unixerror(req, ERRDOS, ERRbadpath);
6842 return;
6846 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6847 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6848 return;
6851 if (!CAN_WRITE(conn)) {
6852 /* Allow POSIX opens. The open path will deny
6853 * any non-readonly opens. */
6854 if (info_level != SMB_POSIX_PATH_OPEN) {
6855 reply_doserror(req, ERRSRV, ERRaccess);
6856 return;
6860 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6861 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6863 /* Realloc the parameter size */
6864 *pparams = (char *)SMB_REALLOC(*pparams,2);
6865 if (*pparams == NULL) {
6866 reply_nterror(req, NT_STATUS_NO_MEMORY);
6867 return;
6869 params = *pparams;
6871 SSVAL(params,0,0);
6873 switch (info_level) {
6875 case SMB_INFO_STANDARD:
6877 status = smb_set_info_standard(conn,
6878 pdata,
6879 total_data,
6880 fsp,
6881 fname,
6882 &sbuf);
6883 break;
6886 case SMB_INFO_SET_EA:
6888 status = smb_info_set_ea(conn,
6889 pdata,
6890 total_data,
6891 fsp,
6892 fname);
6893 break;
6896 case SMB_SET_FILE_BASIC_INFO:
6897 case SMB_FILE_BASIC_INFORMATION:
6899 status = smb_set_file_basic_info(conn,
6900 pdata,
6901 total_data,
6902 fsp,
6903 fname,
6904 &sbuf);
6905 break;
6908 case SMB_FILE_ALLOCATION_INFORMATION:
6909 case SMB_SET_FILE_ALLOCATION_INFO:
6911 status = smb_set_file_allocation_info(conn, req,
6912 pdata,
6913 total_data,
6914 fsp,
6915 fname,
6916 &sbuf);
6917 break;
6920 case SMB_FILE_END_OF_FILE_INFORMATION:
6921 case SMB_SET_FILE_END_OF_FILE_INFO:
6923 status = smb_set_file_end_of_file_info(conn, req,
6924 pdata,
6925 total_data,
6926 fsp,
6927 fname,
6928 &sbuf);
6929 break;
6932 case SMB_FILE_DISPOSITION_INFORMATION:
6933 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6935 #if 0
6936 /* JRA - We used to just ignore this on a path ?
6937 * Shouldn't this be invalid level on a pathname
6938 * based call ?
6940 if (tran_call != TRANSACT2_SETFILEINFO) {
6941 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6943 #endif
6944 status = smb_set_file_disposition_info(conn,
6945 pdata,
6946 total_data,
6947 fsp,
6948 fname,
6949 &sbuf);
6950 break;
6953 case SMB_FILE_POSITION_INFORMATION:
6955 status = smb_file_position_information(conn,
6956 pdata,
6957 total_data,
6958 fsp);
6959 break;
6962 /* From tridge Samba4 :
6963 * MODE_INFORMATION in setfileinfo (I have no
6964 * idea what "mode information" on a file is - it takes a value of 0,
6965 * 2, 4 or 6. What could it be?).
6968 case SMB_FILE_MODE_INFORMATION:
6970 status = smb_file_mode_information(conn,
6971 pdata,
6972 total_data);
6973 break;
6977 * CIFS UNIX extensions.
6980 case SMB_SET_FILE_UNIX_BASIC:
6982 status = smb_set_file_unix_basic(conn, req,
6983 pdata,
6984 total_data,
6985 fsp,
6986 fname,
6987 &sbuf);
6988 break;
6991 case SMB_SET_FILE_UNIX_INFO2:
6993 status = smb_set_file_unix_info2(conn, req,
6994 pdata,
6995 total_data,
6996 fsp,
6997 fname,
6998 &sbuf);
6999 break;
7002 case SMB_SET_FILE_UNIX_LINK:
7004 if (tran_call != TRANSACT2_SETPATHINFO) {
7005 /* We must have a pathname for this. */
7006 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7007 return;
7009 status = smb_set_file_unix_link(conn, req, pdata,
7010 total_data, fname);
7011 break;
7014 case SMB_SET_FILE_UNIX_HLINK:
7016 if (tran_call != TRANSACT2_SETPATHINFO) {
7017 /* We must have a pathname for this. */
7018 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7019 return;
7021 status = smb_set_file_unix_hlink(conn, req,
7022 pdata, total_data,
7023 fname);
7024 break;
7027 case SMB_FILE_RENAME_INFORMATION:
7029 status = smb_file_rename_information(conn, req,
7030 pdata, total_data,
7031 fsp, fname);
7032 break;
7035 #if defined(HAVE_POSIX_ACLS)
7036 case SMB_SET_POSIX_ACL:
7038 status = smb_set_posix_acl(conn,
7039 pdata,
7040 total_data,
7041 fsp,
7042 fname,
7043 &sbuf);
7044 break;
7046 #endif
7048 case SMB_SET_POSIX_LOCK:
7050 if (tran_call != TRANSACT2_SETFILEINFO) {
7051 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7052 return;
7054 status = smb_set_posix_lock(conn, req,
7055 pdata, total_data, fsp);
7056 break;
7059 case SMB_POSIX_PATH_OPEN:
7061 if (tran_call != TRANSACT2_SETPATHINFO) {
7062 /* We must have a pathname for this. */
7063 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7064 return;
7067 status = smb_posix_open(conn, req,
7068 ppdata,
7069 total_data,
7070 fname,
7071 &sbuf,
7072 &data_return_size);
7073 break;
7076 case SMB_POSIX_PATH_UNLINK:
7078 if (tran_call != TRANSACT2_SETPATHINFO) {
7079 /* We must have a pathname for this. */
7080 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7081 return;
7084 status = smb_posix_unlink(conn, req,
7085 pdata,
7086 total_data,
7087 fname,
7088 &sbuf);
7089 break;
7092 default:
7093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7094 return;
7098 if (!NT_STATUS_IS_OK(status)) {
7099 if (open_was_deferred(req->mid)) {
7100 /* We have re-scheduled this call. */
7101 return;
7103 if (blocking_lock_was_deferred(req->mid)) {
7104 /* We have re-scheduled this call. */
7105 return;
7107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7108 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7109 ERRSRV, ERRbadpath);
7110 return;
7112 if (info_level == SMB_POSIX_PATH_OPEN) {
7113 reply_openerror(req, status);
7114 return;
7117 reply_nterror(req, status);
7118 return;
7121 SSVAL(params,0,0);
7122 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7123 max_data_bytes);
7125 return;
7128 /****************************************************************************
7129 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7130 ****************************************************************************/
7132 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7133 char **pparams, int total_params,
7134 char **ppdata, int total_data,
7135 unsigned int max_data_bytes)
7137 char *params = *pparams;
7138 char *pdata = *ppdata;
7139 char *directory = NULL;
7140 SMB_STRUCT_STAT sbuf;
7141 NTSTATUS status = NT_STATUS_OK;
7142 struct ea_list *ea_list = NULL;
7143 TALLOC_CTX *ctx = talloc_tos();
7145 if (!CAN_WRITE(conn)) {
7146 reply_doserror(req, ERRSRV, ERRaccess);
7147 return;
7150 if (total_params < 5) {
7151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7152 return;
7155 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7156 total_params - 4, STR_TERMINATE,
7157 &status);
7158 if (!NT_STATUS_IS_OK(status)) {
7159 reply_nterror(req, status);
7160 return;
7163 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7165 status = resolve_dfspath(ctx,
7166 conn,
7167 req->flags2 & FLAGS2_DFS_PATHNAMES,
7168 directory,
7169 &directory);
7170 if (!NT_STATUS_IS_OK(status)) {
7171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7172 reply_botherror(req,
7173 NT_STATUS_PATH_NOT_COVERED,
7174 ERRSRV, ERRbadpath);
7176 reply_nterror(req, status);
7177 return;
7180 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7181 if (!NT_STATUS_IS_OK(status)) {
7182 reply_nterror(req, status);
7183 return;
7186 status = check_name(conn, directory);
7187 if (!NT_STATUS_IS_OK(status)) {
7188 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7189 reply_nterror(req, status);
7190 return;
7193 /* Any data in this call is an EA list. */
7194 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7195 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7196 return;
7200 * OS/2 workplace shell seems to send SET_EA requests of "null"
7201 * length (4 bytes containing IVAL 4).
7202 * They seem to have no effect. Bug #3212. JRA.
7205 if (total_data != 4) {
7206 if (total_data < 10) {
7207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7208 return;
7211 if (IVAL(pdata,0) > total_data) {
7212 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7213 IVAL(pdata,0), (unsigned int)total_data));
7214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7215 return;
7218 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7219 total_data - 4);
7220 if (!ea_list) {
7221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7222 return;
7225 /* If total_data == 4 Windows doesn't care what values
7226 * are placed in that field, it just ignores them.
7227 * The System i QNTC IBM SMB client puts bad values here,
7228 * so ignore them. */
7230 status = create_directory(conn, req, directory);
7232 if (!NT_STATUS_IS_OK(status)) {
7233 reply_nterror(req, status);
7234 return;
7237 /* Try and set any given EA. */
7238 if (ea_list) {
7239 status = set_ea(conn, NULL, directory, ea_list);
7240 if (!NT_STATUS_IS_OK(status)) {
7241 reply_nterror(req, status);
7242 return;
7246 /* Realloc the parameter and data sizes */
7247 *pparams = (char *)SMB_REALLOC(*pparams,2);
7248 if(*pparams == NULL) {
7249 reply_nterror(req, NT_STATUS_NO_MEMORY);
7250 return;
7252 params = *pparams;
7254 SSVAL(params,0,0);
7256 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7258 return;
7261 /****************************************************************************
7262 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7263 We don't actually do this - we just send a null response.
7264 ****************************************************************************/
7266 static void call_trans2findnotifyfirst(connection_struct *conn,
7267 struct smb_request *req,
7268 char **pparams, int total_params,
7269 char **ppdata, int total_data,
7270 unsigned int max_data_bytes)
7272 char *params = *pparams;
7273 uint16 info_level;
7275 if (total_params < 6) {
7276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7277 return;
7280 info_level = SVAL(params,4);
7281 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7283 switch (info_level) {
7284 case 1:
7285 case 2:
7286 break;
7287 default:
7288 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7289 return;
7292 /* Realloc the parameter and data sizes */
7293 *pparams = (char *)SMB_REALLOC(*pparams,6);
7294 if (*pparams == NULL) {
7295 reply_nterror(req, NT_STATUS_NO_MEMORY);
7296 return;
7298 params = *pparams;
7300 SSVAL(params,0,fnf_handle);
7301 SSVAL(params,2,0); /* No changes */
7302 SSVAL(params,4,0); /* No EA errors */
7304 fnf_handle++;
7306 if(fnf_handle == 0)
7307 fnf_handle = 257;
7309 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7311 return;
7314 /****************************************************************************
7315 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7316 changes). Currently this does nothing.
7317 ****************************************************************************/
7319 static void call_trans2findnotifynext(connection_struct *conn,
7320 struct smb_request *req,
7321 char **pparams, int total_params,
7322 char **ppdata, int total_data,
7323 unsigned int max_data_bytes)
7325 char *params = *pparams;
7327 DEBUG(3,("call_trans2findnotifynext\n"));
7329 /* Realloc the parameter and data sizes */
7330 *pparams = (char *)SMB_REALLOC(*pparams,4);
7331 if (*pparams == NULL) {
7332 reply_nterror(req, NT_STATUS_NO_MEMORY);
7333 return;
7335 params = *pparams;
7337 SSVAL(params,0,0); /* No changes */
7338 SSVAL(params,2,0); /* No EA errors */
7340 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7342 return;
7345 /****************************************************************************
7346 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7347 ****************************************************************************/
7349 static void call_trans2getdfsreferral(connection_struct *conn,
7350 struct smb_request *req,
7351 char **pparams, int total_params,
7352 char **ppdata, int total_data,
7353 unsigned int max_data_bytes)
7355 char *params = *pparams;
7356 char *pathname = NULL;
7357 int reply_size = 0;
7358 int max_referral_level;
7359 NTSTATUS status = NT_STATUS_OK;
7360 TALLOC_CTX *ctx = talloc_tos();
7362 DEBUG(10,("call_trans2getdfsreferral\n"));
7364 if (total_params < 3) {
7365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7366 return;
7369 max_referral_level = SVAL(params,0);
7371 if(!lp_host_msdfs()) {
7372 reply_doserror(req, ERRDOS, ERRbadfunc);
7373 return;
7376 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7377 total_params - 2, STR_TERMINATE);
7378 if (!pathname) {
7379 reply_nterror(req, NT_STATUS_NOT_FOUND);
7380 return;
7382 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7383 ppdata,&status)) < 0) {
7384 reply_nterror(req, status);
7385 return;
7388 SSVAL(req->inbuf, smb_flg2,
7389 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7390 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7392 return;
7395 #define LMCAT_SPL 0x53
7396 #define LMFUNC_GETJOBID 0x60
7398 /****************************************************************************
7399 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7400 ****************************************************************************/
7402 static void call_trans2ioctl(connection_struct *conn,
7403 struct smb_request *req,
7404 char **pparams, int total_params,
7405 char **ppdata, int total_data,
7406 unsigned int max_data_bytes)
7408 char *pdata = *ppdata;
7409 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7411 /* check for an invalid fid before proceeding */
7413 if (!fsp) {
7414 reply_doserror(req, ERRDOS, ERRbadfid);
7415 return;
7418 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7419 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7420 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7421 if (*ppdata == NULL) {
7422 reply_nterror(req, NT_STATUS_NO_MEMORY);
7423 return;
7425 pdata = *ppdata;
7427 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7428 CAN ACCEPT THIS IN UNICODE. JRA. */
7430 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7431 srvstr_push(pdata, req->flags2, pdata + 2,
7432 global_myname(), 15,
7433 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7434 srvstr_push(pdata, req->flags2, pdata+18,
7435 lp_servicename(SNUM(conn)), 13,
7436 STR_ASCII|STR_TERMINATE); /* Service name */
7437 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7438 max_data_bytes);
7439 return;
7442 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7443 reply_doserror(req, ERRSRV, ERRerror);
7446 /****************************************************************************
7447 Reply to a SMBfindclose (stop trans2 directory search).
7448 ****************************************************************************/
7450 void reply_findclose(struct smb_request *req)
7452 int dptr_num;
7454 START_PROFILE(SMBfindclose);
7456 if (req->wct < 1) {
7457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7458 END_PROFILE(SMBfindclose);
7459 return;
7462 dptr_num = SVALS(req->vwv+0, 0);
7464 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7466 dptr_close(&dptr_num);
7468 reply_outbuf(req, 0, 0);
7470 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7472 END_PROFILE(SMBfindclose);
7473 return;
7476 /****************************************************************************
7477 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7478 ****************************************************************************/
7480 void reply_findnclose(struct smb_request *req)
7482 int dptr_num;
7484 START_PROFILE(SMBfindnclose);
7486 if (req->wct < 1) {
7487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7488 END_PROFILE(SMBfindnclose);
7489 return;
7492 dptr_num = SVAL(req->vwv+0, 0);
7494 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7496 /* We never give out valid handles for a
7497 findnotifyfirst - so any dptr_num is ok here.
7498 Just ignore it. */
7500 reply_outbuf(req, 0, 0);
7502 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7504 END_PROFILE(SMBfindnclose);
7505 return;
7508 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7509 struct trans_state *state)
7511 if (Protocol >= PROTOCOL_NT1) {
7512 req->flags2 |= 0x40; /* IS_LONG_NAME */
7513 SSVAL(req->inbuf,smb_flg2,req->flags2);
7516 if (conn->encrypt_level == Required && !req->encrypted) {
7517 if (state->call != TRANSACT2_QFSINFO &&
7518 state->call != TRANSACT2_SETFSINFO) {
7519 DEBUG(0,("handle_trans2: encryption required "
7520 "with call 0x%x\n",
7521 (unsigned int)state->call));
7522 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7523 return;
7527 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7529 /* Now we must call the relevant TRANS2 function */
7530 switch(state->call) {
7531 case TRANSACT2_OPEN:
7533 START_PROFILE(Trans2_open);
7534 call_trans2open(conn, req,
7535 &state->param, state->total_param,
7536 &state->data, state->total_data,
7537 state->max_data_return);
7538 END_PROFILE(Trans2_open);
7539 break;
7542 case TRANSACT2_FINDFIRST:
7544 START_PROFILE(Trans2_findfirst);
7545 call_trans2findfirst(conn, req,
7546 &state->param, state->total_param,
7547 &state->data, state->total_data,
7548 state->max_data_return);
7549 END_PROFILE(Trans2_findfirst);
7550 break;
7553 case TRANSACT2_FINDNEXT:
7555 START_PROFILE(Trans2_findnext);
7556 call_trans2findnext(conn, req,
7557 &state->param, state->total_param,
7558 &state->data, state->total_data,
7559 state->max_data_return);
7560 END_PROFILE(Trans2_findnext);
7561 break;
7564 case TRANSACT2_QFSINFO:
7566 START_PROFILE(Trans2_qfsinfo);
7567 call_trans2qfsinfo(conn, req,
7568 &state->param, state->total_param,
7569 &state->data, state->total_data,
7570 state->max_data_return);
7571 END_PROFILE(Trans2_qfsinfo);
7572 break;
7575 case TRANSACT2_SETFSINFO:
7577 START_PROFILE(Trans2_setfsinfo);
7578 call_trans2setfsinfo(conn, req,
7579 &state->param, state->total_param,
7580 &state->data, state->total_data,
7581 state->max_data_return);
7582 END_PROFILE(Trans2_setfsinfo);
7583 break;
7586 case TRANSACT2_QPATHINFO:
7587 case TRANSACT2_QFILEINFO:
7589 START_PROFILE(Trans2_qpathinfo);
7590 call_trans2qfilepathinfo(conn, req, state->call,
7591 &state->param, state->total_param,
7592 &state->data, state->total_data,
7593 state->max_data_return);
7594 END_PROFILE(Trans2_qpathinfo);
7595 break;
7598 case TRANSACT2_SETPATHINFO:
7599 case TRANSACT2_SETFILEINFO:
7601 START_PROFILE(Trans2_setpathinfo);
7602 call_trans2setfilepathinfo(conn, req, state->call,
7603 &state->param, state->total_param,
7604 &state->data, state->total_data,
7605 state->max_data_return);
7606 END_PROFILE(Trans2_setpathinfo);
7607 break;
7610 case TRANSACT2_FINDNOTIFYFIRST:
7612 START_PROFILE(Trans2_findnotifyfirst);
7613 call_trans2findnotifyfirst(conn, req,
7614 &state->param, state->total_param,
7615 &state->data, state->total_data,
7616 state->max_data_return);
7617 END_PROFILE(Trans2_findnotifyfirst);
7618 break;
7621 case TRANSACT2_FINDNOTIFYNEXT:
7623 START_PROFILE(Trans2_findnotifynext);
7624 call_trans2findnotifynext(conn, req,
7625 &state->param, state->total_param,
7626 &state->data, state->total_data,
7627 state->max_data_return);
7628 END_PROFILE(Trans2_findnotifynext);
7629 break;
7632 case TRANSACT2_MKDIR:
7634 START_PROFILE(Trans2_mkdir);
7635 call_trans2mkdir(conn, req,
7636 &state->param, state->total_param,
7637 &state->data, state->total_data,
7638 state->max_data_return);
7639 END_PROFILE(Trans2_mkdir);
7640 break;
7643 case TRANSACT2_GET_DFS_REFERRAL:
7645 START_PROFILE(Trans2_get_dfs_referral);
7646 call_trans2getdfsreferral(conn, req,
7647 &state->param, state->total_param,
7648 &state->data, state->total_data,
7649 state->max_data_return);
7650 END_PROFILE(Trans2_get_dfs_referral);
7651 break;
7654 case TRANSACT2_IOCTL:
7656 START_PROFILE(Trans2_ioctl);
7657 call_trans2ioctl(conn, req,
7658 &state->param, state->total_param,
7659 &state->data, state->total_data,
7660 state->max_data_return);
7661 END_PROFILE(Trans2_ioctl);
7662 break;
7665 default:
7666 /* Error in request */
7667 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7668 reply_doserror(req, ERRSRV,ERRerror);
7672 /****************************************************************************
7673 Reply to a SMBtrans2.
7674 ****************************************************************************/
7676 void reply_trans2(struct smb_request *req)
7678 connection_struct *conn = req->conn;
7679 unsigned int dsoff;
7680 unsigned int dscnt;
7681 unsigned int psoff;
7682 unsigned int pscnt;
7683 unsigned int tran_call;
7684 struct trans_state *state;
7685 NTSTATUS result;
7687 START_PROFILE(SMBtrans2);
7689 if (req->wct < 14) {
7690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7691 END_PROFILE(SMBtrans2);
7692 return;
7695 dsoff = SVAL(req->vwv+12, 0);
7696 dscnt = SVAL(req->vwv+11, 0);
7697 psoff = SVAL(req->vwv+10, 0);
7698 pscnt = SVAL(req->vwv+9, 0);
7699 tran_call = SVAL(req->vwv+14, 0);
7701 result = allow_new_trans(conn->pending_trans, req->mid);
7702 if (!NT_STATUS_IS_OK(result)) {
7703 DEBUG(2, ("Got invalid trans2 request: %s\n",
7704 nt_errstr(result)));
7705 reply_nterror(req, result);
7706 END_PROFILE(SMBtrans2);
7707 return;
7710 if (IS_IPC(conn)) {
7711 switch (tran_call) {
7712 /* List the allowed trans2 calls on IPC$ */
7713 case TRANSACT2_OPEN:
7714 case TRANSACT2_GET_DFS_REFERRAL:
7715 case TRANSACT2_QFILEINFO:
7716 case TRANSACT2_QFSINFO:
7717 case TRANSACT2_SETFSINFO:
7718 break;
7719 default:
7720 reply_doserror(req, ERRSRV, ERRaccess);
7721 END_PROFILE(SMBtrans2);
7722 return;
7726 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7727 DEBUG(0, ("talloc failed\n"));
7728 reply_nterror(req, NT_STATUS_NO_MEMORY);
7729 END_PROFILE(SMBtrans2);
7730 return;
7733 state->cmd = SMBtrans2;
7735 state->mid = req->mid;
7736 state->vuid = req->vuid;
7737 state->setup_count = SVAL(req->vwv+13, 0);
7738 state->setup = NULL;
7739 state->total_param = SVAL(req->vwv+0, 0);
7740 state->param = NULL;
7741 state->total_data = SVAL(req->vwv+1, 0);
7742 state->data = NULL;
7743 state->max_param_return = SVAL(req->vwv+2, 0);
7744 state->max_data_return = SVAL(req->vwv+3, 0);
7745 state->max_setup_return = SVAL(req->vwv+4, 0);
7746 state->close_on_completion = BITSETW(req->vwv+5, 0);
7747 state->one_way = BITSETW(req->vwv+5, 1);
7749 state->call = tran_call;
7751 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7752 is so as a sanity check */
7753 if (state->setup_count != 1) {
7755 * Need to have rc=0 for ioctl to get job id for OS/2.
7756 * Network printing will fail if function is not successful.
7757 * Similar function in reply.c will be used if protocol
7758 * is LANMAN1.0 instead of LM1.2X002.
7759 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7760 * outbuf doesn't have to be set(only job id is used).
7762 if ( (state->setup_count == 4)
7763 && (tran_call == TRANSACT2_IOCTL)
7764 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7765 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7766 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7767 } else {
7768 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7769 DEBUG(2,("Transaction is %d\n",tran_call));
7770 TALLOC_FREE(state);
7771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7772 END_PROFILE(SMBtrans2);
7773 return;
7777 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7778 goto bad_param;
7780 if (state->total_data) {
7782 if (trans_oob(state->total_data, 0, dscnt)
7783 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7784 goto bad_param;
7787 /* Can't use talloc here, the core routines do realloc on the
7788 * params and data. */
7789 state->data = (char *)SMB_MALLOC(state->total_data);
7790 if (state->data == NULL) {
7791 DEBUG(0,("reply_trans2: data malloc fail for %u "
7792 "bytes !\n", (unsigned int)state->total_data));
7793 TALLOC_FREE(state);
7794 reply_nterror(req, NT_STATUS_NO_MEMORY);
7795 END_PROFILE(SMBtrans2);
7796 return;
7799 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7802 if (state->total_param) {
7804 if (trans_oob(state->total_param, 0, pscnt)
7805 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7806 goto bad_param;
7809 /* Can't use talloc here, the core routines do realloc on the
7810 * params and data. */
7811 state->param = (char *)SMB_MALLOC(state->total_param);
7812 if (state->param == NULL) {
7813 DEBUG(0,("reply_trans: param malloc fail for %u "
7814 "bytes !\n", (unsigned int)state->total_param));
7815 SAFE_FREE(state->data);
7816 TALLOC_FREE(state);
7817 reply_nterror(req, NT_STATUS_NO_MEMORY);
7818 END_PROFILE(SMBtrans2);
7819 return;
7822 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7825 state->received_data = dscnt;
7826 state->received_param = pscnt;
7828 if ((state->received_param == state->total_param) &&
7829 (state->received_data == state->total_data)) {
7831 handle_trans2(conn, req, state);
7833 SAFE_FREE(state->data);
7834 SAFE_FREE(state->param);
7835 TALLOC_FREE(state);
7836 END_PROFILE(SMBtrans2);
7837 return;
7840 DLIST_ADD(conn->pending_trans, state);
7842 /* We need to send an interim response then receive the rest
7843 of the parameter/data bytes */
7844 reply_outbuf(req, 0, 0);
7845 show_msg((char *)req->outbuf);
7846 END_PROFILE(SMBtrans2);
7847 return;
7849 bad_param:
7851 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7852 SAFE_FREE(state->data);
7853 SAFE_FREE(state->param);
7854 TALLOC_FREE(state);
7855 END_PROFILE(SMBtrans2);
7856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7860 /****************************************************************************
7861 Reply to a SMBtranss2
7862 ****************************************************************************/
7864 void reply_transs2(struct smb_request *req)
7866 connection_struct *conn = req->conn;
7867 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7868 struct trans_state *state;
7870 START_PROFILE(SMBtranss2);
7872 show_msg((char *)req->inbuf);
7874 if (req->wct < 8) {
7875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7876 END_PROFILE(SMBtranss2);
7877 return;
7880 for (state = conn->pending_trans; state != NULL;
7881 state = state->next) {
7882 if (state->mid == req->mid) {
7883 break;
7887 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7889 END_PROFILE(SMBtranss2);
7890 return;
7893 /* Revise state->total_param and state->total_data in case they have
7894 changed downwards */
7896 if (SVAL(req->vwv+0, 0) < state->total_param)
7897 state->total_param = SVAL(req->vwv+0, 0);
7898 if (SVAL(req->vwv+1, 0) < state->total_data)
7899 state->total_data = SVAL(req->vwv+1, 0);
7901 pcnt = SVAL(req->vwv+2, 0);
7902 poff = SVAL(req->vwv+3, 0);
7903 pdisp = SVAL(req->vwv+4, 0);
7905 dcnt = SVAL(req->vwv+5, 0);
7906 doff = SVAL(req->vwv+6, 0);
7907 ddisp = SVAL(req->vwv+7, 0);
7909 state->received_param += pcnt;
7910 state->received_data += dcnt;
7912 if ((state->received_data > state->total_data) ||
7913 (state->received_param > state->total_param))
7914 goto bad_param;
7916 if (pcnt) {
7917 if (trans_oob(state->total_param, pdisp, pcnt)
7918 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7919 goto bad_param;
7921 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7924 if (dcnt) {
7925 if (trans_oob(state->total_data, ddisp, dcnt)
7926 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7927 goto bad_param;
7929 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7932 if ((state->received_param < state->total_param) ||
7933 (state->received_data < state->total_data)) {
7934 END_PROFILE(SMBtranss2);
7935 return;
7938 handle_trans2(conn, req, state);
7940 DLIST_REMOVE(conn->pending_trans, state);
7941 SAFE_FREE(state->data);
7942 SAFE_FREE(state->param);
7943 TALLOC_FREE(state);
7945 END_PROFILE(SMBtranss2);
7946 return;
7948 bad_param:
7950 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7951 DLIST_REMOVE(conn->pending_trans, state);
7952 SAFE_FREE(state->data);
7953 SAFE_FREE(state->param);
7954 TALLOC_FREE(state);
7955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7956 END_PROFILE(SMBtranss2);
7957 return;