Fix bug #5986 - Editing a stream is broken (rename problems).
[Samba.git] / source / smbd / trans2.c
blobb6f4c342c7165f648d75bca9b66b7b458e24dc1a
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"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
37 char *pdata,
38 files_struct *fsp,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
42 char *pdata,
43 files_struct *fsp,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
60 return val;
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
65 account sparse files.
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
70 SMB_BIG_UINT ret;
72 if(S_ISDIR(sbuf->st_mode)) {
73 return 0;
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
78 #else
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
80 #endif
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
101 NULL
104 int i;
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 return true;
110 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
112 return true;
114 return false;
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
127 char *val = NULL;
128 ssize_t sizeret;
130 again:
132 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (!val) {
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 } else {
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
144 attr_size = 65536;
145 goto again;
148 if (sizeret == -1) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
155 pea->flags = 0;
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 } else {
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
162 TALLOC_FREE(val);
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
167 return NT_STATUS_OK;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
178 char *p;
179 char **names, **tmp;
180 size_t num_names;
181 ssize_t sizeret;
183 if (!lp_ea_support(SNUM(conn))) {
184 *pnames = NULL;
185 *pnum_names = 0;
186 return NT_STATUS_OK;
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
194 if (names == NULL) {
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
205 TALLOC_FREE(names);
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
211 ea_namelist_size);
212 } else {
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
214 ea_namelist_size);
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
220 else {
221 break;
225 if (sizeret == -1) {
226 TALLOC_FREE(names);
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
233 if (sizeret == 0) {
234 TALLOC_FREE(names);
235 *pnames = NULL;
236 *pnum_names = 0;
237 return NT_STATUS_OK;
241 * Ensure the result is 0-terminated
244 if (ea_namelist[sizeret-1] != '\0') {
245 TALLOC_FREE(names);
246 return NT_STATUS_INTERNAL_ERROR;
250 * count the names
252 num_names = 0;
254 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
255 num_names += 1;
258 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
259 if (tmp == NULL) {
260 DEBUG(0, ("talloc failed\n"));
261 TALLOC_FREE(names);
262 return NT_STATUS_NO_MEMORY;
265 names = tmp;
266 num_names = 0;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 names[num_names++] = p;
272 *pnames = names;
273 *pnum_names = num_names;
274 return NT_STATUS_OK;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
282 const char *fname, size_t *pea_total_len)
284 /* Get a list of all xattrs. Max namesize is 64k. */
285 size_t i, num_names;
286 char **names;
287 struct ea_list *ea_list_head = NULL;
288 NTSTATUS status;
290 *pea_total_len = 0;
292 if (!lp_ea_support(SNUM(conn))) {
293 return NULL;
296 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
297 &names, &num_names);
299 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
300 return NULL;
303 for (i=0; i<num_names; i++) {
304 struct ea_list *listp;
305 fstring dos_ea_name;
307 if (strnequal(names[i], "system.", 7)
308 || samba_private_attr_name(names[i]))
309 continue;
311 listp = TALLOC_P(mem_ctx, struct ea_list);
312 if (listp == NULL) {
313 return NULL;
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
317 fname, names[i],
318 &listp->ea))) {
319 return NULL;
322 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 *pea_total_len +=
325 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
329 (unsigned int)listp->ea.value.length));
331 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
335 /* Add on 4 for total length. */
336 if (*pea_total_len) {
337 *pea_total_len += 4;
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len));
343 return ea_list_head;
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 that was filled.
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
352 connection_struct *conn, struct ea_list *ea_list)
354 unsigned int ret_data_size = 4;
355 char *p = pdata;
357 SMB_ASSERT(total_data_size >= 4);
359 if (!lp_ea_support(SNUM(conn))) {
360 SIVAL(pdata,4,0);
361 return 4;
364 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
365 size_t dos_namelen;
366 fstring dos_ea_name;
367 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
368 dos_namelen = strlen(dos_ea_name);
369 if (dos_namelen > 255 || dos_namelen == 0) {
370 break;
372 if (ea_list->ea.value.length > 65535) {
373 break;
375 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
376 break;
379 /* We know we have room. */
380 SCVAL(p,0,ea_list->ea.flags);
381 SCVAL(p,1,dos_namelen);
382 SSVAL(p,2,ea_list->ea.value.length);
383 fstrcpy(p+4, dos_ea_name);
384 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
386 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
387 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
390 ret_data_size = PTR_DIFF(p, pdata);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
392 SIVAL(pdata,0,ret_data_size);
393 return ret_data_size;
396 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
398 size_t total_ea_len = 0;
399 TALLOC_CTX *mem_ctx = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
402 return 0;
404 mem_ctx = talloc_tos();
405 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
406 return total_ea_len;
409 /****************************************************************************
410 Ensure the EA name is case insensitive by matching any existing EA name.
411 ****************************************************************************/
413 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
415 size_t total_ea_len;
416 TALLOC_CTX *mem_ctx = talloc_tos();
417 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
419 for (; ea_list; ea_list = ea_list->next) {
420 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
421 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
422 &unix_ea_name[5], ea_list->ea.name));
423 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
424 break;
429 /****************************************************************************
430 Set or delete an extended attribute.
431 ****************************************************************************/
433 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
435 if (!lp_ea_support(SNUM(conn))) {
436 return NT_STATUS_EAS_NOT_SUPPORTED;
439 for (;ea_list; ea_list = ea_list->next) {
440 int ret;
441 fstring unix_ea_name;
443 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
444 fstrcat(unix_ea_name, ea_list->ea.name);
446 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
448 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
450 if (samba_private_attr_name(unix_ea_name)) {
451 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
452 return NT_STATUS_ACCESS_DENIED;
455 if (ea_list->ea.value.length == 0) {
456 /* Remove the attribute. */
457 if (fsp && (fsp->fh->fd != -1)) {
458 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
459 unix_ea_name, fsp->fsp_name));
460 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
461 } else {
462 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
463 unix_ea_name, fname));
464 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
466 #ifdef ENOATTR
467 /* Removing a non existent attribute always succeeds. */
468 if (ret == -1 && errno == ENOATTR) {
469 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
470 unix_ea_name));
471 ret = 0;
473 #endif
474 } else {
475 if (fsp && (fsp->fh->fd != -1)) {
476 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
477 unix_ea_name, fsp->fsp_name));
478 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
479 ea_list->ea.value.data, ea_list->ea.value.length, 0);
480 } else {
481 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
482 unix_ea_name, fname));
483 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
484 ea_list->ea.value.data, ea_list->ea.value.length, 0);
488 if (ret == -1) {
489 #ifdef ENOTSUP
490 if (errno == ENOTSUP) {
491 return NT_STATUS_EAS_NOT_SUPPORTED;
493 #endif
494 return map_nt_error_from_unix(errno);
498 return NT_STATUS_OK;
500 /****************************************************************************
501 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
502 ****************************************************************************/
504 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
506 struct ea_list *ea_list_head = NULL;
507 size_t offset = 0;
509 while (offset + 2 < data_size) {
510 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
511 unsigned int namelen = CVAL(pdata,offset);
513 offset++; /* Go past the namelen byte. */
515 /* integer wrap paranioa. */
516 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
517 (offset > data_size) || (namelen > data_size) ||
518 (offset + namelen >= data_size)) {
519 break;
521 /* Ensure the name is null terminated. */
522 if (pdata[offset + namelen] != '\0') {
523 return NULL;
525 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
526 if (!eal->ea.name) {
527 return NULL;
530 offset += (namelen + 1); /* Go past the name + terminating zero. */
531 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
532 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
535 return ea_list_head;
538 /****************************************************************************
539 Read one EA list entry from the buffer.
540 ****************************************************************************/
542 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
544 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
545 uint16 val_len;
546 unsigned int namelen;
548 if (!eal) {
549 return NULL;
552 if (data_size < 6) {
553 return NULL;
556 eal->ea.flags = CVAL(pdata,0);
557 namelen = CVAL(pdata,1);
558 val_len = SVAL(pdata,2);
560 if (4 + namelen + 1 + val_len > data_size) {
561 return NULL;
564 /* Ensure the name is null terminated. */
565 if (pdata[namelen + 4] != '\0') {
566 return NULL;
568 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
569 if (!eal->ea.name) {
570 return NULL;
573 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
574 if (!eal->ea.value.data) {
575 return NULL;
578 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
580 /* Ensure we're null terminated just in case we print the value. */
581 eal->ea.value.data[val_len] = '\0';
582 /* But don't count the null. */
583 eal->ea.value.length--;
585 if (pbytes_used) {
586 *pbytes_used = 4 + namelen + 1 + val_len;
589 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
590 dump_data(10, eal->ea.value.data, eal->ea.value.length);
592 return eal;
595 /****************************************************************************
596 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
597 ****************************************************************************/
599 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
601 struct ea_list *ea_list_head = NULL;
602 size_t offset = 0;
603 size_t bytes_used = 0;
605 while (offset < data_size) {
606 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
608 if (!eal) {
609 return NULL;
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 offset += bytes_used;
616 return ea_list_head;
619 /****************************************************************************
620 Count the total EA size needed.
621 ****************************************************************************/
623 static size_t ea_list_size(struct ea_list *ealist)
625 fstring dos_ea_name;
626 struct ea_list *listp;
627 size_t ret = 0;
629 for (listp = ealist; listp; listp = listp->next) {
630 push_ascii_fstring(dos_ea_name, listp->ea.name);
631 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
633 /* Add on 4 for total length. */
634 if (ret) {
635 ret += 4;
638 return ret;
641 /****************************************************************************
642 Return a union of EA's from a file list and a list of names.
643 The TALLOC context for the two lists *MUST* be identical as we steal
644 memory from one list to add to another. JRA.
645 ****************************************************************************/
647 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
649 struct ea_list *nlistp, *flistp;
651 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
652 for (flistp = file_list; flistp; flistp = flistp->next) {
653 if (strequal(nlistp->ea.name, flistp->ea.name)) {
654 break;
658 if (flistp) {
659 /* Copy the data from this entry. */
660 nlistp->ea.flags = flistp->ea.flags;
661 nlistp->ea.value = flistp->ea.value;
662 } else {
663 /* Null entry. */
664 nlistp->ea.flags = 0;
665 ZERO_STRUCT(nlistp->ea.value);
669 *total_ea_len = ea_list_size(name_list);
670 return name_list;
673 /****************************************************************************
674 Send the required number of replies back.
675 We assume all fields other than the data fields are
676 set correctly for the type of call.
677 HACK ! Always assumes smb_setup field is zero.
678 ****************************************************************************/
680 void send_trans2_replies(connection_struct *conn,
681 struct smb_request *req,
682 const char *params,
683 int paramsize,
684 const char *pdata,
685 int datasize,
686 int max_data_bytes)
688 /* As we are using a protocol > LANMAN1 then the max_send
689 variable must have been set in the sessetupX call.
690 This takes precedence over the max_xmit field in the
691 global struct. These different max_xmit variables should
692 be merged as this is now too confusing */
694 int data_to_send = datasize;
695 int params_to_send = paramsize;
696 int useable_space;
697 const char *pp = params;
698 const char *pd = pdata;
699 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
700 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
701 int data_alignment_offset = 0;
702 bool overflow = False;
704 /* Modify the data_to_send and datasize and set the error if
705 we're trying to send more than max_data_bytes. We still send
706 the part of the packet(s) that fit. Strange, but needed
707 for OS/2. */
709 if (max_data_bytes > 0 && datasize > max_data_bytes) {
710 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
711 max_data_bytes, datasize ));
712 datasize = data_to_send = max_data_bytes;
713 overflow = True;
716 /* If there genuinely are no parameters or data to send just send the empty packet */
718 if(params_to_send == 0 && data_to_send == 0) {
719 reply_outbuf(req, 10, 0);
720 show_msg((char *)req->outbuf);
721 return;
724 /* When sending params and data ensure that both are nicely aligned */
725 /* Only do this alignment when there is also data to send - else
726 can cause NT redirector problems. */
728 if (((params_to_send % 4) != 0) && (data_to_send != 0))
729 data_alignment_offset = 4 - (params_to_send % 4);
731 /* Space is bufsize minus Netbios over TCP header minus SMB header */
732 /* The alignment_offset is to align the param bytes on an even byte
733 boundary. NT 4.0 Beta needs this to work correctly. */
735 useable_space = max_send - (smb_size
736 + 2 * 10 /* wct */
737 + alignment_offset
738 + data_alignment_offset);
740 if (useable_space < 0) {
741 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
742 "= %d!!!", useable_space));
743 exit_server_cleanly("send_trans2_replies: Not enough space");
746 while (params_to_send || data_to_send) {
747 /* Calculate whether we will totally or partially fill this packet */
749 total_sent_thistime = params_to_send + data_to_send;
751 /* We can never send more than useable_space */
753 * Note that 'useable_space' does not include the alignment offsets,
754 * but we must include the alignment offsets in the calculation of
755 * the length of the data we send over the wire, as the alignment offsets
756 * are sent here. Fix from Marc_Jacobsen@hp.com.
759 total_sent_thistime = MIN(total_sent_thistime, useable_space);
761 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
762 + data_alignment_offset);
764 /* Set total params and data to be sent */
765 SSVAL(req->outbuf,smb_tprcnt,paramsize);
766 SSVAL(req->outbuf,smb_tdrcnt,datasize);
768 /* Calculate how many parameters and data we can fit into
769 * this packet. Parameters get precedence
772 params_sent_thistime = MIN(params_to_send,useable_space);
773 data_sent_thistime = useable_space - params_sent_thistime;
774 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
776 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
778 /* smb_proff is the offset from the start of the SMB header to the
779 parameter bytes, however the first 4 bytes of outbuf are
780 the Netbios over TCP header. Thus use smb_base() to subtract
781 them from the calculation */
783 SSVAL(req->outbuf,smb_proff,
784 ((smb_buf(req->outbuf)+alignment_offset)
785 - smb_base(req->outbuf)));
787 if(params_sent_thistime == 0)
788 SSVAL(req->outbuf,smb_prdisp,0);
789 else
790 /* Absolute displacement of param bytes sent in this packet */
791 SSVAL(req->outbuf,smb_prdisp,pp - params);
793 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
794 if(data_sent_thistime == 0) {
795 SSVAL(req->outbuf,smb_droff,0);
796 SSVAL(req->outbuf,smb_drdisp, 0);
797 } else {
798 /* The offset of the data bytes is the offset of the
799 parameter bytes plus the number of parameters being sent this time */
800 SSVAL(req->outbuf, smb_droff,
801 ((smb_buf(req->outbuf)+alignment_offset)
802 - smb_base(req->outbuf))
803 + params_sent_thistime + data_alignment_offset);
804 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
807 /* Initialize the padding for alignment */
809 if (alignment_offset != 0) {
810 memset(smb_buf(req->outbuf), 0, alignment_offset);
813 /* Copy the param bytes into the packet */
815 if(params_sent_thistime) {
816 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
817 params_sent_thistime);
820 /* Copy in the data bytes */
821 if(data_sent_thistime) {
822 if (data_alignment_offset != 0) {
823 memset((smb_buf(req->outbuf)+alignment_offset+
824 params_sent_thistime), 0,
825 data_alignment_offset);
827 memcpy(smb_buf(req->outbuf)+alignment_offset
828 +params_sent_thistime+data_alignment_offset,
829 pd,data_sent_thistime);
832 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
833 params_sent_thistime, data_sent_thistime, useable_space));
834 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
835 params_to_send, data_to_send, paramsize, datasize));
837 if (overflow) {
838 error_packet_set((char *)req->outbuf,
839 ERRDOS,ERRbufferoverflow,
840 STATUS_BUFFER_OVERFLOW,
841 __LINE__,__FILE__);
844 /* Send the packet */
845 show_msg((char *)req->outbuf);
846 if (!srv_send_smb(smbd_server_fd(),
847 (char *)req->outbuf,
848 IS_CONN_ENCRYPTED(conn)))
849 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
851 TALLOC_FREE(req->outbuf);
853 pp += params_sent_thistime;
854 pd += data_sent_thistime;
856 params_to_send -= params_sent_thistime;
857 data_to_send -= data_sent_thistime;
859 /* Sanity check */
860 if(params_to_send < 0 || data_to_send < 0) {
861 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
862 params_to_send, data_to_send));
863 return;
867 return;
870 /****************************************************************************
871 Reply to a TRANSACT2_OPEN.
872 ****************************************************************************/
874 static void call_trans2open(connection_struct *conn,
875 struct smb_request *req,
876 char **pparams, int total_params,
877 char **ppdata, int total_data,
878 unsigned int max_data_bytes)
880 char *params = *pparams;
881 char *pdata = *ppdata;
882 int deny_mode;
883 int32 open_attr;
884 bool oplock_request;
885 #if 0
886 bool return_additional_info;
887 int16 open_sattr;
888 time_t open_time;
889 #endif
890 int open_ofun;
891 uint32 open_size;
892 char *pname;
893 char *fname = NULL;
894 SMB_OFF_T size=0;
895 int fattr=0,mtime=0;
896 SMB_INO_T inode = 0;
897 SMB_STRUCT_STAT sbuf;
898 int smb_action = 0;
899 files_struct *fsp;
900 struct ea_list *ea_list = NULL;
901 uint16 flags = 0;
902 NTSTATUS status;
903 uint32 access_mask;
904 uint32 share_mode;
905 uint32 create_disposition;
906 uint32 create_options = 0;
907 TALLOC_CTX *ctx = talloc_tos();
910 * Ensure we have enough parameters to perform the operation.
913 if (total_params < 29) {
914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
915 return;
918 flags = SVAL(params, 0);
919 deny_mode = SVAL(params, 2);
920 open_attr = SVAL(params,6);
921 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
922 if (oplock_request) {
923 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
926 #if 0
927 return_additional_info = BITSETW(params,0);
928 open_sattr = SVAL(params, 4);
929 open_time = make_unix_date3(params+8);
930 #endif
931 open_ofun = SVAL(params,12);
932 open_size = IVAL(params,14);
933 pname = &params[28];
935 if (IS_IPC(conn)) {
936 reply_doserror(req, ERRSRV, ERRaccess);
937 return;
940 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
941 total_params - 28, STR_TERMINATE,
942 &status);
943 if (!NT_STATUS_IS_OK(status)) {
944 reply_nterror(req, status);
945 return;
948 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
949 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
950 (unsigned int)open_ofun, open_size));
952 if (open_ofun == 0) {
953 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
954 return;
957 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
958 &access_mask,
959 &share_mode,
960 &create_disposition,
961 &create_options)) {
962 reply_doserror(req, ERRDOS, ERRbadaccess);
963 return;
966 /* Any data in this call is an EA list. */
967 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
968 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
969 return;
972 if (total_data != 4) {
973 if (total_data < 10) {
974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 return;
978 if (IVAL(pdata,0) > total_data) {
979 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
980 IVAL(pdata,0), (unsigned int)total_data));
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 return;
985 ea_list = read_ea_list(talloc_tos(), pdata + 4,
986 total_data - 4);
987 if (!ea_list) {
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 return;
991 } else if (IVAL(pdata,0) != 4) {
992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 return;
996 status = create_file(conn, /* conn */
997 req, /* req */
998 0, /* root_dir_fid */
999 fname, /* fname */
1000 access_mask, /* access_mask */
1001 share_mode, /* share_access */
1002 create_disposition, /* create_disposition*/
1003 create_options, /* create_options */
1004 open_attr, /* file_attributes */
1005 oplock_request, /* oplock_request */
1006 open_size, /* allocation_size */
1007 NULL, /* sd */
1008 ea_list, /* ea_list */
1009 &fsp, /* result */
1010 &smb_action, /* pinfo */
1011 &sbuf); /* psbuf */
1013 if (!NT_STATUS_IS_OK(status)) {
1014 if (open_was_deferred(req->mid)) {
1015 /* We have re-scheduled this call. */
1016 return;
1018 reply_openerror(req, status);
1019 return;
1022 size = get_file_size(sbuf);
1023 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1024 mtime = sbuf.st_mtime;
1025 inode = sbuf.st_ino;
1026 if (fattr & aDIR) {
1027 close_file(fsp,ERROR_CLOSE);
1028 reply_doserror(req, ERRDOS,ERRnoaccess);
1029 return;
1032 /* Realloc the size of parameters and data we will return */
1033 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1034 if(*pparams == NULL ) {
1035 reply_nterror(req, NT_STATUS_NO_MEMORY);
1036 return;
1038 params = *pparams;
1040 SSVAL(params,0,fsp->fnum);
1041 SSVAL(params,2,fattr);
1042 srv_put_dos_date2(params,4, mtime);
1043 SIVAL(params,8, (uint32)size);
1044 SSVAL(params,12,deny_mode);
1045 SSVAL(params,14,0); /* open_type - file or directory. */
1046 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1048 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1049 smb_action |= EXTENDED_OPLOCK_GRANTED;
1052 SSVAL(params,18,smb_action);
1055 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1057 SIVAL(params,20,inode);
1058 SSVAL(params,24,0); /* Padding. */
1059 if (flags & 8) {
1060 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1061 SIVAL(params, 26, ea_size);
1062 } else {
1063 SIVAL(params, 26, 0);
1066 /* Send the required number of replies */
1067 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1070 /*********************************************************
1071 Routine to check if a given string matches exactly.
1072 as a special case a mask of "." does NOT match. That
1073 is required for correct wildcard semantics
1074 Case can be significant or not.
1075 **********************************************************/
1077 static bool exact_match(connection_struct *conn,
1078 const char *str,
1079 const char *mask)
1081 if (mask[0] == '.' && mask[1] == 0)
1082 return False;
1083 if (dptr_has_wild(conn->dirptr)) {
1084 return False;
1086 if (conn->case_sensitive)
1087 return strcmp(str,mask)==0;
1088 else
1089 return StrCaseCmp(str,mask) == 0;
1092 /****************************************************************************
1093 Return the filetype for UNIX extensions.
1094 ****************************************************************************/
1096 static uint32 unix_filetype(mode_t mode)
1098 if(S_ISREG(mode))
1099 return UNIX_TYPE_FILE;
1100 else if(S_ISDIR(mode))
1101 return UNIX_TYPE_DIR;
1102 #ifdef S_ISLNK
1103 else if(S_ISLNK(mode))
1104 return UNIX_TYPE_SYMLINK;
1105 #endif
1106 #ifdef S_ISCHR
1107 else if(S_ISCHR(mode))
1108 return UNIX_TYPE_CHARDEV;
1109 #endif
1110 #ifdef S_ISBLK
1111 else if(S_ISBLK(mode))
1112 return UNIX_TYPE_BLKDEV;
1113 #endif
1114 #ifdef S_ISFIFO
1115 else if(S_ISFIFO(mode))
1116 return UNIX_TYPE_FIFO;
1117 #endif
1118 #ifdef S_ISSOCK
1119 else if(S_ISSOCK(mode))
1120 return UNIX_TYPE_SOCKET;
1121 #endif
1123 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1124 return UNIX_TYPE_UNKNOWN;
1127 /****************************************************************************
1128 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1129 ****************************************************************************/
1131 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1133 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1134 SMB_STRUCT_STAT *psbuf,
1135 uint32 perms,
1136 enum perm_type ptype,
1137 mode_t *ret_perms)
1139 mode_t ret = 0;
1141 if (perms == SMB_MODE_NO_CHANGE) {
1142 if (!VALID_STAT(*psbuf)) {
1143 return NT_STATUS_INVALID_PARAMETER;
1144 } else {
1145 *ret_perms = psbuf->st_mode;
1146 return NT_STATUS_OK;
1150 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1151 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1152 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1153 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1154 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1155 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1156 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1157 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1158 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1159 #ifdef S_ISVTX
1160 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1161 #endif
1162 #ifdef S_ISGID
1163 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1164 #endif
1165 #ifdef S_ISUID
1166 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1167 #endif
1169 switch (ptype) {
1170 case PERM_NEW_FILE:
1171 /* Apply mode mask */
1172 ret &= lp_create_mask(SNUM(conn));
1173 /* Add in force bits */
1174 ret |= lp_force_create_mode(SNUM(conn));
1175 break;
1176 case PERM_NEW_DIR:
1177 ret &= lp_dir_mask(SNUM(conn));
1178 /* Add in force bits */
1179 ret |= lp_force_dir_mode(SNUM(conn));
1180 break;
1181 case PERM_EXISTING_FILE:
1182 /* Apply mode mask */
1183 ret &= lp_security_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_security_mode(SNUM(conn));
1186 break;
1187 case PERM_EXISTING_DIR:
1188 /* Apply mode mask */
1189 ret &= lp_dir_security_mask(SNUM(conn));
1190 /* Add in force bits */
1191 ret |= lp_force_dir_security_mode(SNUM(conn));
1192 break;
1195 *ret_perms = ret;
1196 return NT_STATUS_OK;
1199 /****************************************************************************
1200 Needed to show the msdfs symlinks as directories. Modifies psbuf
1201 to be a directory if it's a msdfs link.
1202 ****************************************************************************/
1204 static bool check_msdfs_link(connection_struct *conn,
1205 const char *pathname,
1206 SMB_STRUCT_STAT *psbuf)
1208 int saved_errno = errno;
1209 if(lp_host_msdfs() &&
1210 lp_msdfs_root(SNUM(conn)) &&
1211 is_msdfs_link(conn, pathname, psbuf)) {
1213 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1214 "as a directory\n",
1215 pathname));
1216 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1217 errno = saved_errno;
1218 return true;
1220 errno = saved_errno;
1221 return false;
1225 /****************************************************************************
1226 Get a level dependent lanman2 dir entry.
1227 ****************************************************************************/
1229 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1230 connection_struct *conn,
1231 uint16 flags2,
1232 const char *path_mask,
1233 uint32 dirtype,
1234 int info_level,
1235 int requires_resume_key,
1236 bool dont_descend,
1237 bool ask_sharemode,
1238 char **ppdata,
1239 char *base_data,
1240 char *end_data,
1241 int space_remaining,
1242 bool *out_of_space,
1243 bool *got_exact_match,
1244 int *last_entry_off,
1245 struct ea_list *name_list)
1247 const char *dname;
1248 bool found = False;
1249 SMB_STRUCT_STAT sbuf;
1250 const char *mask = NULL;
1251 char *pathreal = NULL;
1252 const char *fname = NULL;
1253 char *p, *q, *pdata = *ppdata;
1254 uint32 reskey=0;
1255 long prev_dirpos=0;
1256 uint32 mode=0;
1257 SMB_OFF_T file_size = 0;
1258 SMB_BIG_UINT allocation_size = 0;
1259 uint32 len;
1260 struct timespec mdate_ts, adate_ts, create_date_ts;
1261 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1262 char *nameptr;
1263 char *last_entry_ptr;
1264 bool was_8_3;
1265 uint32 nt_extmode; /* Used for NT connections instead of mode */
1266 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1267 bool check_mangled_names = lp_manglednames(conn->params);
1268 char mangled_name[13]; /* mangled 8.3 name. */
1270 *out_of_space = False;
1271 *got_exact_match = False;
1273 ZERO_STRUCT(mdate_ts);
1274 ZERO_STRUCT(adate_ts);
1275 ZERO_STRUCT(create_date_ts);
1277 if (!conn->dirptr) {
1278 return(False);
1281 p = strrchr_m(path_mask,'/');
1282 if(p != NULL) {
1283 if(p[1] == '\0') {
1284 mask = talloc_strdup(ctx,"*.*");
1285 } else {
1286 mask = p+1;
1288 } else {
1289 mask = path_mask;
1292 while (!found) {
1293 bool got_match;
1294 bool ms_dfs_link = False;
1296 /* Needed if we run out of space */
1297 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1298 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1301 * Due to bugs in NT client redirectors we are not using
1302 * resume keys any more - set them to zero.
1303 * Check out the related comments in findfirst/findnext.
1304 * JRA.
1307 reskey = 0;
1309 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1310 (long)conn->dirptr,curr_dirpos));
1312 if (!dname) {
1313 return(False);
1317 * fname may get mangled, dname is never mangled.
1318 * Whenever we're accessing the filesystem we use
1319 * pathreal which is composed from dname.
1322 pathreal = NULL;
1323 fname = dname;
1325 /* Mangle fname if it's an illegal name. */
1326 if (mangle_must_mangle(dname,conn->params)) {
1327 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1328 continue; /* Error - couldn't mangle. */
1330 fname = mangled_name;
1333 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1334 got_match = mask_match(fname, mask, conn->case_sensitive);
1337 if(!got_match && check_mangled_names &&
1338 !mangle_is_8_3(fname, False, conn->params)) {
1340 * It turns out that NT matches wildcards against
1341 * both long *and* short names. This may explain some
1342 * of the wildcard wierdness from old DOS clients
1343 * that some people have been seeing.... JRA.
1345 /* Force the mangling into 8.3. */
1346 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1347 continue; /* Error - couldn't mangle. */
1350 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1351 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1355 if (got_match) {
1356 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1358 if (dont_descend && !isdots) {
1359 continue;
1362 if (needslash) {
1363 pathreal = NULL;
1364 pathreal = talloc_asprintf(ctx,
1365 "%s/%s",
1366 conn->dirpath,
1367 dname);
1368 } else {
1369 pathreal = talloc_asprintf(ctx,
1370 "%s%s",
1371 conn->dirpath,
1372 dname);
1375 if (!pathreal) {
1376 return False;
1379 if (INFO_LEVEL_IS_UNIX(info_level)) {
1380 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1381 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1382 pathreal,strerror(errno)));
1383 TALLOC_FREE(pathreal);
1384 continue;
1386 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387 /* Needed to show the msdfs symlinks as
1388 * directories */
1390 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391 if (!ms_dfs_link) {
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal,strerror(errno)));
1394 TALLOC_FREE(pathreal);
1395 continue;
1399 if (ms_dfs_link) {
1400 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1401 } else {
1402 mode = dos_mode(conn,pathreal,&sbuf);
1405 if (!dir_check_ftype(conn,mode,dirtype)) {
1406 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1407 TALLOC_FREE(pathreal);
1408 continue;
1411 if (!(mode & aDIR)) {
1412 file_size = get_file_size(sbuf);
1414 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1416 mdate_ts = get_mtimespec(&sbuf);
1417 adate_ts = get_atimespec(&sbuf);
1418 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1420 if (ask_sharemode) {
1421 struct timespec write_time_ts;
1422 struct file_id fileid;
1424 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1425 get_file_infos(fileid, NULL, &write_time_ts);
1426 if (!null_timespec(write_time_ts)) {
1427 mdate_ts = write_time_ts;
1431 if (lp_dos_filetime_resolution(SNUM(conn))) {
1432 dos_filetime_timespec(&create_date_ts);
1433 dos_filetime_timespec(&mdate_ts);
1434 dos_filetime_timespec(&adate_ts);
1437 create_date = convert_timespec_to_time_t(create_date_ts);
1438 mdate = convert_timespec_to_time_t(mdate_ts);
1439 adate = convert_timespec_to_time_t(adate_ts);
1441 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1443 found = True;
1445 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1449 p = pdata;
1450 last_entry_ptr = p;
1452 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1454 switch (info_level) {
1455 case SMB_FIND_INFO_STANDARD:
1456 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1457 if(requires_resume_key) {
1458 SIVAL(p,0,reskey);
1459 p += 4;
1461 srv_put_dos_date2(p,0,create_date);
1462 srv_put_dos_date2(p,4,adate);
1463 srv_put_dos_date2(p,8,mdate);
1464 SIVAL(p,12,(uint32)file_size);
1465 SIVAL(p,16,(uint32)allocation_size);
1466 SSVAL(p,20,mode);
1467 p += 23;
1468 nameptr = p;
1469 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1470 p += ucs2_align(base_data, p, 0);
1472 len = srvstr_push(base_data, flags2, p,
1473 fname, PTR_DIFF(end_data, p),
1474 STR_TERMINATE);
1475 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1476 if (len > 2) {
1477 SCVAL(nameptr, -1, len - 2);
1478 } else {
1479 SCVAL(nameptr, -1, 0);
1481 } else {
1482 if (len > 1) {
1483 SCVAL(nameptr, -1, len - 1);
1484 } else {
1485 SCVAL(nameptr, -1, 0);
1488 p += len;
1489 break;
1491 case SMB_FIND_EA_SIZE:
1492 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1493 if(requires_resume_key) {
1494 SIVAL(p,0,reskey);
1495 p += 4;
1497 srv_put_dos_date2(p,0,create_date);
1498 srv_put_dos_date2(p,4,adate);
1499 srv_put_dos_date2(p,8,mdate);
1500 SIVAL(p,12,(uint32)file_size);
1501 SIVAL(p,16,(uint32)allocation_size);
1502 SSVAL(p,20,mode);
1504 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1505 SIVAL(p,22,ea_size); /* Extended attributes */
1507 p += 27;
1508 nameptr = p - 1;
1509 len = srvstr_push(base_data, flags2,
1510 p, fname, PTR_DIFF(end_data, p),
1511 STR_TERMINATE | STR_NOALIGN);
1512 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1513 if (len > 2) {
1514 len -= 2;
1515 } else {
1516 len = 0;
1518 } else {
1519 if (len > 1) {
1520 len -= 1;
1521 } else {
1522 len = 0;
1525 SCVAL(nameptr,0,len);
1526 p += len;
1527 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1528 break;
1530 case SMB_FIND_EA_LIST:
1532 struct ea_list *file_list = NULL;
1533 size_t ea_len = 0;
1535 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1536 if (!name_list) {
1537 return False;
1539 if(requires_resume_key) {
1540 SIVAL(p,0,reskey);
1541 p += 4;
1543 srv_put_dos_date2(p,0,create_date);
1544 srv_put_dos_date2(p,4,adate);
1545 srv_put_dos_date2(p,8,mdate);
1546 SIVAL(p,12,(uint32)file_size);
1547 SIVAL(p,16,(uint32)allocation_size);
1548 SSVAL(p,20,mode);
1549 p += 22; /* p now points to the EA area. */
1551 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1552 name_list = ea_list_union(name_list, file_list, &ea_len);
1554 /* We need to determine if this entry will fit in the space available. */
1555 /* Max string size is 255 bytes. */
1556 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1557 /* Move the dirptr back to prev_dirpos */
1558 dptr_SeekDir(conn->dirptr, prev_dirpos);
1559 *out_of_space = True;
1560 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1561 return False; /* Not finished - just out of space */
1564 /* Push the ea_data followed by the name. */
1565 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1566 nameptr = p;
1567 len = srvstr_push(base_data, flags2,
1568 p + 1, fname, PTR_DIFF(end_data, p+1),
1569 STR_TERMINATE | STR_NOALIGN);
1570 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 if (len > 2) {
1572 len -= 2;
1573 } else {
1574 len = 0;
1576 } else {
1577 if (len > 1) {
1578 len -= 1;
1579 } else {
1580 len = 0;
1583 SCVAL(nameptr,0,len);
1584 p += len + 1;
1585 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1586 break;
1589 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1590 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1591 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1592 p += 4;
1593 SIVAL(p,0,reskey); p += 4;
1594 put_long_date_timespec(p,create_date_ts); p += 8;
1595 put_long_date_timespec(p,adate_ts); p += 8;
1596 put_long_date_timespec(p,mdate_ts); p += 8;
1597 put_long_date_timespec(p,mdate_ts); p += 8;
1598 SOFF_T(p,0,file_size); p += 8;
1599 SOFF_T(p,0,allocation_size); p += 8;
1600 SIVAL(p,0,nt_extmode); p += 4;
1601 q = p; p += 4; /* q is placeholder for name length. */
1603 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1604 SIVAL(p,0,ea_size); /* Extended attributes */
1605 p += 4;
1607 /* Clear the short name buffer. This is
1608 * IMPORTANT as not doing so will trigger
1609 * a Win2k client bug. JRA.
1611 if (!was_8_3 && check_mangled_names) {
1612 if (!name_to_8_3(fname,mangled_name,True,
1613 conn->params)) {
1614 /* Error - mangle failed ! */
1615 memset(mangled_name,'\0',12);
1617 mangled_name[12] = 0;
1618 len = srvstr_push(base_data, flags2,
1619 p+2, mangled_name, 24,
1620 STR_UPPER|STR_UNICODE);
1621 if (len < 24) {
1622 memset(p + 2 + len,'\0',24 - len);
1624 SSVAL(p, 0, len);
1625 } else {
1626 memset(p,'\0',26);
1628 p += 2 + 24;
1629 len = srvstr_push(base_data, flags2, p,
1630 fname, PTR_DIFF(end_data, p),
1631 STR_TERMINATE_ASCII);
1632 SIVAL(q,0,len);
1633 p += len;
1634 SIVAL(p,0,0); /* Ensure any padding is null. */
1635 len = PTR_DIFF(p, pdata);
1636 len = (len + 3) & ~3;
1637 SIVAL(pdata,0,len);
1638 p = pdata + len;
1639 break;
1641 case SMB_FIND_FILE_DIRECTORY_INFO:
1642 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1643 p += 4;
1644 SIVAL(p,0,reskey); p += 4;
1645 put_long_date_timespec(p,create_date_ts); p += 8;
1646 put_long_date_timespec(p,adate_ts); p += 8;
1647 put_long_date_timespec(p,mdate_ts); p += 8;
1648 put_long_date_timespec(p,mdate_ts); p += 8;
1649 SOFF_T(p,0,file_size); p += 8;
1650 SOFF_T(p,0,allocation_size); p += 8;
1651 SIVAL(p,0,nt_extmode); p += 4;
1652 len = srvstr_push(base_data, flags2,
1653 p + 4, fname, PTR_DIFF(end_data, p+4),
1654 STR_TERMINATE_ASCII);
1655 SIVAL(p,0,len);
1656 p += 4 + len;
1657 SIVAL(p,0,0); /* Ensure any padding is null. */
1658 len = PTR_DIFF(p, pdata);
1659 len = (len + 3) & ~3;
1660 SIVAL(pdata,0,len);
1661 p = pdata + len;
1662 break;
1664 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1665 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1666 p += 4;
1667 SIVAL(p,0,reskey); p += 4;
1668 put_long_date_timespec(p,create_date_ts); p += 8;
1669 put_long_date_timespec(p,adate_ts); p += 8;
1670 put_long_date_timespec(p,mdate_ts); p += 8;
1671 put_long_date_timespec(p,mdate_ts); p += 8;
1672 SOFF_T(p,0,file_size); p += 8;
1673 SOFF_T(p,0,allocation_size); p += 8;
1674 SIVAL(p,0,nt_extmode); p += 4;
1675 q = p; p += 4; /* q is placeholder for name length. */
1677 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1678 SIVAL(p,0,ea_size); /* Extended attributes */
1679 p +=4;
1681 len = srvstr_push(base_data, flags2, p,
1682 fname, PTR_DIFF(end_data, p),
1683 STR_TERMINATE_ASCII);
1684 SIVAL(q, 0, len);
1685 p += len;
1687 SIVAL(p,0,0); /* Ensure any padding is null. */
1688 len = PTR_DIFF(p, pdata);
1689 len = (len + 3) & ~3;
1690 SIVAL(pdata,0,len);
1691 p = pdata + len;
1692 break;
1694 case SMB_FIND_FILE_NAMES_INFO:
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1696 p += 4;
1697 SIVAL(p,0,reskey); p += 4;
1698 p += 4;
1699 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1700 acl on a dir (tridge) */
1701 len = srvstr_push(base_data, flags2, p,
1702 fname, PTR_DIFF(end_data, p),
1703 STR_TERMINATE_ASCII);
1704 SIVAL(p, -4, len);
1705 p += len;
1706 SIVAL(p,0,0); /* Ensure any padding is null. */
1707 len = PTR_DIFF(p, pdata);
1708 len = (len + 3) & ~3;
1709 SIVAL(pdata,0,len);
1710 p = pdata + len;
1711 break;
1713 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1714 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1715 p += 4;
1716 SIVAL(p,0,reskey); p += 4;
1717 put_long_date_timespec(p,create_date_ts); p += 8;
1718 put_long_date_timespec(p,adate_ts); p += 8;
1719 put_long_date_timespec(p,mdate_ts); p += 8;
1720 put_long_date_timespec(p,mdate_ts); p += 8;
1721 SOFF_T(p,0,file_size); p += 8;
1722 SOFF_T(p,0,allocation_size); p += 8;
1723 SIVAL(p,0,nt_extmode); p += 4;
1724 q = p; p += 4; /* q is placeholder for name length. */
1726 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1727 SIVAL(p,0,ea_size); /* Extended attributes */
1728 p +=4;
1730 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1731 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1732 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1733 len = srvstr_push(base_data, flags2, p,
1734 fname, PTR_DIFF(end_data, p),
1735 STR_TERMINATE_ASCII);
1736 SIVAL(q, 0, len);
1737 p += len;
1738 SIVAL(p,0,0); /* Ensure any padding is null. */
1739 len = PTR_DIFF(p, pdata);
1740 len = (len + 3) & ~3;
1741 SIVAL(pdata,0,len);
1742 p = pdata + len;
1743 break;
1745 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1746 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1747 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1748 p += 4;
1749 SIVAL(p,0,reskey); p += 4;
1750 put_long_date_timespec(p,create_date_ts); p += 8;
1751 put_long_date_timespec(p,adate_ts); p += 8;
1752 put_long_date_timespec(p,mdate_ts); p += 8;
1753 put_long_date_timespec(p,mdate_ts); p += 8;
1754 SOFF_T(p,0,file_size); p += 8;
1755 SOFF_T(p,0,allocation_size); p += 8;
1756 SIVAL(p,0,nt_extmode); p += 4;
1757 q = p; p += 4; /* q is placeholder for name length */
1759 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1760 SIVAL(p,0,ea_size); /* Extended attributes */
1761 p +=4;
1763 /* Clear the short name buffer. This is
1764 * IMPORTANT as not doing so will trigger
1765 * a Win2k client bug. JRA.
1767 if (!was_8_3 && check_mangled_names) {
1768 if (!name_to_8_3(fname,mangled_name,True,
1769 conn->params)) {
1770 /* Error - mangle failed ! */
1771 memset(mangled_name,'\0',12);
1773 mangled_name[12] = 0;
1774 len = srvstr_push(base_data, flags2,
1775 p+2, mangled_name, 24,
1776 STR_UPPER|STR_UNICODE);
1777 SSVAL(p, 0, len);
1778 if (len < 24) {
1779 memset(p + 2 + len,'\0',24 - len);
1781 SSVAL(p, 0, len);
1782 } else {
1783 memset(p,'\0',26);
1785 p += 26;
1786 SSVAL(p,0,0); p += 2; /* Reserved ? */
1787 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1788 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1789 len = srvstr_push(base_data, flags2, p,
1790 fname, PTR_DIFF(end_data, p),
1791 STR_TERMINATE_ASCII);
1792 SIVAL(q,0,len);
1793 p += len;
1794 SIVAL(p,0,0); /* Ensure any padding is null. */
1795 len = PTR_DIFF(p, pdata);
1796 len = (len + 3) & ~3;
1797 SIVAL(pdata,0,len);
1798 p = pdata + len;
1799 break;
1801 /* CIFS UNIX Extension. */
1803 case SMB_FIND_FILE_UNIX:
1804 case SMB_FIND_FILE_UNIX_INFO2:
1805 p+= 4;
1806 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1808 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1810 if (info_level == SMB_FIND_FILE_UNIX) {
1811 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1812 p = store_file_unix_basic(conn, p,
1813 NULL, &sbuf);
1814 len = srvstr_push(base_data, flags2, p,
1815 fname, PTR_DIFF(end_data, p),
1816 STR_TERMINATE);
1817 } else {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1819 p = store_file_unix_basic_info2(conn, p,
1820 NULL, &sbuf);
1821 nameptr = p;
1822 p += 4;
1823 len = srvstr_push(base_data, flags2, p, fname,
1824 PTR_DIFF(end_data, p), 0);
1825 SIVAL(nameptr, 0, len);
1828 p += len;
1829 SIVAL(p,0,0); /* Ensure any padding is null. */
1831 len = PTR_DIFF(p, pdata);
1832 len = (len + 3) & ~3;
1833 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1834 p = pdata + len;
1835 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1837 break;
1839 default:
1840 return(False);
1844 if (PTR_DIFF(p,pdata) > space_remaining) {
1845 /* Move the dirptr back to prev_dirpos */
1846 dptr_SeekDir(conn->dirptr, prev_dirpos);
1847 *out_of_space = True;
1848 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1849 return False; /* Not finished - just out of space */
1852 /* Setup the last entry pointer, as an offset from base_data */
1853 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1854 /* Advance the data pointer to the next slot */
1855 *ppdata = p;
1857 return(found);
1860 /****************************************************************************
1861 Reply to a TRANS2_FINDFIRST.
1862 ****************************************************************************/
1864 static void call_trans2findfirst(connection_struct *conn,
1865 struct smb_request *req,
1866 char **pparams, int total_params,
1867 char **ppdata, int total_data,
1868 unsigned int max_data_bytes)
1870 /* We must be careful here that we don't return more than the
1871 allowed number of data bytes. If this means returning fewer than
1872 maxentries then so be it. We assume that the redirector has
1873 enough room for the fixed number of parameter bytes it has
1874 requested. */
1875 char *params = *pparams;
1876 char *pdata = *ppdata;
1877 char *data_end;
1878 uint32 dirtype;
1879 int maxentries;
1880 uint16 findfirst_flags;
1881 bool close_after_first;
1882 bool close_if_end;
1883 bool requires_resume_key;
1884 int info_level;
1885 char *directory = NULL;
1886 char *mask = NULL;
1887 char *p;
1888 int last_entry_off=0;
1889 int dptr_num = -1;
1890 int numentries = 0;
1891 int i;
1892 bool finished = False;
1893 bool dont_descend = False;
1894 bool out_of_space = False;
1895 int space_remaining;
1896 bool mask_contains_wcard = False;
1897 SMB_STRUCT_STAT sbuf;
1898 struct ea_list *ea_list = NULL;
1899 NTSTATUS ntstatus = NT_STATUS_OK;
1900 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1901 TALLOC_CTX *ctx = talloc_tos();
1903 if (total_params < 13) {
1904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1905 return;
1908 dirtype = SVAL(params,0);
1909 maxentries = SVAL(params,2);
1910 findfirst_flags = SVAL(params,4);
1911 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1912 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1913 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1914 info_level = SVAL(params,6);
1916 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1917 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1918 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1919 info_level, max_data_bytes));
1921 if (!maxentries) {
1922 /* W2K3 seems to treat zero as 1. */
1923 maxentries = 1;
1926 switch (info_level) {
1927 case SMB_FIND_INFO_STANDARD:
1928 case SMB_FIND_EA_SIZE:
1929 case SMB_FIND_EA_LIST:
1930 case SMB_FIND_FILE_DIRECTORY_INFO:
1931 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1932 case SMB_FIND_FILE_NAMES_INFO:
1933 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1934 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1935 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1936 break;
1937 case SMB_FIND_FILE_UNIX:
1938 case SMB_FIND_FILE_UNIX_INFO2:
1939 /* Always use filesystem for UNIX mtime query. */
1940 ask_sharemode = false;
1941 if (!lp_unix_extensions()) {
1942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1943 return;
1945 break;
1946 default:
1947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1948 return;
1951 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1952 params+12, total_params - 12,
1953 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1954 if (!NT_STATUS_IS_OK(ntstatus)) {
1955 reply_nterror(req, ntstatus);
1956 return;
1959 ntstatus = resolve_dfspath_wcard(ctx, conn,
1960 req->flags2 & FLAGS2_DFS_PATHNAMES,
1961 directory,
1962 &directory,
1963 &mask_contains_wcard);
1964 if (!NT_STATUS_IS_OK(ntstatus)) {
1965 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1966 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1967 ERRSRV, ERRbadpath);
1968 return;
1970 reply_nterror(req, ntstatus);
1971 return;
1974 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1975 if (!NT_STATUS_IS_OK(ntstatus)) {
1976 reply_nterror(req, ntstatus);
1977 return;
1980 ntstatus = check_name(conn, directory);
1981 if (!NT_STATUS_IS_OK(ntstatus)) {
1982 reply_nterror(req, ntstatus);
1983 return;
1986 p = strrchr_m(directory,'/');
1987 if(p == NULL) {
1988 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1989 if((directory[0] == '.') && (directory[1] == '\0')) {
1990 mask = talloc_strdup(ctx,"*");
1991 if (!mask) {
1992 reply_nterror(req, NT_STATUS_NO_MEMORY);
1993 return;
1995 mask_contains_wcard = True;
1997 directory = talloc_strdup(talloc_tos(), "./");
1998 if (!directory) {
1999 reply_nterror(req, NT_STATUS_NO_MEMORY);
2000 return;
2002 } else {
2003 *p = 0;
2006 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2008 if (info_level == SMB_FIND_EA_LIST) {
2009 uint32 ea_size;
2011 if (total_data < 4) {
2012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2013 return;
2016 ea_size = IVAL(pdata,0);
2017 if (ea_size != total_data) {
2018 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2019 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2021 return;
2024 if (!lp_ea_support(SNUM(conn))) {
2025 reply_doserror(req, ERRDOS, ERReasnotsupported);
2026 return;
2029 /* Pull out the list of names. */
2030 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2031 if (!ea_list) {
2032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 return;
2037 *ppdata = (char *)SMB_REALLOC(
2038 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2039 if(*ppdata == NULL ) {
2040 reply_nterror(req, NT_STATUS_NO_MEMORY);
2041 return;
2043 pdata = *ppdata;
2044 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2046 /* Realloc the params space */
2047 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2048 if (*pparams == NULL) {
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2050 return;
2052 params = *pparams;
2054 /* Save the wildcard match and attribs we are using on this directory -
2055 needed as lanman2 assumes these are being saved between calls */
2057 ntstatus = dptr_create(conn,
2058 directory,
2059 False,
2060 True,
2061 req->smbpid,
2062 mask,
2063 mask_contains_wcard,
2064 dirtype,
2065 &conn->dirptr);
2067 if (!NT_STATUS_IS_OK(ntstatus)) {
2068 reply_nterror(req, ntstatus);
2069 return;
2072 dptr_num = dptr_dnum(conn->dirptr);
2073 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2075 /* We don't need to check for VOL here as this is returned by
2076 a different TRANS2 call. */
2078 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2079 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2080 dont_descend = True;
2082 p = pdata;
2083 space_remaining = max_data_bytes;
2084 out_of_space = False;
2086 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2087 bool got_exact_match = False;
2089 /* this is a heuristic to avoid seeking the dirptr except when
2090 absolutely necessary. It allows for a filename of about 40 chars */
2091 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2092 out_of_space = True;
2093 finished = False;
2094 } else {
2095 finished = !get_lanman2_dir_entry(ctx,
2096 conn,
2097 req->flags2,
2098 mask,dirtype,info_level,
2099 requires_resume_key,dont_descend,
2100 ask_sharemode,
2101 &p,pdata,data_end,
2102 space_remaining, &out_of_space,
2103 &got_exact_match,
2104 &last_entry_off, ea_list);
2107 if (finished && out_of_space)
2108 finished = False;
2110 if (!finished && !out_of_space)
2111 numentries++;
2114 * As an optimisation if we know we aren't looking
2115 * for a wildcard name (ie. the name matches the wildcard exactly)
2116 * then we can finish on any (first) match.
2117 * This speeds up large directory searches. JRA.
2120 if(got_exact_match)
2121 finished = True;
2123 /* Ensure space_remaining never goes -ve. */
2124 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2125 space_remaining = 0;
2126 out_of_space = true;
2127 } else {
2128 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2132 /* Check if we can close the dirptr */
2133 if(close_after_first || (finished && close_if_end)) {
2134 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2135 dptr_close(&dptr_num);
2139 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2140 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2141 * the protocol level is less than NT1. Tested with smbclient. JRA.
2142 * This should fix the OS/2 client bug #2335.
2145 if(numentries == 0) {
2146 dptr_close(&dptr_num);
2147 if (Protocol < PROTOCOL_NT1) {
2148 reply_doserror(req, ERRDOS, ERRnofiles);
2149 return;
2150 } else {
2151 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2152 ERRDOS, ERRbadfile);
2153 return;
2157 /* At this point pdata points to numentries directory entries. */
2159 /* Set up the return parameter block */
2160 SSVAL(params,0,dptr_num);
2161 SSVAL(params,2,numentries);
2162 SSVAL(params,4,finished);
2163 SSVAL(params,6,0); /* Never an EA error */
2164 SSVAL(params,8,last_entry_off);
2166 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2167 max_data_bytes);
2169 if ((! *directory) && dptr_path(dptr_num)) {
2170 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2171 if (!directory) {
2172 reply_nterror(req, NT_STATUS_NO_MEMORY);
2176 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2177 smb_fn_name(CVAL(req->inbuf,smb_com)),
2178 mask, directory, dirtype, numentries ) );
2181 * Force a name mangle here to ensure that the
2182 * mask as an 8.3 name is top of the mangled cache.
2183 * The reasons for this are subtle. Don't remove
2184 * this code unless you know what you are doing
2185 * (see PR#13758). JRA.
2188 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2189 char mangled_name[13];
2190 name_to_8_3(mask, mangled_name, True, conn->params);
2193 return;
2196 /****************************************************************************
2197 Reply to a TRANS2_FINDNEXT.
2198 ****************************************************************************/
2200 static void call_trans2findnext(connection_struct *conn,
2201 struct smb_request *req,
2202 char **pparams, int total_params,
2203 char **ppdata, int total_data,
2204 unsigned int max_data_bytes)
2206 /* We must be careful here that we don't return more than the
2207 allowed number of data bytes. If this means returning fewer than
2208 maxentries then so be it. We assume that the redirector has
2209 enough room for the fixed number of parameter bytes it has
2210 requested. */
2211 char *params = *pparams;
2212 char *pdata = *ppdata;
2213 char *data_end;
2214 int dptr_num;
2215 int maxentries;
2216 uint16 info_level;
2217 uint32 resume_key;
2218 uint16 findnext_flags;
2219 bool close_after_request;
2220 bool close_if_end;
2221 bool requires_resume_key;
2222 bool continue_bit;
2223 bool mask_contains_wcard = False;
2224 char *resume_name = NULL;
2225 const char *mask = NULL;
2226 const char *directory = NULL;
2227 char *p = NULL;
2228 uint16 dirtype;
2229 int numentries = 0;
2230 int i, last_entry_off=0;
2231 bool finished = False;
2232 bool dont_descend = False;
2233 bool out_of_space = False;
2234 int space_remaining;
2235 struct ea_list *ea_list = NULL;
2236 NTSTATUS ntstatus = NT_STATUS_OK;
2237 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2238 TALLOC_CTX *ctx = talloc_tos();
2240 if (total_params < 13) {
2241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2242 return;
2245 dptr_num = SVAL(params,0);
2246 maxentries = SVAL(params,2);
2247 info_level = SVAL(params,4);
2248 resume_key = IVAL(params,6);
2249 findnext_flags = SVAL(params,10);
2250 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2251 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2252 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2253 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2255 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2256 params+12,
2257 total_params - 12, STR_TERMINATE, &ntstatus,
2258 &mask_contains_wcard);
2259 if (!NT_STATUS_IS_OK(ntstatus)) {
2260 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2261 complain (it thinks we're asking for the directory above the shared
2262 path or an invalid name). Catch this as the resume name is only compared, never used in
2263 a file access. JRA. */
2264 srvstr_pull_talloc(ctx, params, req->flags2,
2265 &resume_name, params+12,
2266 total_params - 12,
2267 STR_TERMINATE);
2269 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2270 reply_nterror(req, ntstatus);
2271 return;
2275 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2276 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2277 resume_key = %d resume name = %s continue=%d level = %d\n",
2278 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2279 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2281 if (!maxentries) {
2282 /* W2K3 seems to treat zero as 1. */
2283 maxentries = 1;
2286 switch (info_level) {
2287 case SMB_FIND_INFO_STANDARD:
2288 case SMB_FIND_EA_SIZE:
2289 case SMB_FIND_EA_LIST:
2290 case SMB_FIND_FILE_DIRECTORY_INFO:
2291 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2292 case SMB_FIND_FILE_NAMES_INFO:
2293 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2294 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2295 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2296 break;
2297 case SMB_FIND_FILE_UNIX:
2298 case SMB_FIND_FILE_UNIX_INFO2:
2299 /* Always use filesystem for UNIX mtime query. */
2300 ask_sharemode = false;
2301 if (!lp_unix_extensions()) {
2302 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2303 return;
2305 break;
2306 default:
2307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2308 return;
2311 if (info_level == SMB_FIND_EA_LIST) {
2312 uint32 ea_size;
2314 if (total_data < 4) {
2315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2316 return;
2319 ea_size = IVAL(pdata,0);
2320 if (ea_size != total_data) {
2321 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2322 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2324 return;
2327 if (!lp_ea_support(SNUM(conn))) {
2328 reply_doserror(req, ERRDOS, ERReasnotsupported);
2329 return;
2332 /* Pull out the list of names. */
2333 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2334 if (!ea_list) {
2335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 return;
2340 *ppdata = (char *)SMB_REALLOC(
2341 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2342 if(*ppdata == NULL) {
2343 reply_nterror(req, NT_STATUS_NO_MEMORY);
2344 return;
2347 pdata = *ppdata;
2348 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2350 /* Realloc the params space */
2351 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2352 if(*pparams == NULL ) {
2353 reply_nterror(req, NT_STATUS_NO_MEMORY);
2354 return;
2357 params = *pparams;
2359 /* Check that the dptr is valid */
2360 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2361 reply_doserror(req, ERRDOS, ERRnofiles);
2362 return;
2365 string_set(&conn->dirpath,dptr_path(dptr_num));
2367 /* Get the wildcard mask from the dptr */
2368 if((p = dptr_wcard(dptr_num))== NULL) {
2369 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2370 reply_doserror(req, ERRDOS, ERRnofiles);
2371 return;
2374 mask = p;
2375 directory = conn->dirpath;
2377 /* Get the attr mask from the dptr */
2378 dirtype = dptr_attr(dptr_num);
2380 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2381 dptr_num, mask, dirtype,
2382 (long)conn->dirptr,
2383 dptr_TellDir(conn->dirptr)));
2385 /* We don't need to check for VOL here as this is returned by
2386 a different TRANS2 call. */
2388 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2389 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2390 dont_descend = True;
2392 p = pdata;
2393 space_remaining = max_data_bytes;
2394 out_of_space = False;
2397 * Seek to the correct position. We no longer use the resume key but
2398 * depend on the last file name instead.
2401 if(*resume_name && !continue_bit) {
2402 SMB_STRUCT_STAT st;
2404 long current_pos = 0;
2406 * Remember, name_to_8_3 is called by
2407 * get_lanman2_dir_entry(), so the resume name
2408 * could be mangled. Ensure we check the unmangled name.
2411 if (mangle_is_mangled(resume_name, conn->params)) {
2412 char *new_resume_name = NULL;
2413 mangle_lookup_name_from_8_3(ctx,
2414 resume_name,
2415 &new_resume_name,
2416 conn->params);
2417 if (new_resume_name) {
2418 resume_name = new_resume_name;
2423 * Fix for NT redirector problem triggered by resume key indexes
2424 * changing between directory scans. We now return a resume key of 0
2425 * and instead look for the filename to continue from (also given
2426 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2427 * findfirst/findnext (as is usual) then the directory pointer
2428 * should already be at the correct place.
2431 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2432 } /* end if resume_name && !continue_bit */
2434 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2435 bool got_exact_match = False;
2437 /* this is a heuristic to avoid seeking the dirptr except when
2438 absolutely necessary. It allows for a filename of about 40 chars */
2439 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2440 out_of_space = True;
2441 finished = False;
2442 } else {
2443 finished = !get_lanman2_dir_entry(ctx,
2444 conn,
2445 req->flags2,
2446 mask,dirtype,info_level,
2447 requires_resume_key,dont_descend,
2448 ask_sharemode,
2449 &p,pdata,data_end,
2450 space_remaining, &out_of_space,
2451 &got_exact_match,
2452 &last_entry_off, ea_list);
2455 if (finished && out_of_space)
2456 finished = False;
2458 if (!finished && !out_of_space)
2459 numentries++;
2462 * As an optimisation if we know we aren't looking
2463 * for a wildcard name (ie. the name matches the wildcard exactly)
2464 * then we can finish on any (first) match.
2465 * This speeds up large directory searches. JRA.
2468 if(got_exact_match)
2469 finished = True;
2471 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2474 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2475 smb_fn_name(CVAL(req->inbuf,smb_com)),
2476 mask, directory, dirtype, numentries ) );
2478 /* Check if we can close the dirptr */
2479 if(close_after_request || (finished && close_if_end)) {
2480 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2481 dptr_close(&dptr_num); /* This frees up the saved mask */
2484 /* Set up the return parameter block */
2485 SSVAL(params,0,numentries);
2486 SSVAL(params,2,finished);
2487 SSVAL(params,4,0); /* Never an EA error */
2488 SSVAL(params,6,last_entry_off);
2490 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2491 max_data_bytes);
2493 return;
2496 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2498 E_md4hash(lp_servicename(SNUM(conn)),objid);
2499 return objid;
2502 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2504 SMB_ASSERT(extended_info != NULL);
2506 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2507 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2508 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2509 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2510 #ifdef SAMBA_VERSION_REVISION
2511 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2512 #endif
2513 extended_info->samba_subversion = 0;
2514 #ifdef SAMBA_VERSION_RC_RELEASE
2515 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2516 #else
2517 #ifdef SAMBA_VERSION_PRE_RELEASE
2518 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2519 #endif
2520 #endif
2521 #ifdef SAMBA_VERSION_VENDOR_PATCH
2522 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2523 #endif
2524 extended_info->samba_gitcommitdate = 0;
2525 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2526 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2527 #endif
2529 memset(extended_info->samba_version_string, 0,
2530 sizeof(extended_info->samba_version_string));
2532 snprintf (extended_info->samba_version_string,
2533 sizeof(extended_info->samba_version_string),
2534 "%s", samba_version_string());
2537 /****************************************************************************
2538 Reply to a TRANS2_QFSINFO (query filesystem info).
2539 ****************************************************************************/
2541 static void call_trans2qfsinfo(connection_struct *conn,
2542 struct smb_request *req,
2543 char **pparams, int total_params,
2544 char **ppdata, int total_data,
2545 unsigned int max_data_bytes)
2547 char *pdata, *end_data;
2548 char *params = *pparams;
2549 uint16 info_level;
2550 int data_len, len;
2551 SMB_STRUCT_STAT st;
2552 const char *vname = volume_label(SNUM(conn));
2553 int snum = SNUM(conn);
2554 char *fstype = lp_fstype(SNUM(conn));
2555 uint32 additional_flags = 0;
2557 if (total_params < 2) {
2558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2559 return;
2562 info_level = SVAL(params,0);
2564 if (IS_IPC(conn)) {
2565 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2566 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2567 "info level (0x%x) on IPC$.\n",
2568 (unsigned int)info_level));
2569 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2570 return;
2574 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2575 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2576 DEBUG(0,("call_trans2qfsinfo: encryption required "
2577 "and info level 0x%x sent.\n",
2578 (unsigned int)info_level));
2579 exit_server_cleanly("encryption required "
2580 "on connection");
2581 return;
2585 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2587 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2588 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2589 reply_doserror(req, ERRSRV, ERRinvdevice);
2590 return;
2593 *ppdata = (char *)SMB_REALLOC(
2594 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2595 if (*ppdata == NULL ) {
2596 reply_nterror(req, NT_STATUS_NO_MEMORY);
2597 return;
2600 pdata = *ppdata;
2601 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2602 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2604 switch (info_level) {
2605 case SMB_INFO_ALLOCATION:
2607 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2608 data_len = 18;
2609 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2610 reply_unixerror(req, ERRHRD, ERRgeneral);
2611 return;
2614 block_size = lp_block_size(snum);
2615 if (bsize < block_size) {
2616 SMB_BIG_UINT factor = block_size/bsize;
2617 bsize = block_size;
2618 dsize /= factor;
2619 dfree /= factor;
2621 if (bsize > block_size) {
2622 SMB_BIG_UINT factor = bsize/block_size;
2623 bsize = block_size;
2624 dsize *= factor;
2625 dfree *= factor;
2627 bytes_per_sector = 512;
2628 sectors_per_unit = bsize/bytes_per_sector;
2630 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2631 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2632 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2634 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2635 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2636 SIVAL(pdata,l1_cUnit,dsize);
2637 SIVAL(pdata,l1_cUnitAvail,dfree);
2638 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2639 break;
2642 case SMB_INFO_VOLUME:
2643 /* Return volume name */
2645 * Add volume serial number - hash of a combination of
2646 * the called hostname and the service name.
2648 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2650 * Win2k3 and previous mess this up by sending a name length
2651 * one byte short. I believe only older clients (OS/2 Win9x) use
2652 * this call so try fixing this by adding a terminating null to
2653 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2655 len = srvstr_push(
2656 pdata, req->flags2,
2657 pdata+l2_vol_szVolLabel, vname,
2658 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2659 STR_NOALIGN|STR_TERMINATE);
2660 SCVAL(pdata,l2_vol_cch,len);
2661 data_len = l2_vol_szVolLabel + len;
2662 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2663 (unsigned)st.st_ctime, len, vname));
2664 break;
2666 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2667 case SMB_FS_ATTRIBUTE_INFORMATION:
2669 additional_flags = 0;
2670 #if defined(HAVE_SYS_QUOTAS)
2671 additional_flags |= FILE_VOLUME_QUOTAS;
2672 #endif
2674 if(lp_nt_acl_support(SNUM(conn))) {
2675 additional_flags |= FILE_PERSISTENT_ACLS;
2678 /* Capabilities are filled in at connection time through STATVFS call */
2679 additional_flags |= conn->fs_capabilities;
2681 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2682 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2683 additional_flags); /* FS ATTRIBUTES */
2685 SIVAL(pdata,4,255); /* Max filename component length */
2686 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2687 and will think we can't do long filenames */
2688 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2689 PTR_DIFF(end_data, pdata+12),
2690 STR_UNICODE);
2691 SIVAL(pdata,8,len);
2692 data_len = 12 + len;
2693 break;
2695 case SMB_QUERY_FS_LABEL_INFO:
2696 case SMB_FS_LABEL_INFORMATION:
2697 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2698 PTR_DIFF(end_data, pdata+4), 0);
2699 data_len = 4 + len;
2700 SIVAL(pdata,0,len);
2701 break;
2703 case SMB_QUERY_FS_VOLUME_INFO:
2704 case SMB_FS_VOLUME_INFORMATION:
2707 * Add volume serial number - hash of a combination of
2708 * the called hostname and the service name.
2710 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2711 (str_checksum(get_local_machine_name())<<16));
2713 /* Max label len is 32 characters. */
2714 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2715 PTR_DIFF(end_data, pdata+18),
2716 STR_UNICODE);
2717 SIVAL(pdata,12,len);
2718 data_len = 18+len;
2720 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2721 (int)strlen(vname),vname, lp_servicename(snum)));
2722 break;
2724 case SMB_QUERY_FS_SIZE_INFO:
2725 case SMB_FS_SIZE_INFORMATION:
2727 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2728 data_len = 24;
2729 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2730 reply_unixerror(req, ERRHRD, ERRgeneral);
2731 return;
2733 block_size = lp_block_size(snum);
2734 if (bsize < block_size) {
2735 SMB_BIG_UINT factor = block_size/bsize;
2736 bsize = block_size;
2737 dsize /= factor;
2738 dfree /= factor;
2740 if (bsize > block_size) {
2741 SMB_BIG_UINT factor = bsize/block_size;
2742 bsize = block_size;
2743 dsize *= factor;
2744 dfree *= factor;
2746 bytes_per_sector = 512;
2747 sectors_per_unit = bsize/bytes_per_sector;
2748 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2749 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2750 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2751 SBIG_UINT(pdata,0,dsize);
2752 SBIG_UINT(pdata,8,dfree);
2753 SIVAL(pdata,16,sectors_per_unit);
2754 SIVAL(pdata,20,bytes_per_sector);
2755 break;
2758 case SMB_FS_FULL_SIZE_INFORMATION:
2760 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2761 data_len = 32;
2762 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2763 reply_unixerror(req, ERRHRD, ERRgeneral);
2764 return;
2766 block_size = lp_block_size(snum);
2767 if (bsize < block_size) {
2768 SMB_BIG_UINT factor = block_size/bsize;
2769 bsize = block_size;
2770 dsize /= factor;
2771 dfree /= factor;
2773 if (bsize > block_size) {
2774 SMB_BIG_UINT factor = bsize/block_size;
2775 bsize = block_size;
2776 dsize *= factor;
2777 dfree *= factor;
2779 bytes_per_sector = 512;
2780 sectors_per_unit = bsize/bytes_per_sector;
2781 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2782 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2783 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2784 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2785 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2786 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2787 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2788 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2789 break;
2792 case SMB_QUERY_FS_DEVICE_INFO:
2793 case SMB_FS_DEVICE_INFORMATION:
2794 data_len = 8;
2795 SIVAL(pdata,0,0); /* dev type */
2796 SIVAL(pdata,4,0); /* characteristics */
2797 break;
2799 #ifdef HAVE_SYS_QUOTAS
2800 case SMB_FS_QUOTA_INFORMATION:
2802 * what we have to send --metze:
2804 * Unknown1: 24 NULL bytes
2805 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2806 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2807 * Quota Flags: 2 byte :
2808 * Unknown3: 6 NULL bytes
2810 * 48 bytes total
2812 * details for Quota Flags:
2814 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2815 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2816 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2817 * 0x0001 Enable Quotas: enable quota for this fs
2821 /* we need to fake up a fsp here,
2822 * because its not send in this call
2824 files_struct fsp;
2825 SMB_NTQUOTA_STRUCT quotas;
2827 ZERO_STRUCT(fsp);
2828 ZERO_STRUCT(quotas);
2830 fsp.conn = conn;
2831 fsp.fnum = -1;
2833 /* access check */
2834 if (current_user.ut.uid != 0) {
2835 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2836 lp_servicename(SNUM(conn)),conn->user));
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,(SMB_BIG_UINT)0);
2853 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2854 SBIG_UINT(pdata,16,(SMB_BIG_UINT)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,((SMB_BIG_UINT)(
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 current_user.nt_user_token)) {
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 current_user.nt_user_token)) {
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 + (current_user.ut.ngroups * 8)
3021 /* groups list */
3022 + (current_user.nt_user_token->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, (SMB_BIG_UINT)current_user.ut.uid);
3029 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3032 if (data_len >= max_data_bytes) {
3033 /* Potential overflow, skip the GIDs and SIDs. */
3035 SIVAL(pdata, 24, 0); /* num_groups */
3036 SIVAL(pdata, 28, 0); /* num_sids */
3037 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3038 SIVAL(pdata, 36, 0); /* reserved */
3040 data_len = 40;
3041 break;
3044 SIVAL(pdata, 24, current_user.ut.ngroups);
3045 SIVAL(pdata, 28,
3046 current_user.nt_user_token->num_sids);
3048 /* We walk the SID list twice, but this call is fairly
3049 * infrequent, and I don't expect that it's performance
3050 * sensitive -- jpeach
3052 for (i = 0, sid_bytes = 0;
3053 i < current_user.nt_user_token->num_sids; ++i) {
3054 sid_bytes += ndr_size_dom_sid(
3055 &current_user.nt_user_token->user_sids[i], 0);
3058 /* SID list byte count */
3059 SIVAL(pdata, 32, sid_bytes);
3061 /* 4 bytes pad/reserved - must be zero */
3062 SIVAL(pdata, 36, 0);
3063 data_len = 40;
3065 /* GID list */
3066 for (i = 0; i < current_user.ut.ngroups; ++i) {
3067 SBIG_UINT(pdata, data_len,
3068 (SMB_BIG_UINT)current_user.ut.groups[i]);
3069 data_len += 8;
3072 /* SID list */
3073 for (i = 0;
3074 i < current_user.nt_user_token->num_sids; ++i) {
3075 int sid_len = ndr_size_dom_sid(
3076 &current_user.nt_user_token->user_sids[i], 0);
3078 sid_linearize(pdata + data_len, sid_len,
3079 &current_user.nt_user_token->user_sids[i]);
3080 data_len += sid_len;
3083 break;
3086 case SMB_MAC_QUERY_FS_INFO:
3088 * Thursby MAC extension... ONLY on NTFS filesystems
3089 * once we do streams then we don't need this
3091 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3092 data_len = 88;
3093 SIVAL(pdata,84,0x100); /* Don't support mac... */
3094 break;
3096 /* drop through */
3097 default:
3098 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3099 return;
3103 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3104 max_data_bytes);
3106 DEBUG( 4, ( "%s info_level = %d\n",
3107 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3109 return;
3112 /****************************************************************************
3113 Reply to a TRANS2_SETFSINFO (set filesystem info).
3114 ****************************************************************************/
3116 static void call_trans2setfsinfo(connection_struct *conn,
3117 struct smb_request *req,
3118 char **pparams, int total_params,
3119 char **ppdata, int total_data,
3120 unsigned int max_data_bytes)
3122 char *pdata = *ppdata;
3123 char *params = *pparams;
3124 uint16 info_level;
3126 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3128 /* */
3129 if (total_params < 4) {
3130 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3131 total_params));
3132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3133 return;
3136 info_level = SVAL(params,2);
3138 if (IS_IPC(conn)) {
3139 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3140 info_level != SMB_SET_CIFS_UNIX_INFO) {
3141 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3142 "info level (0x%x) on IPC$.\n",
3143 (unsigned int)info_level));
3144 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3145 return;
3149 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3150 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3151 DEBUG(0,("call_trans2setfsinfo: encryption required "
3152 "and info level 0x%x sent.\n",
3153 (unsigned int)info_level));
3154 exit_server_cleanly("encryption required "
3155 "on connection");
3156 return;
3160 switch(info_level) {
3161 case SMB_SET_CIFS_UNIX_INFO:
3163 uint16 client_unix_major;
3164 uint16 client_unix_minor;
3165 uint32 client_unix_cap_low;
3166 uint32 client_unix_cap_high;
3168 if (!lp_unix_extensions()) {
3169 reply_nterror(req,
3170 NT_STATUS_INVALID_LEVEL);
3171 return;
3174 /* There should be 12 bytes of capabilities set. */
3175 if (total_data < 8) {
3176 reply_nterror(
3177 req,
3178 NT_STATUS_INVALID_PARAMETER);
3179 return;
3181 client_unix_major = SVAL(pdata,0);
3182 client_unix_minor = SVAL(pdata,2);
3183 client_unix_cap_low = IVAL(pdata,4);
3184 client_unix_cap_high = IVAL(pdata,8);
3185 /* Just print these values for now. */
3186 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3187 cap_low = 0x%x, cap_high = 0x%x\n",
3188 (unsigned int)client_unix_major,
3189 (unsigned int)client_unix_minor,
3190 (unsigned int)client_unix_cap_low,
3191 (unsigned int)client_unix_cap_high ));
3193 /* Here is where we must switch to posix pathname processing... */
3194 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3195 lp_set_posix_pathnames();
3196 mangle_change_to_posix();
3199 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3200 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3201 /* Client that knows how to do posix locks,
3202 * but not posix open/mkdir operations. Set a
3203 * default type for read/write checks. */
3205 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3208 break;
3211 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3213 NTSTATUS status;
3214 size_t param_len = 0;
3215 size_t data_len = total_data;
3217 if (!lp_unix_extensions()) {
3218 reply_nterror(
3219 req,
3220 NT_STATUS_INVALID_LEVEL);
3221 return;
3224 if (lp_smb_encrypt(SNUM(conn)) == false) {
3225 reply_nterror(
3226 req,
3227 NT_STATUS_NOT_SUPPORTED);
3228 return;
3231 DEBUG( 4,("call_trans2setfsinfo: "
3232 "request transport encryption.\n"));
3234 status = srv_request_encryption_setup(conn,
3235 (unsigned char **)ppdata,
3236 &data_len,
3237 (unsigned char **)pparams,
3238 &param_len);
3240 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3241 !NT_STATUS_IS_OK(status)) {
3242 reply_nterror(req, status);
3243 return;
3246 send_trans2_replies(conn, req,
3247 *pparams,
3248 param_len,
3249 *ppdata,
3250 data_len,
3251 max_data_bytes);
3253 if (NT_STATUS_IS_OK(status)) {
3254 /* Server-side transport
3255 * encryption is now *on*. */
3256 status = srv_encryption_start(conn);
3257 if (!NT_STATUS_IS_OK(status)) {
3258 exit_server_cleanly(
3259 "Failure in setting "
3260 "up encrypted transport");
3263 return;
3266 case SMB_FS_QUOTA_INFORMATION:
3268 files_struct *fsp = NULL;
3269 SMB_NTQUOTA_STRUCT quotas;
3271 ZERO_STRUCT(quotas);
3273 /* access check */
3274 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3275 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3276 lp_servicename(SNUM(conn)),conn->user));
3277 reply_doserror(req, ERRSRV, ERRaccess);
3278 return;
3281 /* note: normaly there're 48 bytes,
3282 * but we didn't use the last 6 bytes for now
3283 * --metze
3285 fsp = file_fsp(SVAL(params,0));
3286 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3287 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3288 reply_nterror(
3289 req, NT_STATUS_INVALID_HANDLE);
3290 return;
3293 if (total_data < 42) {
3294 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3295 total_data));
3296 reply_nterror(
3297 req,
3298 NT_STATUS_INVALID_PARAMETER);
3299 return;
3302 /* unknown_1 24 NULL bytes in pdata*/
3304 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3305 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3306 #ifdef LARGE_SMB_OFF_T
3307 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3308 #else /* LARGE_SMB_OFF_T */
3309 if ((IVAL(pdata,28) != 0)&&
3310 ((quotas.softlim != 0xFFFFFFFF)||
3311 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3312 /* more than 32 bits? */
3313 reply_nterror(
3314 req,
3315 NT_STATUS_INVALID_PARAMETER);
3316 return;
3318 #endif /* LARGE_SMB_OFF_T */
3320 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3321 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3322 #ifdef LARGE_SMB_OFF_T
3323 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3324 #else /* LARGE_SMB_OFF_T */
3325 if ((IVAL(pdata,36) != 0)&&
3326 ((quotas.hardlim != 0xFFFFFFFF)||
3327 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3328 /* more than 32 bits? */
3329 reply_nterror(
3330 req,
3331 NT_STATUS_INVALID_PARAMETER);
3332 return;
3334 #endif /* LARGE_SMB_OFF_T */
3336 /* quota_flags 2 bytes **/
3337 quotas.qflags = SVAL(pdata,40);
3339 /* unknown_2 6 NULL bytes follow*/
3341 /* now set the quotas */
3342 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3343 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3344 reply_doserror(req, ERRSRV, ERRerror);
3345 return;
3348 break;
3350 default:
3351 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3352 info_level));
3353 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3354 return;
3355 break;
3359 * sending this reply works fine,
3360 * but I'm not sure it's the same
3361 * like windows do...
3362 * --metze
3364 reply_outbuf(req, 10, 0);
3367 #if defined(HAVE_POSIX_ACLS)
3368 /****************************************************************************
3369 Utility function to count the number of entries in a POSIX acl.
3370 ****************************************************************************/
3372 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3374 unsigned int ace_count = 0;
3375 int entry_id = SMB_ACL_FIRST_ENTRY;
3376 SMB_ACL_ENTRY_T entry;
3378 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3379 /* get_next... */
3380 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3381 entry_id = SMB_ACL_NEXT_ENTRY;
3383 ace_count++;
3385 return ace_count;
3388 /****************************************************************************
3389 Utility function to marshall a POSIX acl into wire format.
3390 ****************************************************************************/
3392 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3394 int entry_id = SMB_ACL_FIRST_ENTRY;
3395 SMB_ACL_ENTRY_T entry;
3397 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3398 SMB_ACL_TAG_T tagtype;
3399 SMB_ACL_PERMSET_T permset;
3400 unsigned char perms = 0;
3401 unsigned int own_grp;
3403 /* get_next... */
3404 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3405 entry_id = SMB_ACL_NEXT_ENTRY;
3408 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3409 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3410 return False;
3413 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3414 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3415 return False;
3418 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3419 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3420 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3422 SCVAL(pdata,1,perms);
3424 switch (tagtype) {
3425 case SMB_ACL_USER_OBJ:
3426 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3427 own_grp = (unsigned int)pst->st_uid;
3428 SIVAL(pdata,2,own_grp);
3429 SIVAL(pdata,6,0);
3430 break;
3431 case SMB_ACL_USER:
3433 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3434 if (!puid) {
3435 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3436 return False;
3438 own_grp = (unsigned int)*puid;
3439 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3440 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3441 SIVAL(pdata,2,own_grp);
3442 SIVAL(pdata,6,0);
3443 break;
3445 case SMB_ACL_GROUP_OBJ:
3446 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3447 own_grp = (unsigned int)pst->st_gid;
3448 SIVAL(pdata,2,own_grp);
3449 SIVAL(pdata,6,0);
3450 break;
3451 case SMB_ACL_GROUP:
3453 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3454 if (!pgid) {
3455 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3456 return False;
3458 own_grp = (unsigned int)*pgid;
3459 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3460 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3461 SIVAL(pdata,2,own_grp);
3462 SIVAL(pdata,6,0);
3463 break;
3465 case SMB_ACL_MASK:
3466 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3467 SIVAL(pdata,2,0xFFFFFFFF);
3468 SIVAL(pdata,6,0xFFFFFFFF);
3469 break;
3470 case SMB_ACL_OTHER:
3471 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3472 SIVAL(pdata,2,0xFFFFFFFF);
3473 SIVAL(pdata,6,0xFFFFFFFF);
3474 break;
3475 default:
3476 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3477 return False;
3479 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3482 return True;
3484 #endif
3486 /****************************************************************************
3487 Store the FILE_UNIX_BASIC info.
3488 ****************************************************************************/
3490 static char *store_file_unix_basic(connection_struct *conn,
3491 char *pdata,
3492 files_struct *fsp,
3493 const SMB_STRUCT_STAT *psbuf)
3495 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3496 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3498 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3499 pdata += 8;
3501 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3502 pdata += 8;
3504 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3505 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3506 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3507 pdata += 24;
3509 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3510 SIVAL(pdata,4,0);
3511 pdata += 8;
3513 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3514 SIVAL(pdata,4,0);
3515 pdata += 8;
3517 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3518 pdata += 4;
3520 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3521 SIVAL(pdata,4,0);
3522 pdata += 8;
3524 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3525 SIVAL(pdata,4,0);
3526 pdata += 8;
3528 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3529 pdata += 8;
3531 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3532 SIVAL(pdata,4,0);
3533 pdata += 8;
3535 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3536 SIVAL(pdata,4,0);
3537 pdata += 8;
3539 return pdata;
3542 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3543 * the chflags(2) (or equivalent) flags.
3545 * XXX: this really should be behind the VFS interface. To do this, we would
3546 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3547 * Each VFS module could then implement its own mapping as appropriate for the
3548 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3550 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3551 info2_flags_map[] =
3553 #ifdef UF_NODUMP
3554 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3555 #endif
3557 #ifdef UF_IMMUTABLE
3558 { UF_IMMUTABLE, EXT_IMMUTABLE },
3559 #endif
3561 #ifdef UF_APPEND
3562 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3563 #endif
3565 #ifdef UF_HIDDEN
3566 { UF_HIDDEN, EXT_HIDDEN },
3567 #endif
3569 /* Do not remove. We need to guarantee that this array has at least one
3570 * entry to build on HP-UX.
3572 { 0, 0 }
3576 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3577 uint32 *smb_fflags, uint32 *smb_fmask)
3579 #ifdef HAVE_STAT_ST_FLAGS
3580 int i;
3582 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3583 *smb_fmask |= info2_flags_map[i].smb_fflag;
3584 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3585 *smb_fflags |= info2_flags_map[i].smb_fflag;
3588 #endif /* HAVE_STAT_ST_FLAGS */
3591 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3592 const uint32 smb_fflags,
3593 const uint32 smb_fmask,
3594 int *stat_fflags)
3596 #ifdef HAVE_STAT_ST_FLAGS
3597 uint32 max_fmask = 0;
3598 int i;
3600 *stat_fflags = psbuf->st_flags;
3602 /* For each flags requested in smb_fmask, check the state of the
3603 * corresponding flag in smb_fflags and set or clear the matching
3604 * stat flag.
3607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3608 max_fmask |= info2_flags_map[i].smb_fflag;
3609 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3610 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3611 *stat_fflags |= info2_flags_map[i].stat_fflag;
3612 } else {
3613 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3618 /* If smb_fmask is asking to set any bits that are not supported by
3619 * our flag mappings, we should fail.
3621 if ((smb_fmask & max_fmask) != smb_fmask) {
3622 return False;
3625 return True;
3626 #else
3627 return False;
3628 #endif /* HAVE_STAT_ST_FLAGS */
3632 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3633 * of file flags and birth (create) time.
3635 static char *store_file_unix_basic_info2(connection_struct *conn,
3636 char *pdata,
3637 files_struct *fsp,
3638 const SMB_STRUCT_STAT *psbuf)
3640 uint32 file_flags = 0;
3641 uint32 flags_mask = 0;
3643 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3645 /* Create (birth) time 64 bit */
3646 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3647 pdata += 8;
3649 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3650 SIVAL(pdata, 0, file_flags); /* flags */
3651 SIVAL(pdata, 4, flags_mask); /* mask */
3652 pdata += 8;
3654 return pdata;
3657 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3658 const struct stream_struct *streams,
3659 char *data,
3660 unsigned int max_data_bytes,
3661 unsigned int *data_size)
3663 unsigned int i;
3664 unsigned int ofs = 0;
3666 for (i=0; i<num_streams; i++) {
3667 unsigned int next_offset;
3668 size_t namelen;
3669 smb_ucs2_t *namebuf;
3671 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3672 streams[i].name);
3674 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3675 return NT_STATUS_INVALID_PARAMETER;
3679 * name_buf is now null-terminated, we need to marshall as not
3680 * terminated
3683 namelen -= 2;
3685 if (ofs + 24 + namelen > max_data_bytes) {
3686 TALLOC_FREE(namebuf);
3687 return NT_STATUS_BUFFER_TOO_SMALL;
3690 SIVAL(data, ofs+4, namelen);
3691 SOFF_T(data, ofs+8, streams[i].size);
3692 SOFF_T(data, ofs+16, streams[i].alloc_size);
3693 memcpy(data+ofs+24, namebuf, namelen);
3694 TALLOC_FREE(namebuf);
3696 next_offset = ofs + 24 + namelen;
3698 if (i == num_streams-1) {
3699 SIVAL(data, ofs, 0);
3701 else {
3702 unsigned int align = ndr_align_size(next_offset, 8);
3704 if (next_offset + align > max_data_bytes) {
3705 return NT_STATUS_BUFFER_TOO_SMALL;
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 smb_np_struct *p_pipe = NULL;
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 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3752 if (p_pipe == NULL) {
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 SMB_BIG_UINT 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 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3832 char *lock_data = NULL;
3833 bool ms_dfs_link = false;
3834 TALLOC_CTX *ctx = talloc_tos();
3836 if (!params) {
3837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3838 return;
3841 ZERO_STRUCT(sbuf);
3842 ZERO_STRUCT(write_time_ts);
3844 if (tran_call == TRANSACT2_QFILEINFO) {
3845 if (total_params < 4) {
3846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3847 return;
3850 if (IS_IPC(conn)) {
3851 call_trans2qpipeinfo(conn, req, tran_call,
3852 pparams, total_params,
3853 ppdata, total_data,
3854 max_data_bytes);
3855 return;
3858 fsp = file_fsp(SVAL(params,0));
3859 info_level = SVAL(params,2);
3861 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3863 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3864 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3865 return;
3868 /* Initial check for valid fsp ptr. */
3869 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3870 return;
3873 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3874 if (!fname) {
3875 reply_nterror(req, NT_STATUS_NO_MEMORY);
3876 return;
3879 if(fsp->fake_file_handle) {
3881 * This is actually for the QUOTA_FAKE_FILE --metze
3884 /* We know this name is ok, it's already passed the checks. */
3886 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3888 * This is actually a QFILEINFO on a directory
3889 * handle (returned from an NT SMB). NT5.0 seems
3890 * to do this call. JRA.
3893 if (INFO_LEVEL_IS_UNIX(info_level)) {
3894 /* Always do lstat for UNIX calls. */
3895 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3896 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3897 reply_unixerror(req,ERRDOS,ERRbadpath);
3898 return;
3900 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3901 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3902 reply_unixerror(req, ERRDOS, ERRbadpath);
3903 return;
3906 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3907 get_file_infos(fileid, &delete_pending, &write_time_ts);
3908 } else {
3910 * Original code - this is an open file.
3912 if (!check_fsp(conn, req, fsp, &current_user)) {
3913 return;
3916 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3917 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3918 reply_unixerror(req, ERRDOS, ERRbadfid);
3919 return;
3921 pos = fsp->fh->position_information;
3922 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3923 get_file_infos(fileid, &delete_pending, &write_time_ts);
3924 access_mask = fsp->access_mask;
3927 } else {
3928 NTSTATUS status = NT_STATUS_OK;
3930 /* qpathinfo */
3931 if (total_params < 7) {
3932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3933 return;
3936 info_level = SVAL(params,0);
3938 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3940 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3942 return;
3945 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3946 total_params - 6,
3947 STR_TERMINATE, &status);
3948 if (!NT_STATUS_IS_OK(status)) {
3949 reply_nterror(req, status);
3950 return;
3953 status = resolve_dfspath(ctx,
3954 conn,
3955 req->flags2 & FLAGS2_DFS_PATHNAMES,
3956 fname,
3957 &fname);
3958 if (!NT_STATUS_IS_OK(status)) {
3959 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3960 reply_botherror(req,
3961 NT_STATUS_PATH_NOT_COVERED,
3962 ERRSRV, ERRbadpath);
3964 reply_nterror(req, status);
3965 return;
3968 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3969 if (!NT_STATUS_IS_OK(status)) {
3970 reply_nterror(req, status);
3971 return;
3973 status = check_name(conn, fname);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3976 reply_nterror(req, status);
3977 return;
3980 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3981 && is_ntfs_stream_name(fname)) {
3982 char *base;
3983 SMB_STRUCT_STAT bsbuf;
3985 status = split_ntfs_stream_name(talloc_tos(), fname,
3986 &base, NULL);
3987 if (!NT_STATUS_IS_OK(status)) {
3988 DEBUG(10, ("create_file_unixpath: "
3989 "split_ntfs_stream_name failed: %s\n",
3990 nt_errstr(status)));
3991 reply_nterror(req, status);
3992 return;
3995 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3997 if (INFO_LEVEL_IS_UNIX(info_level)) {
3998 /* Always do lstat for UNIX calls. */
3999 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4000 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4001 reply_unixerror(req,ERRDOS,ERRbadpath);
4002 return;
4004 } else {
4005 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4006 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4007 reply_unixerror(req,ERRDOS,ERRbadpath);
4008 return;
4012 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4013 get_file_infos(fileid, &delete_pending, NULL);
4014 if (delete_pending) {
4015 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4016 return;
4020 if (INFO_LEVEL_IS_UNIX(info_level)) {
4021 /* Always do lstat for UNIX calls. */
4022 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4023 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4024 reply_unixerror(req, ERRDOS, ERRbadpath);
4025 return;
4028 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4029 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4031 if (!ms_dfs_link) {
4032 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4033 reply_unixerror(req, ERRDOS, ERRbadpath);
4034 return;
4038 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4039 get_file_infos(fileid, &delete_pending, &write_time_ts);
4040 if (delete_pending) {
4041 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4042 return;
4046 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4047 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4048 return;
4051 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4052 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4054 p = strrchr_m(fname,'/');
4055 if (!p)
4056 base_name = fname;
4057 else
4058 base_name = p+1;
4060 if (ms_dfs_link) {
4061 mode = dos_mode_msdfs(conn,fname,&sbuf);
4062 } else {
4063 mode = dos_mode(conn,fname,&sbuf);
4065 if (!mode)
4066 mode = FILE_ATTRIBUTE_NORMAL;
4068 nlink = sbuf.st_nlink;
4070 if (nlink && (mode&aDIR)) {
4071 nlink = 1;
4074 if ((nlink > 0) && delete_pending) {
4075 nlink -= 1;
4078 fullpathname = fname;
4079 if (!(mode & aDIR))
4080 file_size = get_file_size(sbuf);
4082 /* Pull out any data sent here before we realloc. */
4083 switch (info_level) {
4084 case SMB_INFO_QUERY_EAS_FROM_LIST:
4086 /* Pull any EA list from the data portion. */
4087 uint32 ea_size;
4089 if (total_data < 4) {
4090 reply_nterror(
4091 req, NT_STATUS_INVALID_PARAMETER);
4092 return;
4094 ea_size = IVAL(pdata,0);
4096 if (total_data > 0 && ea_size != total_data) {
4097 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4098 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4099 reply_nterror(
4100 req, NT_STATUS_INVALID_PARAMETER);
4101 return;
4104 if (!lp_ea_support(SNUM(conn))) {
4105 reply_doserror(req, ERRDOS,
4106 ERReasnotsupported);
4107 return;
4110 /* Pull out the list of names. */
4111 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4112 if (!ea_list) {
4113 reply_nterror(
4114 req, NT_STATUS_INVALID_PARAMETER);
4115 return;
4117 break;
4120 case SMB_QUERY_POSIX_LOCK:
4122 if (fsp == NULL || fsp->fh->fd == -1) {
4123 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4124 return;
4127 if (total_data != POSIX_LOCK_DATA_SIZE) {
4128 reply_nterror(
4129 req, NT_STATUS_INVALID_PARAMETER);
4130 return;
4133 /* Copy the lock range data. */
4134 lock_data = (char *)TALLOC_MEMDUP(
4135 ctx, pdata, total_data);
4136 if (!lock_data) {
4137 reply_nterror(req, NT_STATUS_NO_MEMORY);
4138 return;
4141 default:
4142 break;
4145 *pparams = (char *)SMB_REALLOC(*pparams,2);
4146 if (*pparams == NULL) {
4147 reply_nterror(req, NT_STATUS_NO_MEMORY);
4148 return;
4150 params = *pparams;
4151 SSVAL(params,0,0);
4152 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4153 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4154 if (*ppdata == NULL ) {
4155 reply_nterror(req, NT_STATUS_NO_MEMORY);
4156 return;
4158 pdata = *ppdata;
4159 dstart = pdata;
4160 dend = dstart + data_size - 1;
4162 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4163 mtime_ts = get_mtimespec(&sbuf);
4164 atime_ts = get_atimespec(&sbuf);
4166 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4168 if (!fsp) {
4169 /* Do we have this path open ? */
4170 files_struct *fsp1;
4171 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4172 fsp1 = file_find_di_first(fileid);
4173 if (fsp1 && fsp1->initial_allocation_size) {
4174 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4178 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4179 mtime_ts = write_time_ts;
4182 if (lp_dos_filetime_resolution(SNUM(conn))) {
4183 dos_filetime_timespec(&create_time_ts);
4184 dos_filetime_timespec(&mtime_ts);
4185 dos_filetime_timespec(&atime_ts);
4188 create_time = convert_timespec_to_time_t(create_time_ts);
4189 mtime = convert_timespec_to_time_t(mtime_ts);
4190 atime = convert_timespec_to_time_t(atime_ts);
4192 /* NT expects the name to be in an exact form of the *full*
4193 filename. See the trans2 torture test */
4194 if (ISDOT(base_name)) {
4195 dos_fname = talloc_strdup(ctx, "\\");
4196 if (!dos_fname) {
4197 reply_nterror(req, NT_STATUS_NO_MEMORY);
4198 return;
4200 } else {
4201 dos_fname = talloc_asprintf(ctx,
4202 "\\%s",
4203 fname);
4204 if (!dos_fname) {
4205 reply_nterror(req, NT_STATUS_NO_MEMORY);
4206 return;
4208 string_replace(dos_fname, '/', '\\');
4211 switch (info_level) {
4212 case SMB_INFO_STANDARD:
4213 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4214 data_size = 22;
4215 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4216 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4217 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4218 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4219 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4220 SSVAL(pdata,l1_attrFile,mode);
4221 break;
4223 case SMB_INFO_QUERY_EA_SIZE:
4225 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4226 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4227 data_size = 26;
4228 srv_put_dos_date2(pdata,0,create_time);
4229 srv_put_dos_date2(pdata,4,atime);
4230 srv_put_dos_date2(pdata,8,mtime); /* write time */
4231 SIVAL(pdata,12,(uint32)file_size);
4232 SIVAL(pdata,16,(uint32)allocation_size);
4233 SSVAL(pdata,20,mode);
4234 SIVAL(pdata,22,ea_size);
4235 break;
4238 case SMB_INFO_IS_NAME_VALID:
4239 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4240 if (tran_call == TRANSACT2_QFILEINFO) {
4241 /* os/2 needs this ? really ?*/
4242 reply_doserror(req, ERRDOS, ERRbadfunc);
4243 return;
4245 data_size = 0;
4246 param_size = 0;
4247 break;
4249 case SMB_INFO_QUERY_EAS_FROM_LIST:
4251 size_t total_ea_len = 0;
4252 struct ea_list *ea_file_list = NULL;
4254 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4256 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4257 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4259 if (!ea_list || (total_ea_len > data_size)) {
4260 data_size = 4;
4261 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4262 break;
4265 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4266 break;
4269 case SMB_INFO_QUERY_ALL_EAS:
4271 /* We have data_size bytes to put EA's into. */
4272 size_t total_ea_len = 0;
4274 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4276 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4277 if (!ea_list || (total_ea_len > data_size)) {
4278 data_size = 4;
4279 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4280 break;
4283 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4284 break;
4287 case SMB_FILE_BASIC_INFORMATION:
4288 case SMB_QUERY_FILE_BASIC_INFO:
4290 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4292 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4293 } else {
4294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4295 data_size = 40;
4296 SIVAL(pdata,36,0);
4298 put_long_date_timespec(pdata,create_time_ts);
4299 put_long_date_timespec(pdata+8,atime_ts);
4300 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4301 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4302 SIVAL(pdata,32,mode);
4304 DEBUG(5,("SMB_QFBI - "));
4305 DEBUG(5,("create: %s ", ctime(&create_time)));
4306 DEBUG(5,("access: %s ", ctime(&atime)));
4307 DEBUG(5,("write: %s ", ctime(&mtime)));
4308 DEBUG(5,("change: %s ", ctime(&mtime)));
4309 DEBUG(5,("mode: %x\n", mode));
4310 break;
4312 case SMB_FILE_STANDARD_INFORMATION:
4313 case SMB_QUERY_FILE_STANDARD_INFO:
4315 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4316 data_size = 24;
4317 SOFF_T(pdata,0,allocation_size);
4318 SOFF_T(pdata,8,file_size);
4319 SIVAL(pdata,16,nlink);
4320 SCVAL(pdata,20,delete_pending?1:0);
4321 SCVAL(pdata,21,(mode&aDIR)?1:0);
4322 SSVAL(pdata,22,0); /* Padding. */
4323 break;
4325 case SMB_FILE_EA_INFORMATION:
4326 case SMB_QUERY_FILE_EA_INFO:
4328 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4330 data_size = 4;
4331 SIVAL(pdata,0,ea_size);
4332 break;
4335 /* Get the 8.3 name - used if NT SMB was negotiated. */
4336 case SMB_QUERY_FILE_ALT_NAME_INFO:
4337 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4339 char mangled_name[13];
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4341 if (!name_to_8_3(base_name,mangled_name,
4342 True,conn->params)) {
4343 reply_nterror(
4344 req,
4345 NT_STATUS_NO_MEMORY);
4347 len = srvstr_push(dstart, req->flags2,
4348 pdata+4, mangled_name,
4349 PTR_DIFF(dend, pdata+4),
4350 STR_UNICODE);
4351 data_size = 4 + len;
4352 SIVAL(pdata,0,len);
4353 break;
4356 case SMB_QUERY_FILE_NAME_INFO:
4358 this must be *exactly* right for ACLs on mapped drives to work
4360 len = srvstr_push(dstart, req->flags2,
4361 pdata+4, dos_fname,
4362 PTR_DIFF(dend, pdata+4),
4363 STR_UNICODE);
4364 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4365 data_size = 4 + len;
4366 SIVAL(pdata,0,len);
4367 break;
4369 case SMB_FILE_ALLOCATION_INFORMATION:
4370 case SMB_QUERY_FILE_ALLOCATION_INFO:
4371 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4372 data_size = 8;
4373 SOFF_T(pdata,0,allocation_size);
4374 break;
4376 case SMB_FILE_END_OF_FILE_INFORMATION:
4377 case SMB_QUERY_FILE_END_OF_FILEINFO:
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4379 data_size = 8;
4380 SOFF_T(pdata,0,file_size);
4381 break;
4383 case SMB_QUERY_FILE_ALL_INFO:
4384 case SMB_FILE_ALL_INFORMATION:
4386 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4388 put_long_date_timespec(pdata,create_time_ts);
4389 put_long_date_timespec(pdata+8,atime_ts);
4390 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4391 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4392 SIVAL(pdata,32,mode);
4393 SIVAL(pdata,36,0); /* padding. */
4394 pdata += 40;
4395 SOFF_T(pdata,0,allocation_size);
4396 SOFF_T(pdata,8,file_size);
4397 SIVAL(pdata,16,nlink);
4398 SCVAL(pdata,20,delete_pending);
4399 SCVAL(pdata,21,(mode&aDIR)?1:0);
4400 SSVAL(pdata,22,0);
4401 pdata += 24;
4402 SIVAL(pdata,0,ea_size);
4403 pdata += 4; /* EA info */
4404 len = srvstr_push(dstart, req->flags2,
4405 pdata+4, dos_fname,
4406 PTR_DIFF(dend, pdata+4),
4407 STR_UNICODE);
4408 SIVAL(pdata,0,len);
4409 pdata += 4 + len;
4410 data_size = PTR_DIFF(pdata,(*ppdata));
4411 break;
4413 case SMB_FILE_INTERNAL_INFORMATION:
4414 /* This should be an index number - looks like
4415 dev/ino to me :-)
4417 I think this causes us to fail the IFSKIT
4418 BasicFileInformationTest. -tpot */
4420 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4421 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4422 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4423 data_size = 8;
4424 break;
4426 case SMB_FILE_ACCESS_INFORMATION:
4427 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4428 SIVAL(pdata,0,access_mask);
4429 data_size = 4;
4430 break;
4432 case SMB_FILE_NAME_INFORMATION:
4433 /* Pathname with leading '\'. */
4435 size_t byte_len;
4436 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4437 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4438 SIVAL(pdata,0,byte_len);
4439 data_size = 4 + byte_len;
4440 break;
4443 case SMB_FILE_DISPOSITION_INFORMATION:
4444 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4445 data_size = 1;
4446 SCVAL(pdata,0,delete_pending);
4447 break;
4449 case SMB_FILE_POSITION_INFORMATION:
4450 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4451 data_size = 8;
4452 SOFF_T(pdata,0,pos);
4453 break;
4455 case SMB_FILE_MODE_INFORMATION:
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4457 SIVAL(pdata,0,mode);
4458 data_size = 4;
4459 break;
4461 case SMB_FILE_ALIGNMENT_INFORMATION:
4462 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4463 SIVAL(pdata,0,0); /* No alignment needed. */
4464 data_size = 4;
4465 break;
4468 * NT4 server just returns "invalid query" to this - if we try
4469 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4470 * want this. JRA.
4472 /* The first statement above is false - verified using Thursby
4473 * client against NT4 -- gcolley.
4475 case SMB_QUERY_FILE_STREAM_INFO:
4476 case SMB_FILE_STREAM_INFORMATION: {
4477 unsigned int num_streams;
4478 struct stream_struct *streams;
4479 NTSTATUS status;
4481 DEBUG(10,("call_trans2qfilepathinfo: "
4482 "SMB_FILE_STREAM_INFORMATION\n"));
4484 status = SMB_VFS_STREAMINFO(
4485 conn, fsp, fname, talloc_tos(),
4486 &num_streams, &streams);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 DEBUG(10, ("could not get stream info: %s\n",
4490 nt_errstr(status)));
4491 reply_nterror(req, status);
4492 return;
4495 status = marshall_stream_info(num_streams, streams,
4496 pdata, max_data_bytes,
4497 &data_size);
4499 if (!NT_STATUS_IS_OK(status)) {
4500 DEBUG(10, ("marshall_stream_info failed: %s\n",
4501 nt_errstr(status)));
4502 reply_nterror(req, status);
4503 return;
4506 TALLOC_FREE(streams);
4508 break;
4510 case SMB_QUERY_COMPRESSION_INFO:
4511 case SMB_FILE_COMPRESSION_INFORMATION:
4512 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4513 SOFF_T(pdata,0,file_size);
4514 SIVAL(pdata,8,0); /* ??? */
4515 SIVAL(pdata,12,0); /* ??? */
4516 data_size = 16;
4517 break;
4519 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4520 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4521 put_long_date_timespec(pdata,create_time_ts);
4522 put_long_date_timespec(pdata+8,atime_ts);
4523 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4524 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4525 SOFF_T(pdata,32,allocation_size);
4526 SOFF_T(pdata,40,file_size);
4527 SIVAL(pdata,48,mode);
4528 SIVAL(pdata,52,0); /* ??? */
4529 data_size = 56;
4530 break;
4532 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4533 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4534 SIVAL(pdata,0,mode);
4535 SIVAL(pdata,4,0);
4536 data_size = 8;
4537 break;
4540 * CIFS UNIX Extensions.
4543 case SMB_QUERY_FILE_UNIX_BASIC:
4545 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4546 data_size = PTR_DIFF(pdata,(*ppdata));
4549 int i;
4550 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4552 for (i=0; i<100; i++)
4553 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4554 DEBUG(4,("\n"));
4557 break;
4559 case SMB_QUERY_FILE_UNIX_INFO2:
4561 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4562 data_size = PTR_DIFF(pdata,(*ppdata));
4565 int i;
4566 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4568 for (i=0; i<100; i++)
4569 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4570 DEBUG(4,("\n"));
4573 break;
4575 case SMB_QUERY_FILE_UNIX_LINK:
4577 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4579 if (!buffer) {
4580 reply_nterror(req, NT_STATUS_NO_MEMORY);
4581 return;
4584 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4585 #ifdef S_ISLNK
4586 if(!S_ISLNK(sbuf.st_mode)) {
4587 reply_unixerror(req, ERRSRV,
4588 ERRbadlink);
4589 return;
4591 #else
4592 reply_unixerror(req, ERRDOS, ERRbadlink);
4593 return;
4594 #endif
4595 len = SMB_VFS_READLINK(conn,fullpathname,
4596 buffer, PATH_MAX);
4597 if (len == -1) {
4598 reply_unixerror(req, ERRDOS,
4599 ERRnoaccess);
4600 return;
4602 buffer[len] = 0;
4603 len = srvstr_push(dstart, req->flags2,
4604 pdata, buffer,
4605 PTR_DIFF(dend, pdata),
4606 STR_TERMINATE);
4607 pdata += len;
4608 data_size = PTR_DIFF(pdata,(*ppdata));
4610 break;
4613 #if defined(HAVE_POSIX_ACLS)
4614 case SMB_QUERY_POSIX_ACL:
4616 SMB_ACL_T file_acl = NULL;
4617 SMB_ACL_T def_acl = NULL;
4618 uint16 num_file_acls = 0;
4619 uint16 num_def_acls = 0;
4621 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4622 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4623 } else {
4624 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4627 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4628 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4629 fname ));
4630 reply_nterror(
4631 req,
4632 NT_STATUS_NOT_IMPLEMENTED);
4633 return;
4636 if (S_ISDIR(sbuf.st_mode)) {
4637 if (fsp && fsp->is_directory) {
4638 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4639 } else {
4640 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4642 def_acl = free_empty_sys_acl(conn, def_acl);
4645 num_file_acls = count_acl_entries(conn, file_acl);
4646 num_def_acls = count_acl_entries(conn, def_acl);
4648 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4649 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4650 data_size,
4651 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4652 SMB_POSIX_ACL_HEADER_SIZE) ));
4653 if (file_acl) {
4654 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4656 if (def_acl) {
4657 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4659 reply_nterror(
4660 req,
4661 NT_STATUS_BUFFER_TOO_SMALL);
4662 return;
4665 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4666 SSVAL(pdata,2,num_file_acls);
4667 SSVAL(pdata,4,num_def_acls);
4668 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4669 if (file_acl) {
4670 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4672 if (def_acl) {
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4675 reply_nterror(
4676 req, NT_STATUS_INTERNAL_ERROR);
4677 return;
4679 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4680 if (file_acl) {
4681 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4683 if (def_acl) {
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4686 reply_nterror(
4687 req,
4688 NT_STATUS_INTERNAL_ERROR);
4689 return;
4692 if (file_acl) {
4693 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4695 if (def_acl) {
4696 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4698 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4699 break;
4701 #endif
4704 case SMB_QUERY_POSIX_LOCK:
4706 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4707 SMB_BIG_UINT count;
4708 SMB_BIG_UINT offset;
4709 uint32 lock_pid;
4710 enum brl_type lock_type;
4712 if (total_data != POSIX_LOCK_DATA_SIZE) {
4713 reply_nterror(
4714 req, NT_STATUS_INVALID_PARAMETER);
4715 return;
4718 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4719 case POSIX_LOCK_TYPE_READ:
4720 lock_type = READ_LOCK;
4721 break;
4722 case POSIX_LOCK_TYPE_WRITE:
4723 lock_type = WRITE_LOCK;
4724 break;
4725 case POSIX_LOCK_TYPE_UNLOCK:
4726 default:
4727 /* There's no point in asking for an unlock... */
4728 reply_nterror(
4729 req,
4730 NT_STATUS_INVALID_PARAMETER);
4731 return;
4734 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4735 #if defined(HAVE_LONGLONG)
4736 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4737 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4738 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4739 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4740 #else /* HAVE_LONGLONG */
4741 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4742 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4743 #endif /* HAVE_LONGLONG */
4745 status = query_lock(fsp,
4746 &lock_pid,
4747 &count,
4748 &offset,
4749 &lock_type,
4750 POSIX_LOCK);
4752 if (ERROR_WAS_LOCK_DENIED(status)) {
4753 /* Here we need to report who has it locked... */
4754 data_size = POSIX_LOCK_DATA_SIZE;
4756 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4757 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4758 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4759 #if defined(HAVE_LONGLONG)
4760 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4761 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4762 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4763 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4764 #else /* HAVE_LONGLONG */
4765 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4766 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4767 #endif /* HAVE_LONGLONG */
4769 } else if (NT_STATUS_IS_OK(status)) {
4770 /* For success we just return a copy of what we sent
4771 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4772 data_size = POSIX_LOCK_DATA_SIZE;
4773 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4774 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4775 } else {
4776 reply_nterror(req, status);
4777 return;
4779 break;
4782 default:
4783 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4784 return;
4787 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4788 max_data_bytes);
4790 return;
4793 /****************************************************************************
4794 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4795 code.
4796 ****************************************************************************/
4798 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4799 connection_struct *conn,
4800 const char *oldname_in,
4801 const char *newname_in)
4803 SMB_STRUCT_STAT sbuf1, sbuf2;
4804 char *last_component_oldname = NULL;
4805 char *last_component_newname = NULL;
4806 char *oldname = NULL;
4807 char *newname = NULL;
4808 NTSTATUS status = NT_STATUS_OK;
4810 ZERO_STRUCT(sbuf1);
4811 ZERO_STRUCT(sbuf2);
4813 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4814 &last_component_oldname, &sbuf1);
4815 if (!NT_STATUS_IS_OK(status)) {
4816 return status;
4819 status = check_name(conn, oldname);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 return status;
4824 /* source must already exist. */
4825 if (!VALID_STAT(sbuf1)) {
4826 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4829 status = unix_convert(ctx, conn, newname_in, False, &newname,
4830 &last_component_newname, &sbuf2);
4831 if (!NT_STATUS_IS_OK(status)) {
4832 return status;
4835 status = check_name(conn, newname);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 return status;
4840 /* Disallow if newname already exists. */
4841 if (VALID_STAT(sbuf2)) {
4842 return NT_STATUS_OBJECT_NAME_COLLISION;
4845 /* No links from a directory. */
4846 if (S_ISDIR(sbuf1.st_mode)) {
4847 return NT_STATUS_FILE_IS_A_DIRECTORY;
4850 /* Ensure this is within the share. */
4851 status = check_reduced_name(conn, oldname);
4852 if (!NT_STATUS_IS_OK(status)) {
4853 return status;
4856 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4858 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4859 status = map_nt_error_from_unix(errno);
4860 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4861 nt_errstr(status), newname, oldname));
4864 return status;
4867 /****************************************************************************
4868 Deal with setting the time from any of the setfilepathinfo functions.
4869 ****************************************************************************/
4871 NTSTATUS smb_set_file_time(connection_struct *conn,
4872 files_struct *fsp,
4873 const char *fname,
4874 const SMB_STRUCT_STAT *psbuf,
4875 struct timespec ts[2],
4876 bool setting_write_time)
4878 uint32 action =
4879 FILE_NOTIFY_CHANGE_LAST_ACCESS
4880 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4882 if (!VALID_STAT(*psbuf)) {
4883 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4886 /* get some defaults (no modifications) if any info is zero or -1. */
4887 if (null_timespec(ts[0])) {
4888 ts[0] = get_atimespec(psbuf);
4889 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4892 if (null_timespec(ts[1])) {
4893 ts[1] = get_mtimespec(psbuf);
4894 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4897 if (!setting_write_time) {
4898 /* ts[1] comes from change time, not write time. */
4899 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4902 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4903 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4906 * Try and set the times of this file if
4907 * they are different from the current values.
4911 struct timespec mts = get_mtimespec(psbuf);
4912 struct timespec ats = get_atimespec(psbuf);
4913 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4914 return NT_STATUS_OK;
4918 if (setting_write_time) {
4920 * This was a setfileinfo on an open file.
4921 * NT does this a lot. We also need to
4922 * set the time here, as it can be read by
4923 * FindFirst/FindNext and with the patch for bug #2045
4924 * in smbd/fileio.c it ensures that this timestamp is
4925 * kept sticky even after a write. We save the request
4926 * away and will set it on file close and after a write. JRA.
4929 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4930 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4932 if (fsp != NULL) {
4933 if (fsp->base_fsp) {
4934 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4935 } else {
4936 set_sticky_write_time_fsp(fsp, ts[1]);
4938 } else {
4939 set_sticky_write_time_path(conn, fname,
4940 vfs_file_id_from_sbuf(conn, psbuf),
4941 ts[1]);
4945 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4947 if (fsp && fsp->base_fsp) {
4948 fname = fsp->base_fsp->fsp_name;
4951 if(file_ntimes(conn, fname, ts)!=0) {
4952 return map_nt_error_from_unix(errno);
4954 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4956 return NT_STATUS_OK;
4959 /****************************************************************************
4960 Deal with setting the dosmode from any of the setfilepathinfo functions.
4961 ****************************************************************************/
4963 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4964 const char *fname,
4965 SMB_STRUCT_STAT *psbuf,
4966 uint32 dosmode)
4968 if (!VALID_STAT(*psbuf)) {
4969 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4972 if (dosmode) {
4973 if (S_ISDIR(psbuf->st_mode)) {
4974 dosmode |= aDIR;
4975 } else {
4976 dosmode &= ~aDIR;
4980 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4982 /* check the mode isn't different, before changing it */
4983 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4985 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4986 fname, (unsigned int)dosmode ));
4988 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4989 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4990 fname, strerror(errno)));
4991 return map_nt_error_from_unix(errno);
4994 return NT_STATUS_OK;
4997 /****************************************************************************
4998 Deal with setting the size from any of the setfilepathinfo functions.
4999 ****************************************************************************/
5001 static NTSTATUS smb_set_file_size(connection_struct *conn,
5002 struct smb_request *req,
5003 files_struct *fsp,
5004 const char *fname,
5005 SMB_STRUCT_STAT *psbuf,
5006 SMB_OFF_T size)
5008 NTSTATUS status = NT_STATUS_OK;
5009 files_struct *new_fsp = NULL;
5011 if (!VALID_STAT(*psbuf)) {
5012 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5015 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5017 if (size == get_file_size(*psbuf)) {
5018 return NT_STATUS_OK;
5021 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5022 fname, (double)size ));
5024 if (fsp && fsp->fh->fd != -1) {
5025 /* Handle based call. */
5026 if (vfs_set_filelen(fsp, size) == -1) {
5027 return map_nt_error_from_unix(errno);
5029 trigger_write_time_update_immediate(fsp);
5030 return NT_STATUS_OK;
5033 status = open_file_ntcreate(conn, req, fname, psbuf,
5034 FILE_WRITE_ATTRIBUTES,
5035 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5036 FILE_OPEN,
5038 FILE_ATTRIBUTE_NORMAL,
5039 FORCE_OPLOCK_BREAK_TO_NONE,
5040 NULL, &new_fsp);
5042 if (!NT_STATUS_IS_OK(status)) {
5043 /* NB. We check for open_was_deferred in the caller. */
5044 return status;
5047 if (vfs_set_filelen(new_fsp, size) == -1) {
5048 status = map_nt_error_from_unix(errno);
5049 close_file(new_fsp,NORMAL_CLOSE);
5050 return status;
5053 trigger_write_time_update_immediate(new_fsp);
5054 close_file(new_fsp,NORMAL_CLOSE);
5055 return NT_STATUS_OK;
5058 /****************************************************************************
5059 Deal with SMB_INFO_SET_EA.
5060 ****************************************************************************/
5062 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5063 const char *pdata,
5064 int total_data,
5065 files_struct *fsp,
5066 const char *fname)
5068 struct ea_list *ea_list = NULL;
5069 TALLOC_CTX *ctx = NULL;
5070 NTSTATUS status = NT_STATUS_OK;
5072 if (total_data < 10) {
5074 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5075 length. They seem to have no effect. Bug #3212. JRA */
5077 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5078 /* We're done. We only get EA info in this call. */
5079 return NT_STATUS_OK;
5082 return NT_STATUS_INVALID_PARAMETER;
5085 if (IVAL(pdata,0) > total_data) {
5086 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5087 IVAL(pdata,0), (unsigned int)total_data));
5088 return NT_STATUS_INVALID_PARAMETER;
5091 ctx = talloc_tos();
5092 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5093 if (!ea_list) {
5094 return NT_STATUS_INVALID_PARAMETER;
5096 status = set_ea(conn, fsp, fname, ea_list);
5098 return status;
5101 /****************************************************************************
5102 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5103 ****************************************************************************/
5105 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5106 const char *pdata,
5107 int total_data,
5108 files_struct *fsp,
5109 const char *fname,
5110 SMB_STRUCT_STAT *psbuf)
5112 NTSTATUS status = NT_STATUS_OK;
5113 bool delete_on_close;
5114 uint32 dosmode = 0;
5116 if (total_data < 1) {
5117 return NT_STATUS_INVALID_PARAMETER;
5120 if (fsp == NULL) {
5121 return NT_STATUS_INVALID_HANDLE;
5124 delete_on_close = (CVAL(pdata,0) ? True : False);
5125 dosmode = dos_mode(conn, fname, psbuf);
5127 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5128 "delete_on_close = %u\n",
5129 fsp->fsp_name,
5130 (unsigned int)dosmode,
5131 (unsigned int)delete_on_close ));
5133 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 return status;
5139 /* The set is across all open files on this dev/inode pair. */
5140 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
5141 return NT_STATUS_ACCESS_DENIED;
5143 return NT_STATUS_OK;
5146 /****************************************************************************
5147 Deal with SMB_FILE_POSITION_INFORMATION.
5148 ****************************************************************************/
5150 static NTSTATUS smb_file_position_information(connection_struct *conn,
5151 const char *pdata,
5152 int total_data,
5153 files_struct *fsp)
5155 SMB_BIG_UINT position_information;
5157 if (total_data < 8) {
5158 return NT_STATUS_INVALID_PARAMETER;
5161 if (fsp == NULL) {
5162 /* Ignore on pathname based set. */
5163 return NT_STATUS_OK;
5166 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5167 #ifdef LARGE_SMB_OFF_T
5168 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5169 #else /* LARGE_SMB_OFF_T */
5170 if (IVAL(pdata,4) != 0) {
5171 /* more than 32 bits? */
5172 return NT_STATUS_INVALID_PARAMETER;
5174 #endif /* LARGE_SMB_OFF_T */
5176 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5177 fsp->fsp_name, (double)position_information ));
5178 fsp->fh->position_information = position_information;
5179 return NT_STATUS_OK;
5182 /****************************************************************************
5183 Deal with SMB_FILE_MODE_INFORMATION.
5184 ****************************************************************************/
5186 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5187 const char *pdata,
5188 int total_data)
5190 uint32 mode;
5192 if (total_data < 4) {
5193 return NT_STATUS_INVALID_PARAMETER;
5195 mode = IVAL(pdata,0);
5196 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5197 return NT_STATUS_INVALID_PARAMETER;
5199 return NT_STATUS_OK;
5202 /****************************************************************************
5203 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5204 ****************************************************************************/
5206 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5207 struct smb_request *req,
5208 const char *pdata,
5209 int total_data,
5210 const char *fname)
5212 char *link_target = NULL;
5213 const char *newname = fname;
5214 NTSTATUS status = NT_STATUS_OK;
5215 TALLOC_CTX *ctx = talloc_tos();
5217 /* Set a symbolic link. */
5218 /* Don't allow this if follow links is false. */
5220 if (total_data == 0) {
5221 return NT_STATUS_INVALID_PARAMETER;
5224 if (!lp_symlinks(SNUM(conn))) {
5225 return NT_STATUS_ACCESS_DENIED;
5228 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5229 total_data, STR_TERMINATE);
5231 if (!link_target) {
5232 return NT_STATUS_INVALID_PARAMETER;
5235 /* !widelinks forces the target path to be within the share. */
5236 /* This means we can interpret the target as a pathname. */
5237 if (!lp_widelinks(SNUM(conn))) {
5238 char *rel_name = NULL;
5239 char *last_dirp = NULL;
5241 if (*link_target == '/') {
5242 /* No absolute paths allowed. */
5243 return NT_STATUS_ACCESS_DENIED;
5245 rel_name = talloc_strdup(ctx,newname);
5246 if (!rel_name) {
5247 return NT_STATUS_NO_MEMORY;
5249 last_dirp = strrchr_m(rel_name, '/');
5250 if (last_dirp) {
5251 last_dirp[1] = '\0';
5252 } else {
5253 rel_name = talloc_strdup(ctx,"./");
5254 if (!rel_name) {
5255 return NT_STATUS_NO_MEMORY;
5258 rel_name = talloc_asprintf_append(rel_name,
5259 "%s",
5260 link_target);
5261 if (!rel_name) {
5262 return NT_STATUS_NO_MEMORY;
5265 status = check_name(conn, rel_name);
5266 if (!NT_STATUS_IS_OK(status)) {
5267 return status;
5271 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5272 newname, link_target ));
5274 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5275 return map_nt_error_from_unix(errno);
5278 return NT_STATUS_OK;
5281 /****************************************************************************
5282 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5283 ****************************************************************************/
5285 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5286 struct smb_request *req,
5287 const char *pdata, int total_data,
5288 const char *fname)
5290 char *oldname = NULL;
5291 TALLOC_CTX *ctx = talloc_tos();
5292 NTSTATUS status = NT_STATUS_OK;
5294 /* Set a hard link. */
5295 if (total_data == 0) {
5296 return NT_STATUS_INVALID_PARAMETER;
5299 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5300 total_data, STR_TERMINATE, &status);
5301 if (!NT_STATUS_IS_OK(status)) {
5302 return status;
5305 status = resolve_dfspath(ctx, conn,
5306 req->flags2 & FLAGS2_DFS_PATHNAMES,
5307 oldname,
5308 &oldname);
5309 if (!NT_STATUS_IS_OK(status)) {
5310 return status;
5313 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5314 fname, oldname));
5316 return hardlink_internals(ctx, conn, oldname, fname);
5319 /****************************************************************************
5320 Deal with SMB_FILE_RENAME_INFORMATION.
5321 ****************************************************************************/
5323 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5324 struct smb_request *req,
5325 const char *pdata,
5326 int total_data,
5327 files_struct *fsp,
5328 const char *fname)
5330 bool overwrite;
5331 uint32 root_fid;
5332 uint32 len;
5333 char *newname = NULL;
5334 char *base_name = NULL;
5335 bool dest_has_wcard = False;
5336 SMB_STRUCT_STAT sbuf;
5337 char *newname_last_component = NULL;
5338 NTSTATUS status = NT_STATUS_OK;
5339 char *p;
5340 TALLOC_CTX *ctx = talloc_tos();
5342 if (total_data < 13) {
5343 return NT_STATUS_INVALID_PARAMETER;
5346 ZERO_STRUCT(sbuf);
5348 overwrite = (CVAL(pdata,0) ? True : False);
5349 root_fid = IVAL(pdata,4);
5350 len = IVAL(pdata,8);
5352 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5353 return NT_STATUS_INVALID_PARAMETER;
5356 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5357 len, 0, &status,
5358 &dest_has_wcard);
5359 if (!NT_STATUS_IS_OK(status)) {
5360 return status;
5363 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5364 newname));
5366 status = resolve_dfspath_wcard(ctx, conn,
5367 req->flags2 & FLAGS2_DFS_PATHNAMES,
5368 newname,
5369 &newname,
5370 &dest_has_wcard);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 return status;
5375 /* Check the new name has no '/' characters. */
5376 if (strchr_m(newname, '/')) {
5377 return NT_STATUS_NOT_SUPPORTED;
5380 if (fsp && fsp->base_fsp) {
5381 /* newname must be a stream name. */
5382 if (newname[0] != ':') {
5383 return NT_STATUS_NOT_SUPPORTED;
5385 base_name = talloc_asprintf(ctx, "%s%s",
5386 fsp->base_fsp->fsp_name,
5387 newname);
5388 if (!base_name) {
5389 return NT_STATUS_NO_MEMORY;
5391 } else {
5392 /* newname must *not* be a stream name. */
5393 if (is_ntfs_stream_name(newname)) {
5394 return NT_STATUS_NOT_SUPPORTED;
5397 /* Create the base directory. */
5398 base_name = talloc_strdup(ctx, fname);
5399 if (!base_name) {
5400 return NT_STATUS_NO_MEMORY;
5402 p = strrchr_m(base_name, '/');
5403 if (p) {
5404 p[1] = '\0';
5405 } else {
5406 base_name = talloc_strdup(ctx, "./");
5407 if (!base_name) {
5408 return NT_STATUS_NO_MEMORY;
5411 /* Append the new name. */
5412 base_name = talloc_asprintf_append(base_name,
5413 "%s",
5414 newname);
5415 if (!base_name) {
5416 return NT_STATUS_NO_MEMORY;
5419 status = unix_convert(ctx, conn, newname, False,
5420 &newname,
5421 &newname_last_component,
5422 &sbuf);
5424 /* If an error we expect this to be
5425 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5427 if (!NT_STATUS_IS_OK(status)
5428 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5429 status)) {
5430 return status;
5434 if (fsp) {
5435 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5436 fsp->fnum, fsp->fsp_name, base_name ));
5437 status = rename_internals_fsp(conn, fsp, base_name,
5438 newname_last_component, 0,
5439 overwrite);
5440 } else {
5441 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5442 fname, base_name ));
5443 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5444 overwrite, False, dest_has_wcard,
5445 FILE_WRITE_ATTRIBUTES);
5448 return status;
5451 /****************************************************************************
5452 Deal with SMB_SET_POSIX_ACL.
5453 ****************************************************************************/
5455 #if defined(HAVE_POSIX_ACLS)
5456 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5457 const char *pdata,
5458 int total_data,
5459 files_struct *fsp,
5460 const char *fname,
5461 SMB_STRUCT_STAT *psbuf)
5463 uint16 posix_acl_version;
5464 uint16 num_file_acls;
5465 uint16 num_def_acls;
5466 bool valid_file_acls = True;
5467 bool valid_def_acls = True;
5469 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5470 return NT_STATUS_INVALID_PARAMETER;
5472 posix_acl_version = SVAL(pdata,0);
5473 num_file_acls = SVAL(pdata,2);
5474 num_def_acls = SVAL(pdata,4);
5476 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5477 valid_file_acls = False;
5478 num_file_acls = 0;
5481 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5482 valid_def_acls = False;
5483 num_def_acls = 0;
5486 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5487 return NT_STATUS_INVALID_PARAMETER;
5490 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5491 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5492 return NT_STATUS_INVALID_PARAMETER;
5495 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5496 fname ? fname : fsp->fsp_name,
5497 (unsigned int)num_file_acls,
5498 (unsigned int)num_def_acls));
5500 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5501 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5502 return map_nt_error_from_unix(errno);
5505 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5506 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5507 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5508 return map_nt_error_from_unix(errno);
5510 return NT_STATUS_OK;
5512 #endif
5514 /****************************************************************************
5515 Deal with SMB_SET_POSIX_LOCK.
5516 ****************************************************************************/
5518 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5519 const struct smb_request *req,
5520 const char *pdata,
5521 int total_data,
5522 files_struct *fsp)
5524 SMB_BIG_UINT count;
5525 SMB_BIG_UINT offset;
5526 uint32 lock_pid;
5527 bool blocking_lock = False;
5528 enum brl_type lock_type;
5530 NTSTATUS status = NT_STATUS_OK;
5532 if (fsp == NULL || fsp->fh->fd == -1) {
5533 return NT_STATUS_INVALID_HANDLE;
5536 if (total_data != POSIX_LOCK_DATA_SIZE) {
5537 return NT_STATUS_INVALID_PARAMETER;
5540 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5541 case POSIX_LOCK_TYPE_READ:
5542 lock_type = READ_LOCK;
5543 break;
5544 case POSIX_LOCK_TYPE_WRITE:
5545 /* Return the right POSIX-mappable error code for files opened read-only. */
5546 if (!fsp->can_write) {
5547 return NT_STATUS_INVALID_HANDLE;
5549 lock_type = WRITE_LOCK;
5550 break;
5551 case POSIX_LOCK_TYPE_UNLOCK:
5552 lock_type = UNLOCK_LOCK;
5553 break;
5554 default:
5555 return NT_STATUS_INVALID_PARAMETER;
5558 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5559 blocking_lock = False;
5560 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5561 blocking_lock = True;
5562 } else {
5563 return NT_STATUS_INVALID_PARAMETER;
5566 if (!lp_blocking_locks(SNUM(conn))) {
5567 blocking_lock = False;
5570 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5571 #if defined(HAVE_LONGLONG)
5572 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5573 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5574 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5575 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5576 #else /* HAVE_LONGLONG */
5577 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5578 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5579 #endif /* HAVE_LONGLONG */
5581 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5582 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5583 fsp->fsp_name,
5584 (unsigned int)lock_type,
5585 (unsigned int)lock_pid,
5586 (double)count,
5587 (double)offset ));
5589 if (lock_type == UNLOCK_LOCK) {
5590 status = do_unlock(smbd_messaging_context(),
5591 fsp,
5592 lock_pid,
5593 count,
5594 offset,
5595 POSIX_LOCK);
5596 } else {
5597 uint32 block_smbpid;
5599 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5600 fsp,
5601 lock_pid,
5602 count,
5603 offset,
5604 lock_type,
5605 POSIX_LOCK,
5606 blocking_lock,
5607 &status,
5608 &block_smbpid);
5610 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5612 * A blocking lock was requested. Package up
5613 * this smb into a queued request and push it
5614 * onto the blocking lock queue.
5616 if(push_blocking_lock_request(br_lck,
5617 req,
5618 fsp,
5619 -1, /* infinite timeout. */
5621 lock_pid,
5622 lock_type,
5623 POSIX_LOCK,
5624 offset,
5625 count,
5626 block_smbpid)) {
5627 TALLOC_FREE(br_lck);
5628 return status;
5631 TALLOC_FREE(br_lck);
5634 return status;
5637 /****************************************************************************
5638 Deal with SMB_INFO_STANDARD.
5639 ****************************************************************************/
5641 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5642 const char *pdata,
5643 int total_data,
5644 files_struct *fsp,
5645 const char *fname,
5646 const SMB_STRUCT_STAT *psbuf)
5648 struct timespec ts[2];
5650 if (total_data < 12) {
5651 return NT_STATUS_INVALID_PARAMETER;
5654 /* access time */
5655 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5656 /* write time */
5657 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5659 DEBUG(10,("smb_set_info_standard: file %s\n",
5660 fname ? fname : fsp->fsp_name ));
5662 return smb_set_file_time(conn,
5663 fsp,
5664 fname,
5665 psbuf,
5667 true);
5670 /****************************************************************************
5671 Deal with SMB_SET_FILE_BASIC_INFO.
5672 ****************************************************************************/
5674 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5675 const char *pdata,
5676 int total_data,
5677 files_struct *fsp,
5678 const char *fname,
5679 SMB_STRUCT_STAT *psbuf)
5681 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5682 struct timespec write_time;
5683 struct timespec changed_time;
5684 uint32 dosmode = 0;
5685 struct timespec ts[2];
5686 NTSTATUS status = NT_STATUS_OK;
5687 bool setting_write_time = true;
5689 if (total_data < 36) {
5690 return NT_STATUS_INVALID_PARAMETER;
5693 /* Set the attributes */
5694 dosmode = IVAL(pdata,32);
5695 status = smb_set_file_dosmode(conn,
5696 fname,
5697 psbuf,
5698 dosmode);
5699 if (!NT_STATUS_IS_OK(status)) {
5700 return status;
5703 /* Ignore create time at offset pdata. */
5705 /* access time */
5706 ts[0] = interpret_long_date(pdata+8);
5708 write_time = interpret_long_date(pdata+16);
5709 changed_time = interpret_long_date(pdata+24);
5711 /* mtime */
5712 ts[1] = timespec_min(&write_time, &changed_time);
5714 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5715 ts[1] = write_time;
5718 /* Prefer a defined time to an undefined one. */
5719 if (null_timespec(ts[1])) {
5720 if (null_timespec(write_time)) {
5721 ts[1] = changed_time;
5722 setting_write_time = false;
5723 } else {
5724 ts[1] = write_time;
5728 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5729 fname ? fname : fsp->fsp_name ));
5731 return smb_set_file_time(conn,
5732 fsp,
5733 fname,
5734 psbuf,
5736 setting_write_time);
5739 /****************************************************************************
5740 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5741 ****************************************************************************/
5743 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5744 struct smb_request *req,
5745 const char *pdata,
5746 int total_data,
5747 files_struct *fsp,
5748 const char *fname,
5749 SMB_STRUCT_STAT *psbuf)
5751 SMB_BIG_UINT allocation_size = 0;
5752 NTSTATUS status = NT_STATUS_OK;
5753 files_struct *new_fsp = NULL;
5755 if (!VALID_STAT(*psbuf)) {
5756 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5759 if (total_data < 8) {
5760 return NT_STATUS_INVALID_PARAMETER;
5763 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5764 #ifdef LARGE_SMB_OFF_T
5765 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5766 #else /* LARGE_SMB_OFF_T */
5767 if (IVAL(pdata,4) != 0) {
5768 /* more than 32 bits? */
5769 return NT_STATUS_INVALID_PARAMETER;
5771 #endif /* LARGE_SMB_OFF_T */
5773 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5774 fname, (double)allocation_size ));
5776 if (allocation_size) {
5777 allocation_size = smb_roundup(conn, allocation_size);
5780 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5781 fname, (double)allocation_size ));
5783 if (fsp && fsp->fh->fd != -1) {
5784 /* Open file handle. */
5785 /* Only change if needed. */
5786 if (allocation_size != get_file_size(*psbuf)) {
5787 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5788 return map_nt_error_from_unix(errno);
5791 /* But always update the time. */
5793 * This is equivalent to a write. Ensure it's seen immediately
5794 * if there are no pending writes.
5796 trigger_write_time_update_immediate(fsp);
5797 return NT_STATUS_OK;
5800 /* Pathname or stat or directory file. */
5802 status = open_file_ntcreate(conn, req, fname, psbuf,
5803 FILE_WRITE_DATA,
5804 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5805 FILE_OPEN,
5807 FILE_ATTRIBUTE_NORMAL,
5808 FORCE_OPLOCK_BREAK_TO_NONE,
5809 NULL, &new_fsp);
5811 if (!NT_STATUS_IS_OK(status)) {
5812 /* NB. We check for open_was_deferred in the caller. */
5813 return status;
5816 /* Only change if needed. */
5817 if (allocation_size != get_file_size(*psbuf)) {
5818 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5819 status = map_nt_error_from_unix(errno);
5820 close_file(new_fsp,NORMAL_CLOSE);
5821 return status;
5825 /* Changing the allocation size should set the last mod time. */
5827 * This is equivalent to a write. Ensure it's seen immediately
5828 * if there are no pending writes.
5830 trigger_write_time_update_immediate(new_fsp);
5832 close_file(new_fsp,NORMAL_CLOSE);
5833 return NT_STATUS_OK;
5836 /****************************************************************************
5837 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5838 ****************************************************************************/
5840 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5841 struct smb_request *req,
5842 const char *pdata,
5843 int total_data,
5844 files_struct *fsp,
5845 const char *fname,
5846 SMB_STRUCT_STAT *psbuf)
5848 SMB_OFF_T size;
5850 if (total_data < 8) {
5851 return NT_STATUS_INVALID_PARAMETER;
5854 size = IVAL(pdata,0);
5855 #ifdef LARGE_SMB_OFF_T
5856 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5857 #else /* LARGE_SMB_OFF_T */
5858 if (IVAL(pdata,4) != 0) {
5859 /* more than 32 bits? */
5860 return NT_STATUS_INVALID_PARAMETER;
5862 #endif /* LARGE_SMB_OFF_T */
5863 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5864 "file %s to %.0f\n", fname, (double)size ));
5866 return smb_set_file_size(conn, req,
5867 fsp,
5868 fname,
5869 psbuf,
5870 size);
5873 /****************************************************************************
5874 Allow a UNIX info mknod.
5875 ****************************************************************************/
5877 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5878 const char *pdata,
5879 int total_data,
5880 const char *fname,
5881 SMB_STRUCT_STAT *psbuf)
5883 uint32 file_type = IVAL(pdata,56);
5884 #if defined(HAVE_MAKEDEV)
5885 uint32 dev_major = IVAL(pdata,60);
5886 uint32 dev_minor = IVAL(pdata,68);
5887 #endif
5888 SMB_DEV_T dev = (SMB_DEV_T)0;
5889 uint32 raw_unixmode = IVAL(pdata,84);
5890 NTSTATUS status;
5891 mode_t unixmode;
5893 if (total_data < 100) {
5894 return NT_STATUS_INVALID_PARAMETER;
5897 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5898 if (!NT_STATUS_IS_OK(status)) {
5899 return status;
5902 #if defined(HAVE_MAKEDEV)
5903 dev = makedev(dev_major, dev_minor);
5904 #endif
5906 switch (file_type) {
5907 #if defined(S_IFIFO)
5908 case UNIX_TYPE_FIFO:
5909 unixmode |= S_IFIFO;
5910 break;
5911 #endif
5912 #if defined(S_IFSOCK)
5913 case UNIX_TYPE_SOCKET:
5914 unixmode |= S_IFSOCK;
5915 break;
5916 #endif
5917 #if defined(S_IFCHR)
5918 case UNIX_TYPE_CHARDEV:
5919 unixmode |= S_IFCHR;
5920 break;
5921 #endif
5922 #if defined(S_IFBLK)
5923 case UNIX_TYPE_BLKDEV:
5924 unixmode |= S_IFBLK;
5925 break;
5926 #endif
5927 default:
5928 return NT_STATUS_INVALID_PARAMETER;
5931 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5932 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5934 /* Ok - do the mknod. */
5935 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5936 return map_nt_error_from_unix(errno);
5939 /* If any of the other "set" calls fail we
5940 * don't want to end up with a half-constructed mknod.
5943 if (lp_inherit_perms(SNUM(conn))) {
5944 inherit_access_acl(
5945 conn, parent_dirname(fname),
5946 fname, unixmode);
5949 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5950 status = map_nt_error_from_unix(errno);
5951 SMB_VFS_UNLINK(conn,fname);
5952 return status;
5954 return NT_STATUS_OK;
5957 /****************************************************************************
5958 Deal with SMB_SET_FILE_UNIX_BASIC.
5959 ****************************************************************************/
5961 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5962 struct smb_request *req,
5963 const char *pdata,
5964 int total_data,
5965 files_struct *fsp,
5966 const char *fname,
5967 SMB_STRUCT_STAT *psbuf)
5969 struct timespec ts[2];
5970 uint32 raw_unixmode;
5971 mode_t unixmode;
5972 SMB_OFF_T size = 0;
5973 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5974 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5975 NTSTATUS status = NT_STATUS_OK;
5976 bool delete_on_fail = False;
5977 enum perm_type ptype;
5979 if (total_data < 100) {
5980 return NT_STATUS_INVALID_PARAMETER;
5983 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5984 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5985 size=IVAL(pdata,0); /* first 8 Bytes are size */
5986 #ifdef LARGE_SMB_OFF_T
5987 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5988 #else /* LARGE_SMB_OFF_T */
5989 if (IVAL(pdata,4) != 0) {
5990 /* more than 32 bits? */
5991 return NT_STATUS_INVALID_PARAMETER;
5993 #endif /* LARGE_SMB_OFF_T */
5996 ts[0] = interpret_long_date(pdata+24); /* access_time */
5997 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5998 set_owner = (uid_t)IVAL(pdata,40);
5999 set_grp = (gid_t)IVAL(pdata,48);
6000 raw_unixmode = IVAL(pdata,84);
6002 if (VALID_STAT(*psbuf)) {
6003 if (S_ISDIR(psbuf->st_mode)) {
6004 ptype = PERM_EXISTING_DIR;
6005 } else {
6006 ptype = PERM_EXISTING_FILE;
6008 } else {
6009 ptype = PERM_NEW_FILE;
6012 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 return status;
6017 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6018 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6019 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6021 if (!VALID_STAT(*psbuf)) {
6023 * The only valid use of this is to create character and block
6024 * devices, and named pipes. This is deprecated (IMHO) and
6025 * a new info level should be used for mknod. JRA.
6028 status = smb_unix_mknod(conn,
6029 pdata,
6030 total_data,
6031 fname,
6032 psbuf);
6033 if (!NT_STATUS_IS_OK(status)) {
6034 return status;
6037 /* Ensure we don't try and change anything else. */
6038 raw_unixmode = SMB_MODE_NO_CHANGE;
6039 size = get_file_size(*psbuf);
6040 ts[0] = get_atimespec(psbuf);
6041 ts[1] = get_mtimespec(psbuf);
6043 * We continue here as we might want to change the
6044 * owner uid/gid.
6046 delete_on_fail = True;
6049 #if 1
6050 /* Horrible backwards compatibility hack as an old server bug
6051 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6052 * */
6054 if (!size) {
6055 size = get_file_size(*psbuf);
6057 #endif
6060 * Deal with the UNIX specific mode set.
6063 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6064 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6065 (unsigned int)unixmode, fname ));
6066 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6067 return map_nt_error_from_unix(errno);
6072 * Deal with the UNIX specific uid set.
6075 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6076 int ret;
6078 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6079 (unsigned int)set_owner, fname ));
6081 if (S_ISLNK(psbuf->st_mode)) {
6082 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6083 } else {
6084 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6087 if (ret != 0) {
6088 status = map_nt_error_from_unix(errno);
6089 if (delete_on_fail) {
6090 SMB_VFS_UNLINK(conn,fname);
6092 return status;
6097 * Deal with the UNIX specific gid set.
6100 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6101 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6102 (unsigned int)set_owner, fname ));
6103 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6104 status = map_nt_error_from_unix(errno);
6105 if (delete_on_fail) {
6106 SMB_VFS_UNLINK(conn,fname);
6108 return status;
6112 /* Deal with any size changes. */
6114 status = smb_set_file_size(conn, req,
6115 fsp,
6116 fname,
6117 psbuf,
6118 size);
6119 if (!NT_STATUS_IS_OK(status)) {
6120 return status;
6123 /* Deal with any time changes. */
6125 return smb_set_file_time(conn,
6126 fsp,
6127 fname,
6128 psbuf,
6130 true);
6133 /****************************************************************************
6134 Deal with SMB_SET_FILE_UNIX_INFO2.
6135 ****************************************************************************/
6137 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6138 struct smb_request *req,
6139 const char *pdata,
6140 int total_data,
6141 files_struct *fsp,
6142 const char *fname,
6143 SMB_STRUCT_STAT *psbuf)
6145 NTSTATUS status;
6146 uint32 smb_fflags;
6147 uint32 smb_fmask;
6149 if (total_data < 116) {
6150 return NT_STATUS_INVALID_PARAMETER;
6153 /* Start by setting all the fields that are common between UNIX_BASIC
6154 * and UNIX_INFO2.
6156 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6157 fsp, fname, psbuf);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 return status;
6162 smb_fflags = IVAL(pdata, 108);
6163 smb_fmask = IVAL(pdata, 112);
6165 /* NB: We should only attempt to alter the file flags if the client
6166 * sends a non-zero mask.
6168 if (smb_fmask != 0) {
6169 int stat_fflags = 0;
6171 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6172 &stat_fflags)) {
6173 /* Client asked to alter a flag we don't understand. */
6174 return NT_STATUS_INVALID_PARAMETER;
6177 if (fsp && fsp->fh->fd != -1) {
6178 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6179 return NT_STATUS_NOT_SUPPORTED;
6180 } else {
6181 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6182 return map_nt_error_from_unix(errno);
6187 /* XXX: need to add support for changing the create_time here. You
6188 * can do this for paths on Darwin with setattrlist(2). The right way
6189 * to hook this up is probably by extending the VFS utimes interface.
6192 return NT_STATUS_OK;
6195 /****************************************************************************
6196 Create a directory with POSIX semantics.
6197 ****************************************************************************/
6199 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6200 struct smb_request *req,
6201 char **ppdata,
6202 int total_data,
6203 const char *fname,
6204 SMB_STRUCT_STAT *psbuf,
6205 int *pdata_return_size)
6207 NTSTATUS status = NT_STATUS_OK;
6208 uint32 raw_unixmode = 0;
6209 uint32 mod_unixmode = 0;
6210 mode_t unixmode = (mode_t)0;
6211 files_struct *fsp = NULL;
6212 uint16 info_level_return = 0;
6213 int info;
6214 char *pdata = *ppdata;
6216 if (total_data < 18) {
6217 return NT_STATUS_INVALID_PARAMETER;
6220 raw_unixmode = IVAL(pdata,8);
6221 /* Next 4 bytes are not yet defined. */
6223 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6224 if (!NT_STATUS_IS_OK(status)) {
6225 return status;
6228 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6230 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6231 fname, (unsigned int)unixmode ));
6233 status = open_directory(conn, req,
6234 fname,
6235 psbuf,
6236 FILE_READ_ATTRIBUTES, /* Just a stat open */
6237 FILE_SHARE_NONE, /* Ignored for stat opens */
6238 FILE_CREATE,
6240 mod_unixmode,
6241 &info,
6242 &fsp);
6244 if (NT_STATUS_IS_OK(status)) {
6245 close_file(fsp, NORMAL_CLOSE);
6248 info_level_return = SVAL(pdata,16);
6250 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6251 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6252 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6253 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6254 } else {
6255 *pdata_return_size = 12;
6258 /* Realloc the data size */
6259 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6260 if (*ppdata == NULL) {
6261 *pdata_return_size = 0;
6262 return NT_STATUS_NO_MEMORY;
6264 pdata = *ppdata;
6266 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6267 SSVAL(pdata,2,0); /* No fnum. */
6268 SIVAL(pdata,4,info); /* Was directory created. */
6270 switch (info_level_return) {
6271 case SMB_QUERY_FILE_UNIX_BASIC:
6272 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6273 SSVAL(pdata,10,0); /* Padding. */
6274 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6275 break;
6276 case SMB_QUERY_FILE_UNIX_INFO2:
6277 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6278 SSVAL(pdata,10,0); /* Padding. */
6279 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6280 break;
6281 default:
6282 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6283 SSVAL(pdata,10,0); /* Padding. */
6284 break;
6287 return status;
6290 /****************************************************************************
6291 Open/Create a file with POSIX semantics.
6292 ****************************************************************************/
6294 static NTSTATUS smb_posix_open(connection_struct *conn,
6295 struct smb_request *req,
6296 char **ppdata,
6297 int total_data,
6298 const char *fname,
6299 SMB_STRUCT_STAT *psbuf,
6300 int *pdata_return_size)
6302 bool extended_oplock_granted = False;
6303 char *pdata = *ppdata;
6304 uint32 flags = 0;
6305 uint32 wire_open_mode = 0;
6306 uint32 raw_unixmode = 0;
6307 uint32 mod_unixmode = 0;
6308 uint32 create_disp = 0;
6309 uint32 access_mask = 0;
6310 uint32 create_options = 0;
6311 NTSTATUS status = NT_STATUS_OK;
6312 mode_t unixmode = (mode_t)0;
6313 files_struct *fsp = NULL;
6314 int oplock_request = 0;
6315 int info = 0;
6316 uint16 info_level_return = 0;
6318 if (total_data < 18) {
6319 return NT_STATUS_INVALID_PARAMETER;
6322 flags = IVAL(pdata,0);
6323 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6324 if (oplock_request) {
6325 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6328 wire_open_mode = IVAL(pdata,4);
6330 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6331 return smb_posix_mkdir(conn, req,
6332 ppdata,
6333 total_data,
6334 fname,
6335 psbuf,
6336 pdata_return_size);
6339 switch (wire_open_mode & SMB_ACCMODE) {
6340 case SMB_O_RDONLY:
6341 access_mask = FILE_READ_DATA;
6342 break;
6343 case SMB_O_WRONLY:
6344 access_mask = FILE_WRITE_DATA;
6345 break;
6346 case SMB_O_RDWR:
6347 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6348 break;
6349 default:
6350 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6351 (unsigned int)wire_open_mode ));
6352 return NT_STATUS_INVALID_PARAMETER;
6355 wire_open_mode &= ~SMB_ACCMODE;
6357 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6358 create_disp = FILE_CREATE;
6359 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6360 create_disp = FILE_OVERWRITE_IF;
6361 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6362 create_disp = FILE_OPEN_IF;
6363 } else {
6364 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6365 (unsigned int)wire_open_mode ));
6366 return NT_STATUS_INVALID_PARAMETER;
6369 raw_unixmode = IVAL(pdata,8);
6370 /* Next 4 bytes are not yet defined. */
6372 status = unix_perms_from_wire(conn,
6373 psbuf,
6374 raw_unixmode,
6375 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6376 &unixmode);
6378 if (!NT_STATUS_IS_OK(status)) {
6379 return status;
6382 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6384 if (wire_open_mode & SMB_O_SYNC) {
6385 create_options |= FILE_WRITE_THROUGH;
6387 if (wire_open_mode & SMB_O_APPEND) {
6388 access_mask |= FILE_APPEND_DATA;
6390 if (wire_open_mode & SMB_O_DIRECT) {
6391 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6394 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6395 fname,
6396 (unsigned int)wire_open_mode,
6397 (unsigned int)unixmode ));
6399 status = open_file_ntcreate(conn, req,
6400 fname,
6401 psbuf,
6402 access_mask,
6403 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6404 create_disp,
6405 0, /* no create options yet. */
6406 mod_unixmode,
6407 oplock_request,
6408 &info,
6409 &fsp);
6411 if (!NT_STATUS_IS_OK(status)) {
6412 return status;
6415 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6416 extended_oplock_granted = True;
6419 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6420 extended_oplock_granted = True;
6423 info_level_return = SVAL(pdata,16);
6425 /* Allocate the correct return size. */
6427 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6428 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6429 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6430 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6431 } else {
6432 *pdata_return_size = 12;
6435 /* Realloc the data size */
6436 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6437 if (*ppdata == NULL) {
6438 close_file(fsp,ERROR_CLOSE);
6439 *pdata_return_size = 0;
6440 return NT_STATUS_NO_MEMORY;
6442 pdata = *ppdata;
6444 if (extended_oplock_granted) {
6445 if (flags & REQUEST_BATCH_OPLOCK) {
6446 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6447 } else {
6448 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6450 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6451 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6452 } else {
6453 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6456 SSVAL(pdata,2,fsp->fnum);
6457 SIVAL(pdata,4,info); /* Was file created etc. */
6459 switch (info_level_return) {
6460 case SMB_QUERY_FILE_UNIX_BASIC:
6461 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6462 SSVAL(pdata,10,0); /* padding. */
6463 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6464 break;
6465 case SMB_QUERY_FILE_UNIX_INFO2:
6466 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6467 SSVAL(pdata,10,0); /* padding. */
6468 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6469 break;
6470 default:
6471 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6472 SSVAL(pdata,10,0); /* padding. */
6473 break;
6475 return NT_STATUS_OK;
6478 /****************************************************************************
6479 Delete a file with POSIX semantics.
6480 ****************************************************************************/
6482 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6483 struct smb_request *req,
6484 const char *pdata,
6485 int total_data,
6486 const char *fname,
6487 SMB_STRUCT_STAT *psbuf)
6489 NTSTATUS status = NT_STATUS_OK;
6490 files_struct *fsp = NULL;
6491 uint16 flags = 0;
6492 char del = 1;
6493 int info = 0;
6494 int i;
6495 struct share_mode_lock *lck = NULL;
6497 if (total_data < 2) {
6498 return NT_STATUS_INVALID_PARAMETER;
6501 flags = SVAL(pdata,0);
6503 if (!VALID_STAT(*psbuf)) {
6504 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6507 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6508 !VALID_STAT_OF_DIR(*psbuf)) {
6509 return NT_STATUS_NOT_A_DIRECTORY;
6512 DEBUG(10,("smb_posix_unlink: %s %s\n",
6513 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6514 fname));
6516 if (VALID_STAT_OF_DIR(*psbuf)) {
6517 status = open_directory(conn, req,
6518 fname,
6519 psbuf,
6520 DELETE_ACCESS,
6521 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6522 FILE_OPEN,
6524 FILE_FLAG_POSIX_SEMANTICS|0777,
6525 &info,
6526 &fsp);
6527 } else {
6529 status = open_file_ntcreate(conn, req,
6530 fname,
6531 psbuf,
6532 DELETE_ACCESS,
6533 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6534 FILE_OPEN,
6536 FILE_FLAG_POSIX_SEMANTICS|0777,
6537 0, /* No oplock, but break existing ones. */
6538 &info,
6539 &fsp);
6542 if (!NT_STATUS_IS_OK(status)) {
6543 return status;
6547 * Don't lie to client. If we can't really delete due to
6548 * non-POSIX opens return SHARING_VIOLATION.
6551 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6552 NULL);
6553 if (lck == NULL) {
6554 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6555 "lock for file %s\n", fsp->fsp_name));
6556 close_file(fsp, NORMAL_CLOSE);
6557 return NT_STATUS_INVALID_PARAMETER;
6561 * See if others still have the file open. If this is the case, then
6562 * don't delete. If all opens are POSIX delete we can set the delete
6563 * on close disposition.
6565 for (i=0; i<lck->num_share_modes; i++) {
6566 struct share_mode_entry *e = &lck->share_modes[i];
6567 if (is_valid_share_mode_entry(e)) {
6568 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6569 continue;
6571 /* Fail with sharing violation. */
6572 close_file(fsp, NORMAL_CLOSE);
6573 TALLOC_FREE(lck);
6574 return NT_STATUS_SHARING_VIOLATION;
6579 * Set the delete on close.
6581 status = smb_set_file_disposition_info(conn,
6582 &del,
6584 fsp,
6585 fname,
6586 psbuf);
6588 if (!NT_STATUS_IS_OK(status)) {
6589 close_file(fsp, NORMAL_CLOSE);
6590 TALLOC_FREE(lck);
6591 return status;
6593 TALLOC_FREE(lck);
6594 return close_file(fsp, NORMAL_CLOSE);
6597 /****************************************************************************
6598 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6599 ****************************************************************************/
6601 static void call_trans2setfilepathinfo(connection_struct *conn,
6602 struct smb_request *req,
6603 unsigned int tran_call,
6604 char **pparams, int total_params,
6605 char **ppdata, int total_data,
6606 unsigned int max_data_bytes)
6608 char *params = *pparams;
6609 char *pdata = *ppdata;
6610 uint16 info_level;
6611 SMB_STRUCT_STAT sbuf;
6612 char *fname = NULL;
6613 files_struct *fsp = NULL;
6614 NTSTATUS status = NT_STATUS_OK;
6615 int data_return_size = 0;
6616 TALLOC_CTX *ctx = talloc_tos();
6618 if (!params) {
6619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6620 return;
6623 ZERO_STRUCT(sbuf);
6625 if (tran_call == TRANSACT2_SETFILEINFO) {
6626 if (total_params < 4) {
6627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6628 return;
6631 fsp = file_fsp(SVAL(params,0));
6632 /* Basic check for non-null fsp. */
6633 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6634 return;
6636 info_level = SVAL(params,2);
6638 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6639 if (!fname) {
6640 reply_nterror(req, NT_STATUS_NO_MEMORY);
6641 return;
6644 if(fsp->is_directory || fsp->fh->fd == -1) {
6646 * This is actually a SETFILEINFO on a directory
6647 * handle (returned from an NT SMB). NT5.0 seems
6648 * to do this call. JRA.
6650 if (INFO_LEVEL_IS_UNIX(info_level)) {
6651 /* Always do lstat for UNIX calls. */
6652 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6653 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6654 reply_unixerror(req,ERRDOS,ERRbadpath);
6655 return;
6657 } else {
6658 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6659 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6660 reply_unixerror(req,ERRDOS,ERRbadpath);
6661 return;
6664 } else if (fsp->print_file) {
6666 * Doing a DELETE_ON_CLOSE should cancel a print job.
6668 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6669 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6671 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6673 SSVAL(params,0,0);
6674 send_trans2_replies(conn, req, params, 2,
6675 *ppdata, 0,
6676 max_data_bytes);
6677 return;
6678 } else {
6679 reply_unixerror(req, ERRDOS, ERRbadpath);
6680 return;
6682 } else {
6684 * Original code - this is an open file.
6686 if (!check_fsp(conn, req, fsp, &current_user)) {
6687 return;
6690 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6691 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6692 reply_unixerror(req, ERRDOS, ERRbadfid);
6693 return;
6696 } else {
6697 /* set path info */
6698 if (total_params < 7) {
6699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6700 return;
6703 info_level = SVAL(params,0);
6704 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6705 total_params - 6, STR_TERMINATE,
6706 &status);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 reply_nterror(req, status);
6709 return;
6712 status = resolve_dfspath(ctx, conn,
6713 req->flags2 & FLAGS2_DFS_PATHNAMES,
6714 fname,
6715 &fname);
6716 if (!NT_STATUS_IS_OK(status)) {
6717 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6718 reply_botherror(req,
6719 NT_STATUS_PATH_NOT_COVERED,
6720 ERRSRV, ERRbadpath);
6721 return;
6723 reply_nterror(req, status);
6724 return;
6727 status = unix_convert(ctx, conn, fname, False,
6728 &fname, NULL, &sbuf);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 reply_nterror(req, status);
6731 return;
6734 status = check_name(conn, fname);
6735 if (!NT_STATUS_IS_OK(status)) {
6736 reply_nterror(req, status);
6737 return;
6740 if (INFO_LEVEL_IS_UNIX(info_level)) {
6742 * For CIFS UNIX extensions the target name may not exist.
6745 /* Always do lstat for UNIX calls. */
6746 SMB_VFS_LSTAT(conn,fname,&sbuf);
6748 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6749 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6750 reply_unixerror(req, ERRDOS, ERRbadpath);
6751 return;
6755 if (!CAN_WRITE(conn)) {
6756 reply_doserror(req, ERRSRV, ERRaccess);
6757 return;
6760 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6761 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6762 return;
6765 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6766 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6768 /* Realloc the parameter size */
6769 *pparams = (char *)SMB_REALLOC(*pparams,2);
6770 if (*pparams == NULL) {
6771 reply_nterror(req, NT_STATUS_NO_MEMORY);
6772 return;
6774 params = *pparams;
6776 SSVAL(params,0,0);
6778 switch (info_level) {
6780 case SMB_INFO_STANDARD:
6782 status = smb_set_info_standard(conn,
6783 pdata,
6784 total_data,
6785 fsp,
6786 fname,
6787 &sbuf);
6788 break;
6791 case SMB_INFO_SET_EA:
6793 status = smb_info_set_ea(conn,
6794 pdata,
6795 total_data,
6796 fsp,
6797 fname);
6798 break;
6801 case SMB_SET_FILE_BASIC_INFO:
6802 case SMB_FILE_BASIC_INFORMATION:
6804 status = smb_set_file_basic_info(conn,
6805 pdata,
6806 total_data,
6807 fsp,
6808 fname,
6809 &sbuf);
6810 break;
6813 case SMB_FILE_ALLOCATION_INFORMATION:
6814 case SMB_SET_FILE_ALLOCATION_INFO:
6816 status = smb_set_file_allocation_info(conn, req,
6817 pdata,
6818 total_data,
6819 fsp,
6820 fname,
6821 &sbuf);
6822 break;
6825 case SMB_FILE_END_OF_FILE_INFORMATION:
6826 case SMB_SET_FILE_END_OF_FILE_INFO:
6828 status = smb_set_file_end_of_file_info(conn, req,
6829 pdata,
6830 total_data,
6831 fsp,
6832 fname,
6833 &sbuf);
6834 break;
6837 case SMB_FILE_DISPOSITION_INFORMATION:
6838 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6840 #if 0
6841 /* JRA - We used to just ignore this on a path ?
6842 * Shouldn't this be invalid level on a pathname
6843 * based call ?
6845 if (tran_call != TRANSACT2_SETFILEINFO) {
6846 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6848 #endif
6849 status = smb_set_file_disposition_info(conn,
6850 pdata,
6851 total_data,
6852 fsp,
6853 fname,
6854 &sbuf);
6855 break;
6858 case SMB_FILE_POSITION_INFORMATION:
6860 status = smb_file_position_information(conn,
6861 pdata,
6862 total_data,
6863 fsp);
6864 break;
6867 /* From tridge Samba4 :
6868 * MODE_INFORMATION in setfileinfo (I have no
6869 * idea what "mode information" on a file is - it takes a value of 0,
6870 * 2, 4 or 6. What could it be?).
6873 case SMB_FILE_MODE_INFORMATION:
6875 status = smb_file_mode_information(conn,
6876 pdata,
6877 total_data);
6878 break;
6882 * CIFS UNIX extensions.
6885 case SMB_SET_FILE_UNIX_BASIC:
6887 status = smb_set_file_unix_basic(conn, req,
6888 pdata,
6889 total_data,
6890 fsp,
6891 fname,
6892 &sbuf);
6893 break;
6896 case SMB_SET_FILE_UNIX_INFO2:
6898 status = smb_set_file_unix_info2(conn, req,
6899 pdata,
6900 total_data,
6901 fsp,
6902 fname,
6903 &sbuf);
6904 break;
6907 case SMB_SET_FILE_UNIX_LINK:
6909 if (tran_call != TRANSACT2_SETPATHINFO) {
6910 /* We must have a pathname for this. */
6911 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6912 return;
6914 status = smb_set_file_unix_link(conn, req, pdata,
6915 total_data, fname);
6916 break;
6919 case SMB_SET_FILE_UNIX_HLINK:
6921 if (tran_call != TRANSACT2_SETPATHINFO) {
6922 /* We must have a pathname for this. */
6923 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6924 return;
6926 status = smb_set_file_unix_hlink(conn, req,
6927 pdata, total_data,
6928 fname);
6929 break;
6932 case SMB_FILE_RENAME_INFORMATION:
6934 status = smb_file_rename_information(conn, req,
6935 pdata, total_data,
6936 fsp, fname);
6937 break;
6940 #if defined(HAVE_POSIX_ACLS)
6941 case SMB_SET_POSIX_ACL:
6943 status = smb_set_posix_acl(conn,
6944 pdata,
6945 total_data,
6946 fsp,
6947 fname,
6948 &sbuf);
6949 break;
6951 #endif
6953 case SMB_SET_POSIX_LOCK:
6955 if (tran_call != TRANSACT2_SETFILEINFO) {
6956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6957 return;
6959 status = smb_set_posix_lock(conn, req,
6960 pdata, total_data, fsp);
6961 break;
6964 case SMB_POSIX_PATH_OPEN:
6966 if (tran_call != TRANSACT2_SETPATHINFO) {
6967 /* We must have a pathname for this. */
6968 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6969 return;
6972 status = smb_posix_open(conn, req,
6973 ppdata,
6974 total_data,
6975 fname,
6976 &sbuf,
6977 &data_return_size);
6978 break;
6981 case SMB_POSIX_PATH_UNLINK:
6983 if (tran_call != TRANSACT2_SETPATHINFO) {
6984 /* We must have a pathname for this. */
6985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6986 return;
6989 status = smb_posix_unlink(conn, req,
6990 pdata,
6991 total_data,
6992 fname,
6993 &sbuf);
6994 break;
6997 default:
6998 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6999 return;
7003 if (!NT_STATUS_IS_OK(status)) {
7004 if (open_was_deferred(req->mid)) {
7005 /* We have re-scheduled this call. */
7006 return;
7008 if (blocking_lock_was_deferred(req->mid)) {
7009 /* We have re-scheduled this call. */
7010 return;
7012 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7013 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7014 ERRSRV, ERRbadpath);
7015 return;
7017 if (info_level == SMB_POSIX_PATH_OPEN) {
7018 reply_openerror(req, status);
7019 return;
7022 reply_nterror(req, status);
7023 return;
7026 SSVAL(params,0,0);
7027 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7028 max_data_bytes);
7030 return;
7033 /****************************************************************************
7034 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7035 ****************************************************************************/
7037 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7038 char **pparams, int total_params,
7039 char **ppdata, int total_data,
7040 unsigned int max_data_bytes)
7042 char *params = *pparams;
7043 char *pdata = *ppdata;
7044 char *directory = NULL;
7045 SMB_STRUCT_STAT sbuf;
7046 NTSTATUS status = NT_STATUS_OK;
7047 struct ea_list *ea_list = NULL;
7048 TALLOC_CTX *ctx = talloc_tos();
7050 if (!CAN_WRITE(conn)) {
7051 reply_doserror(req, ERRSRV, ERRaccess);
7052 return;
7055 if (total_params < 5) {
7056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7057 return;
7060 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7061 total_params - 4, STR_TERMINATE,
7062 &status);
7063 if (!NT_STATUS_IS_OK(status)) {
7064 reply_nterror(req, status);
7065 return;
7068 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7070 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7071 if (!NT_STATUS_IS_OK(status)) {
7072 reply_nterror(req, status);
7073 return;
7076 status = check_name(conn, directory);
7077 if (!NT_STATUS_IS_OK(status)) {
7078 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7079 reply_nterror(req, status);
7080 return;
7083 /* Any data in this call is an EA list. */
7084 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7085 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7086 return;
7090 * OS/2 workplace shell seems to send SET_EA requests of "null"
7091 * length (4 bytes containing IVAL 4).
7092 * They seem to have no effect. Bug #3212. JRA.
7095 if (total_data != 4) {
7096 if (total_data < 10) {
7097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7098 return;
7101 if (IVAL(pdata,0) > total_data) {
7102 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7103 IVAL(pdata,0), (unsigned int)total_data));
7104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7105 return;
7108 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7109 total_data - 4);
7110 if (!ea_list) {
7111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7112 return;
7115 /* If total_data == 4 Windows doesn't care what values
7116 * are placed in that field, it just ignores them.
7117 * The System i QNTC IBM SMB client puts bad values here,
7118 * so ignore them. */
7120 status = create_directory(conn, req, directory);
7122 if (!NT_STATUS_IS_OK(status)) {
7123 reply_nterror(req, status);
7124 return;
7127 /* Try and set any given EA. */
7128 if (ea_list) {
7129 status = set_ea(conn, NULL, directory, ea_list);
7130 if (!NT_STATUS_IS_OK(status)) {
7131 reply_nterror(req, status);
7132 return;
7136 /* Realloc the parameter and data sizes */
7137 *pparams = (char *)SMB_REALLOC(*pparams,2);
7138 if(*pparams == NULL) {
7139 reply_nterror(req, NT_STATUS_NO_MEMORY);
7140 return;
7142 params = *pparams;
7144 SSVAL(params,0,0);
7146 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7148 return;
7151 /****************************************************************************
7152 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7153 We don't actually do this - we just send a null response.
7154 ****************************************************************************/
7156 static void call_trans2findnotifyfirst(connection_struct *conn,
7157 struct smb_request *req,
7158 char **pparams, int total_params,
7159 char **ppdata, int total_data,
7160 unsigned int max_data_bytes)
7162 static uint16 fnf_handle = 257;
7163 char *params = *pparams;
7164 uint16 info_level;
7166 if (total_params < 6) {
7167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7168 return;
7171 info_level = SVAL(params,4);
7172 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7174 switch (info_level) {
7175 case 1:
7176 case 2:
7177 break;
7178 default:
7179 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7180 return;
7183 /* Realloc the parameter and data sizes */
7184 *pparams = (char *)SMB_REALLOC(*pparams,6);
7185 if (*pparams == NULL) {
7186 reply_nterror(req, NT_STATUS_NO_MEMORY);
7187 return;
7189 params = *pparams;
7191 SSVAL(params,0,fnf_handle);
7192 SSVAL(params,2,0); /* No changes */
7193 SSVAL(params,4,0); /* No EA errors */
7195 fnf_handle++;
7197 if(fnf_handle == 0)
7198 fnf_handle = 257;
7200 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7202 return;
7205 /****************************************************************************
7206 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7207 changes). Currently this does nothing.
7208 ****************************************************************************/
7210 static void call_trans2findnotifynext(connection_struct *conn,
7211 struct smb_request *req,
7212 char **pparams, int total_params,
7213 char **ppdata, int total_data,
7214 unsigned int max_data_bytes)
7216 char *params = *pparams;
7218 DEBUG(3,("call_trans2findnotifynext\n"));
7220 /* Realloc the parameter and data sizes */
7221 *pparams = (char *)SMB_REALLOC(*pparams,4);
7222 if (*pparams == NULL) {
7223 reply_nterror(req, NT_STATUS_NO_MEMORY);
7224 return;
7226 params = *pparams;
7228 SSVAL(params,0,0); /* No changes */
7229 SSVAL(params,2,0); /* No EA errors */
7231 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7233 return;
7236 /****************************************************************************
7237 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7238 ****************************************************************************/
7240 static void call_trans2getdfsreferral(connection_struct *conn,
7241 struct smb_request *req,
7242 char **pparams, int total_params,
7243 char **ppdata, int total_data,
7244 unsigned int max_data_bytes)
7246 char *params = *pparams;
7247 char *pathname = NULL;
7248 int reply_size = 0;
7249 int max_referral_level;
7250 NTSTATUS status = NT_STATUS_OK;
7251 TALLOC_CTX *ctx = talloc_tos();
7253 DEBUG(10,("call_trans2getdfsreferral\n"));
7255 if (total_params < 3) {
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7257 return;
7260 max_referral_level = SVAL(params,0);
7262 if(!lp_host_msdfs()) {
7263 reply_doserror(req, ERRDOS, ERRbadfunc);
7264 return;
7267 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7268 total_params - 2, STR_TERMINATE);
7269 if (!pathname) {
7270 reply_nterror(req, NT_STATUS_NOT_FOUND);
7271 return;
7273 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7274 ppdata,&status)) < 0) {
7275 reply_nterror(req, status);
7276 return;
7279 SSVAL(req->inbuf, smb_flg2,
7280 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7281 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7283 return;
7286 #define LMCAT_SPL 0x53
7287 #define LMFUNC_GETJOBID 0x60
7289 /****************************************************************************
7290 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7291 ****************************************************************************/
7293 static void call_trans2ioctl(connection_struct *conn,
7294 struct smb_request *req,
7295 char **pparams, int total_params,
7296 char **ppdata, int total_data,
7297 unsigned int max_data_bytes)
7299 char *pdata = *ppdata;
7300 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7302 /* check for an invalid fid before proceeding */
7304 if (!fsp) {
7305 reply_doserror(req, ERRDOS, ERRbadfid);
7306 return;
7309 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7310 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7311 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7312 if (*ppdata == NULL) {
7313 reply_nterror(req, NT_STATUS_NO_MEMORY);
7314 return;
7316 pdata = *ppdata;
7318 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7319 CAN ACCEPT THIS IN UNICODE. JRA. */
7321 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7322 srvstr_push(pdata, req->flags2, pdata + 2,
7323 global_myname(), 15,
7324 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7325 srvstr_push(pdata, req->flags2, pdata+18,
7326 lp_servicename(SNUM(conn)), 13,
7327 STR_ASCII|STR_TERMINATE); /* Service name */
7328 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7329 max_data_bytes);
7330 return;
7333 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7334 reply_doserror(req, ERRSRV, ERRerror);
7337 /****************************************************************************
7338 Reply to a SMBfindclose (stop trans2 directory search).
7339 ****************************************************************************/
7341 void reply_findclose(struct smb_request *req)
7343 int dptr_num;
7345 START_PROFILE(SMBfindclose);
7347 if (req->wct < 1) {
7348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7349 END_PROFILE(SMBfindclose);
7350 return;
7353 dptr_num = SVALS(req->inbuf,smb_vwv0);
7355 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7357 dptr_close(&dptr_num);
7359 reply_outbuf(req, 0, 0);
7361 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7363 END_PROFILE(SMBfindclose);
7364 return;
7367 /****************************************************************************
7368 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7369 ****************************************************************************/
7371 void reply_findnclose(struct smb_request *req)
7373 int dptr_num;
7375 START_PROFILE(SMBfindnclose);
7377 if (req->wct < 1) {
7378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7379 END_PROFILE(SMBfindnclose);
7380 return;
7383 dptr_num = SVAL(req->inbuf,smb_vwv0);
7385 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7387 /* We never give out valid handles for a
7388 findnotifyfirst - so any dptr_num is ok here.
7389 Just ignore it. */
7391 reply_outbuf(req, 0, 0);
7393 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7395 END_PROFILE(SMBfindnclose);
7396 return;
7399 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7400 struct trans_state *state)
7402 if (Protocol >= PROTOCOL_NT1) {
7403 req->flags2 |= 0x40; /* IS_LONG_NAME */
7404 SSVAL(req->inbuf,smb_flg2,req->flags2);
7407 if (conn->encrypt_level == Required && !req->encrypted) {
7408 if (state->call != TRANSACT2_QFSINFO &&
7409 state->call != TRANSACT2_SETFSINFO) {
7410 DEBUG(0,("handle_trans2: encryption required "
7411 "with call 0x%x\n",
7412 (unsigned int)state->call));
7413 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7414 return;
7418 /* Now we must call the relevant TRANS2 function */
7419 switch(state->call) {
7420 case TRANSACT2_OPEN:
7422 START_PROFILE(Trans2_open);
7423 call_trans2open(conn, req,
7424 &state->param, state->total_param,
7425 &state->data, state->total_data,
7426 state->max_data_return);
7427 END_PROFILE(Trans2_open);
7428 break;
7431 case TRANSACT2_FINDFIRST:
7433 START_PROFILE(Trans2_findfirst);
7434 call_trans2findfirst(conn, req,
7435 &state->param, state->total_param,
7436 &state->data, state->total_data,
7437 state->max_data_return);
7438 END_PROFILE(Trans2_findfirst);
7439 break;
7442 case TRANSACT2_FINDNEXT:
7444 START_PROFILE(Trans2_findnext);
7445 call_trans2findnext(conn, req,
7446 &state->param, state->total_param,
7447 &state->data, state->total_data,
7448 state->max_data_return);
7449 END_PROFILE(Trans2_findnext);
7450 break;
7453 case TRANSACT2_QFSINFO:
7455 START_PROFILE(Trans2_qfsinfo);
7456 call_trans2qfsinfo(conn, req,
7457 &state->param, state->total_param,
7458 &state->data, state->total_data,
7459 state->max_data_return);
7460 END_PROFILE(Trans2_qfsinfo);
7461 break;
7464 case TRANSACT2_SETFSINFO:
7466 START_PROFILE(Trans2_setfsinfo);
7467 call_trans2setfsinfo(conn, req,
7468 &state->param, state->total_param,
7469 &state->data, state->total_data,
7470 state->max_data_return);
7471 END_PROFILE(Trans2_setfsinfo);
7472 break;
7475 case TRANSACT2_QPATHINFO:
7476 case TRANSACT2_QFILEINFO:
7478 START_PROFILE(Trans2_qpathinfo);
7479 call_trans2qfilepathinfo(conn, req, state->call,
7480 &state->param, state->total_param,
7481 &state->data, state->total_data,
7482 state->max_data_return);
7483 END_PROFILE(Trans2_qpathinfo);
7484 break;
7487 case TRANSACT2_SETPATHINFO:
7488 case TRANSACT2_SETFILEINFO:
7490 START_PROFILE(Trans2_setpathinfo);
7491 call_trans2setfilepathinfo(conn, req, state->call,
7492 &state->param, state->total_param,
7493 &state->data, state->total_data,
7494 state->max_data_return);
7495 END_PROFILE(Trans2_setpathinfo);
7496 break;
7499 case TRANSACT2_FINDNOTIFYFIRST:
7501 START_PROFILE(Trans2_findnotifyfirst);
7502 call_trans2findnotifyfirst(conn, req,
7503 &state->param, state->total_param,
7504 &state->data, state->total_data,
7505 state->max_data_return);
7506 END_PROFILE(Trans2_findnotifyfirst);
7507 break;
7510 case TRANSACT2_FINDNOTIFYNEXT:
7512 START_PROFILE(Trans2_findnotifynext);
7513 call_trans2findnotifynext(conn, req,
7514 &state->param, state->total_param,
7515 &state->data, state->total_data,
7516 state->max_data_return);
7517 END_PROFILE(Trans2_findnotifynext);
7518 break;
7521 case TRANSACT2_MKDIR:
7523 START_PROFILE(Trans2_mkdir);
7524 call_trans2mkdir(conn, req,
7525 &state->param, state->total_param,
7526 &state->data, state->total_data,
7527 state->max_data_return);
7528 END_PROFILE(Trans2_mkdir);
7529 break;
7532 case TRANSACT2_GET_DFS_REFERRAL:
7534 START_PROFILE(Trans2_get_dfs_referral);
7535 call_trans2getdfsreferral(conn, req,
7536 &state->param, state->total_param,
7537 &state->data, state->total_data,
7538 state->max_data_return);
7539 END_PROFILE(Trans2_get_dfs_referral);
7540 break;
7543 case TRANSACT2_IOCTL:
7545 START_PROFILE(Trans2_ioctl);
7546 call_trans2ioctl(conn, req,
7547 &state->param, state->total_param,
7548 &state->data, state->total_data,
7549 state->max_data_return);
7550 END_PROFILE(Trans2_ioctl);
7551 break;
7554 default:
7555 /* Error in request */
7556 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7557 reply_doserror(req, ERRSRV,ERRerror);
7561 /****************************************************************************
7562 Reply to a SMBtrans2.
7563 ****************************************************************************/
7565 void reply_trans2(struct smb_request *req)
7567 connection_struct *conn = req->conn;
7568 unsigned int dsoff;
7569 unsigned int dscnt;
7570 unsigned int psoff;
7571 unsigned int pscnt;
7572 unsigned int tran_call;
7573 unsigned int size;
7574 unsigned int av_size;
7575 struct trans_state *state;
7576 NTSTATUS result;
7578 START_PROFILE(SMBtrans2);
7580 if (req->wct < 14) {
7581 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7582 END_PROFILE(SMBtrans2);
7583 return;
7586 dsoff = SVAL(req->inbuf, smb_dsoff);
7587 dscnt = SVAL(req->inbuf, smb_dscnt);
7588 psoff = SVAL(req->inbuf, smb_psoff);
7589 pscnt = SVAL(req->inbuf, smb_pscnt);
7590 tran_call = SVAL(req->inbuf, smb_setup0);
7591 size = smb_len(req->inbuf) + 4;
7592 av_size = smb_len(req->inbuf);
7594 result = allow_new_trans(conn->pending_trans, req->mid);
7595 if (!NT_STATUS_IS_OK(result)) {
7596 DEBUG(2, ("Got invalid trans2 request: %s\n",
7597 nt_errstr(result)));
7598 reply_nterror(req, result);
7599 END_PROFILE(SMBtrans2);
7600 return;
7603 if (IS_IPC(conn)) {
7604 switch (tran_call) {
7605 /* List the allowed trans2 calls on IPC$ */
7606 case TRANSACT2_OPEN:
7607 case TRANSACT2_GET_DFS_REFERRAL:
7608 case TRANSACT2_QFILEINFO:
7609 case TRANSACT2_QFSINFO:
7610 case TRANSACT2_SETFSINFO:
7611 break;
7612 default:
7613 reply_doserror(req, ERRSRV, ERRaccess);
7614 END_PROFILE(SMBtrans2);
7615 return;
7619 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7620 DEBUG(0, ("talloc failed\n"));
7621 reply_nterror(req, NT_STATUS_NO_MEMORY);
7622 END_PROFILE(SMBtrans2);
7623 return;
7626 state->cmd = SMBtrans2;
7628 state->mid = req->mid;
7629 state->vuid = req->vuid;
7630 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7631 state->setup = NULL;
7632 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7633 state->param = NULL;
7634 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7635 state->data = NULL;
7636 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7637 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7638 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7639 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7640 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7642 state->call = tran_call;
7644 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7645 is so as a sanity check */
7646 if (state->setup_count != 1) {
7648 * Need to have rc=0 for ioctl to get job id for OS/2.
7649 * Network printing will fail if function is not successful.
7650 * Similar function in reply.c will be used if protocol
7651 * is LANMAN1.0 instead of LM1.2X002.
7652 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7653 * outbuf doesn't have to be set(only job id is used).
7655 if ( (state->setup_count == 4)
7656 && (tran_call == TRANSACT2_IOCTL)
7657 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7658 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7659 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7660 } else {
7661 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7662 DEBUG(2,("Transaction is %d\n",tran_call));
7663 TALLOC_FREE(state);
7664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7665 END_PROFILE(SMBtrans2);
7666 return;
7670 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7671 goto bad_param;
7673 if (state->total_data) {
7674 /* Can't use talloc here, the core routines do realloc on the
7675 * params and data. */
7676 state->data = (char *)SMB_MALLOC(state->total_data);
7677 if (state->data == NULL) {
7678 DEBUG(0,("reply_trans2: data malloc fail for %u "
7679 "bytes !\n", (unsigned int)state->total_data));
7680 TALLOC_FREE(state);
7681 reply_nterror(req, NT_STATUS_NO_MEMORY);
7682 END_PROFILE(SMBtrans2);
7683 return;
7686 if (dscnt > state->total_data ||
7687 dsoff+dscnt < dsoff) {
7688 goto bad_param;
7691 if (dsoff > av_size ||
7692 dscnt > av_size ||
7693 dsoff+dscnt > av_size) {
7694 goto bad_param;
7697 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7700 if (state->total_param) {
7701 /* Can't use talloc here, the core routines do realloc on the
7702 * params and data. */
7703 state->param = (char *)SMB_MALLOC(state->total_param);
7704 if (state->param == NULL) {
7705 DEBUG(0,("reply_trans: param malloc fail for %u "
7706 "bytes !\n", (unsigned int)state->total_param));
7707 SAFE_FREE(state->data);
7708 TALLOC_FREE(state);
7709 reply_nterror(req, NT_STATUS_NO_MEMORY);
7710 END_PROFILE(SMBtrans2);
7711 return;
7714 if (pscnt > state->total_param ||
7715 psoff+pscnt < psoff) {
7716 goto bad_param;
7719 if (psoff > av_size ||
7720 pscnt > av_size ||
7721 psoff+pscnt > av_size) {
7722 goto bad_param;
7725 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7728 state->received_data = dscnt;
7729 state->received_param = pscnt;
7731 if ((state->received_param == state->total_param) &&
7732 (state->received_data == state->total_data)) {
7734 handle_trans2(conn, req, state);
7736 SAFE_FREE(state->data);
7737 SAFE_FREE(state->param);
7738 TALLOC_FREE(state);
7739 END_PROFILE(SMBtrans2);
7740 return;
7743 DLIST_ADD(conn->pending_trans, state);
7745 /* We need to send an interim response then receive the rest
7746 of the parameter/data bytes */
7747 reply_outbuf(req, 0, 0);
7748 show_msg((char *)req->outbuf);
7749 END_PROFILE(SMBtrans2);
7750 return;
7752 bad_param:
7754 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7755 SAFE_FREE(state->data);
7756 SAFE_FREE(state->param);
7757 TALLOC_FREE(state);
7758 END_PROFILE(SMBtrans2);
7759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7763 /****************************************************************************
7764 Reply to a SMBtranss2
7765 ****************************************************************************/
7767 void reply_transs2(struct smb_request *req)
7769 connection_struct *conn = req->conn;
7770 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7771 struct trans_state *state;
7772 unsigned int size;
7773 unsigned int av_size;
7775 START_PROFILE(SMBtranss2);
7777 show_msg((char *)req->inbuf);
7779 if (req->wct < 8) {
7780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7781 END_PROFILE(SMBtranss2);
7782 return;
7785 size = smb_len(req->inbuf)+4;
7786 av_size = smb_len(req->inbuf);
7788 for (state = conn->pending_trans; state != NULL;
7789 state = state->next) {
7790 if (state->mid == req->mid) {
7791 break;
7795 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7797 END_PROFILE(SMBtranss2);
7798 return;
7801 /* Revise state->total_param and state->total_data in case they have
7802 changed downwards */
7804 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7805 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7806 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7807 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7809 pcnt = SVAL(req->inbuf, smb_spscnt);
7810 poff = SVAL(req->inbuf, smb_spsoff);
7811 pdisp = SVAL(req->inbuf, smb_spsdisp);
7813 dcnt = SVAL(req->inbuf, smb_sdscnt);
7814 doff = SVAL(req->inbuf, smb_sdsoff);
7815 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7817 state->received_param += pcnt;
7818 state->received_data += dcnt;
7820 if ((state->received_data > state->total_data) ||
7821 (state->received_param > state->total_param))
7822 goto bad_param;
7824 if (pcnt) {
7825 if (pdisp > state->total_param ||
7826 pcnt > state->total_param ||
7827 pdisp+pcnt > state->total_param ||
7828 pdisp+pcnt < pdisp) {
7829 goto bad_param;
7832 if (poff > av_size ||
7833 pcnt > av_size ||
7834 poff+pcnt > av_size ||
7835 poff+pcnt < poff) {
7836 goto bad_param;
7839 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7840 pcnt);
7843 if (dcnt) {
7844 if (ddisp > state->total_data ||
7845 dcnt > state->total_data ||
7846 ddisp+dcnt > state->total_data ||
7847 ddisp+dcnt < ddisp) {
7848 goto bad_param;
7851 if (doff > av_size ||
7852 dcnt > av_size ||
7853 doff+dcnt > av_size ||
7854 doff+dcnt < doff) {
7855 goto bad_param;
7858 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7859 dcnt);
7862 if ((state->received_param < state->total_param) ||
7863 (state->received_data < state->total_data)) {
7864 END_PROFILE(SMBtranss2);
7865 return;
7869 * construct_reply_common will copy smb_com from inbuf to
7870 * outbuf. SMBtranss2 is wrong here.
7872 SCVAL(req->inbuf,smb_com,SMBtrans2);
7874 handle_trans2(conn, req, state);
7876 DLIST_REMOVE(conn->pending_trans, state);
7877 SAFE_FREE(state->data);
7878 SAFE_FREE(state->param);
7879 TALLOC_FREE(state);
7881 END_PROFILE(SMBtranss2);
7882 return;
7884 bad_param:
7886 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7887 DLIST_REMOVE(conn->pending_trans, state);
7888 SAFE_FREE(state->data);
7889 SAFE_FREE(state->param);
7890 TALLOC_FREE(state);
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7892 END_PROFILE(SMBtranss2);
7893 return;