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