s3:smbd: return DELETE_PENDING on path based operations on streams, when the main...
[Samba.git] / source / smbd / trans2.c
blob89a79111c9a1c17415b7ca0be627c47fffec5688
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 (conn->case_sensitive)
1084 return strcmp(str,mask)==0;
1085 if (StrCaseCmp(str,mask) != 0) {
1086 return False;
1088 if (dptr_has_wild(conn->dirptr)) {
1089 return False;
1091 return True;
1094 /****************************************************************************
1095 Return the filetype for UNIX extensions.
1096 ****************************************************************************/
1098 static uint32 unix_filetype(mode_t mode)
1100 if(S_ISREG(mode))
1101 return UNIX_TYPE_FILE;
1102 else if(S_ISDIR(mode))
1103 return UNIX_TYPE_DIR;
1104 #ifdef S_ISLNK
1105 else if(S_ISLNK(mode))
1106 return UNIX_TYPE_SYMLINK;
1107 #endif
1108 #ifdef S_ISCHR
1109 else if(S_ISCHR(mode))
1110 return UNIX_TYPE_CHARDEV;
1111 #endif
1112 #ifdef S_ISBLK
1113 else if(S_ISBLK(mode))
1114 return UNIX_TYPE_BLKDEV;
1115 #endif
1116 #ifdef S_ISFIFO
1117 else if(S_ISFIFO(mode))
1118 return UNIX_TYPE_FIFO;
1119 #endif
1120 #ifdef S_ISSOCK
1121 else if(S_ISSOCK(mode))
1122 return UNIX_TYPE_SOCKET;
1123 #endif
1125 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1126 return UNIX_TYPE_UNKNOWN;
1129 /****************************************************************************
1130 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1131 ****************************************************************************/
1133 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1135 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1136 SMB_STRUCT_STAT *psbuf,
1137 uint32 perms,
1138 enum perm_type ptype,
1139 mode_t *ret_perms)
1141 mode_t ret = 0;
1143 if (perms == SMB_MODE_NO_CHANGE) {
1144 if (!VALID_STAT(*psbuf)) {
1145 return NT_STATUS_INVALID_PARAMETER;
1146 } else {
1147 *ret_perms = psbuf->st_mode;
1148 return NT_STATUS_OK;
1152 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1153 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1154 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1155 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1156 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1157 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1158 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1159 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1160 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1161 #ifdef S_ISVTX
1162 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1163 #endif
1164 #ifdef S_ISGID
1165 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1166 #endif
1167 #ifdef S_ISUID
1168 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1169 #endif
1171 switch (ptype) {
1172 case PERM_NEW_FILE:
1173 /* Apply mode mask */
1174 ret &= lp_create_mask(SNUM(conn));
1175 /* Add in force bits */
1176 ret |= lp_force_create_mode(SNUM(conn));
1177 break;
1178 case PERM_NEW_DIR:
1179 ret &= lp_dir_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_dir_mode(SNUM(conn));
1182 break;
1183 case PERM_EXISTING_FILE:
1184 /* Apply mode mask */
1185 ret &= lp_security_mask(SNUM(conn));
1186 /* Add in force bits */
1187 ret |= lp_force_security_mode(SNUM(conn));
1188 break;
1189 case PERM_EXISTING_DIR:
1190 /* Apply mode mask */
1191 ret &= lp_dir_security_mask(SNUM(conn));
1192 /* Add in force bits */
1193 ret |= lp_force_dir_security_mode(SNUM(conn));
1194 break;
1197 *ret_perms = ret;
1198 return NT_STATUS_OK;
1201 /****************************************************************************
1202 Needed to show the msdfs symlinks as directories. Modifies psbuf
1203 to be a directory if it's a msdfs link.
1204 ****************************************************************************/
1206 static bool check_msdfs_link(connection_struct *conn,
1207 const char *pathname,
1208 SMB_STRUCT_STAT *psbuf)
1210 int saved_errno = errno;
1211 if(lp_host_msdfs() &&
1212 lp_msdfs_root(SNUM(conn)) &&
1213 is_msdfs_link(conn, pathname, psbuf)) {
1215 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1216 "as a directory\n",
1217 pathname));
1218 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1219 errno = saved_errno;
1220 return true;
1222 errno = saved_errno;
1223 return false;
1227 /****************************************************************************
1228 Get a level dependent lanman2 dir entry.
1229 ****************************************************************************/
1231 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1232 connection_struct *conn,
1233 uint16 flags2,
1234 const char *path_mask,
1235 uint32 dirtype,
1236 int info_level,
1237 int requires_resume_key,
1238 bool dont_descend,
1239 bool ask_sharemode,
1240 char **ppdata,
1241 char *base_data,
1242 char *end_data,
1243 int space_remaining,
1244 bool *out_of_space,
1245 bool *got_exact_match,
1246 int *last_entry_off,
1247 struct ea_list *name_list)
1249 const char *dname;
1250 bool found = False;
1251 SMB_STRUCT_STAT sbuf;
1252 const char *mask = NULL;
1253 char *pathreal = NULL;
1254 const char *fname = NULL;
1255 char *p, *q, *pdata = *ppdata;
1256 uint32 reskey=0;
1257 long prev_dirpos=0;
1258 uint32 mode=0;
1259 SMB_OFF_T file_size = 0;
1260 SMB_BIG_UINT allocation_size = 0;
1261 uint32 len;
1262 struct timespec mdate_ts, adate_ts, create_date_ts;
1263 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1264 char *nameptr;
1265 char *last_entry_ptr;
1266 bool was_8_3;
1267 uint32 nt_extmode; /* Used for NT connections instead of mode */
1268 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1269 bool check_mangled_names = lp_manglednames(conn->params);
1270 char mangled_name[13]; /* mangled 8.3 name. */
1272 *out_of_space = False;
1273 *got_exact_match = False;
1275 ZERO_STRUCT(mdate_ts);
1276 ZERO_STRUCT(adate_ts);
1277 ZERO_STRUCT(create_date_ts);
1279 if (!conn->dirptr) {
1280 return(False);
1283 p = strrchr_m(path_mask,'/');
1284 if(p != NULL) {
1285 if(p[1] == '\0') {
1286 mask = talloc_strdup(ctx,"*.*");
1287 } else {
1288 mask = p+1;
1290 } else {
1291 mask = path_mask;
1294 while (!found) {
1295 bool got_match;
1296 bool ms_dfs_link = False;
1298 /* Needed if we run out of space */
1299 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1300 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1303 * Due to bugs in NT client redirectors we are not using
1304 * resume keys any more - set them to zero.
1305 * Check out the related comments in findfirst/findnext.
1306 * JRA.
1309 reskey = 0;
1311 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1312 (long)conn->dirptr,curr_dirpos));
1314 if (!dname) {
1315 return(False);
1319 * fname may get mangled, dname is never mangled.
1320 * Whenever we're accessing the filesystem we use
1321 * pathreal which is composed from dname.
1324 pathreal = NULL;
1325 fname = dname;
1327 /* Mangle fname if it's an illegal name. */
1328 if (mangle_must_mangle(dname,conn->params)) {
1329 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1330 continue; /* Error - couldn't mangle. */
1332 fname = mangled_name;
1335 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1336 got_match = mask_match(fname, mask, conn->case_sensitive);
1339 if(!got_match && check_mangled_names &&
1340 !mangle_is_8_3(fname, False, conn->params)) {
1342 * It turns out that NT matches wildcards against
1343 * both long *and* short names. This may explain some
1344 * of the wildcard wierdness from old DOS clients
1345 * that some people have been seeing.... JRA.
1347 /* Force the mangling into 8.3. */
1348 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1349 continue; /* Error - couldn't mangle. */
1352 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1353 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1357 if (got_match) {
1358 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1360 if (dont_descend && !isdots) {
1361 continue;
1364 if (needslash) {
1365 pathreal = NULL;
1366 pathreal = talloc_asprintf(ctx,
1367 "%s/%s",
1368 conn->dirpath,
1369 dname);
1370 } else {
1371 pathreal = talloc_asprintf(ctx,
1372 "%s%s",
1373 conn->dirpath,
1374 dname);
1377 if (!pathreal) {
1378 return False;
1381 if (INFO_LEVEL_IS_UNIX(info_level)) {
1382 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1383 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1384 pathreal,strerror(errno)));
1385 TALLOC_FREE(pathreal);
1386 continue;
1388 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1389 /* Needed to show the msdfs symlinks as
1390 * directories */
1392 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1393 if (!ms_dfs_link) {
1394 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395 pathreal,strerror(errno)));
1396 TALLOC_FREE(pathreal);
1397 continue;
1401 if (ms_dfs_link) {
1402 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1403 } else {
1404 mode = dos_mode(conn,pathreal,&sbuf);
1407 if (!dir_check_ftype(conn,mode,dirtype)) {
1408 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1409 TALLOC_FREE(pathreal);
1410 continue;
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size(sbuf);
1416 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1418 mdate_ts = get_mtimespec(&sbuf);
1419 adate_ts = get_atimespec(&sbuf);
1420 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1422 if (ask_sharemode) {
1423 struct timespec write_time_ts;
1424 struct file_id fileid;
1426 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1427 get_file_infos(fileid, NULL, &write_time_ts);
1428 if (!null_timespec(write_time_ts)) {
1429 mdate_ts = write_time_ts;
1433 if (lp_dos_filetime_resolution(SNUM(conn))) {
1434 dos_filetime_timespec(&create_date_ts);
1435 dos_filetime_timespec(&mdate_ts);
1436 dos_filetime_timespec(&adate_ts);
1439 create_date = convert_timespec_to_time_t(create_date_ts);
1440 mdate = convert_timespec_to_time_t(mdate_ts);
1441 adate = convert_timespec_to_time_t(adate_ts);
1443 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1445 found = True;
1447 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1451 p = pdata;
1452 last_entry_ptr = p;
1454 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1456 switch (info_level) {
1457 case SMB_FIND_INFO_STANDARD:
1458 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1459 if(requires_resume_key) {
1460 SIVAL(p,0,reskey);
1461 p += 4;
1463 srv_put_dos_date2(p,0,create_date);
1464 srv_put_dos_date2(p,4,adate);
1465 srv_put_dos_date2(p,8,mdate);
1466 SIVAL(p,12,(uint32)file_size);
1467 SIVAL(p,16,(uint32)allocation_size);
1468 SSVAL(p,20,mode);
1469 p += 23;
1470 nameptr = p;
1471 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1472 p += ucs2_align(base_data, p, 0);
1474 len = srvstr_push(base_data, flags2, p,
1475 fname, PTR_DIFF(end_data, p),
1476 STR_TERMINATE);
1477 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1478 if (len > 2) {
1479 SCVAL(nameptr, -1, len - 2);
1480 } else {
1481 SCVAL(nameptr, -1, 0);
1483 } else {
1484 if (len > 1) {
1485 SCVAL(nameptr, -1, len - 1);
1486 } else {
1487 SCVAL(nameptr, -1, 0);
1490 p += len;
1491 break;
1493 case SMB_FIND_EA_SIZE:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1495 if(requires_resume_key) {
1496 SIVAL(p,0,reskey);
1497 p += 4;
1499 srv_put_dos_date2(p,0,create_date);
1500 srv_put_dos_date2(p,4,adate);
1501 srv_put_dos_date2(p,8,mdate);
1502 SIVAL(p,12,(uint32)file_size);
1503 SIVAL(p,16,(uint32)allocation_size);
1504 SSVAL(p,20,mode);
1506 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1507 SIVAL(p,22,ea_size); /* Extended attributes */
1509 p += 27;
1510 nameptr = p - 1;
1511 len = srvstr_push(base_data, flags2,
1512 p, fname, PTR_DIFF(end_data, p),
1513 STR_TERMINATE | STR_NOALIGN);
1514 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1515 if (len > 2) {
1516 len -= 2;
1517 } else {
1518 len = 0;
1520 } else {
1521 if (len > 1) {
1522 len -= 1;
1523 } else {
1524 len = 0;
1527 SCVAL(nameptr,0,len);
1528 p += len;
1529 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1530 break;
1532 case SMB_FIND_EA_LIST:
1534 struct ea_list *file_list = NULL;
1535 size_t ea_len = 0;
1537 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1538 if (!name_list) {
1539 return False;
1541 if(requires_resume_key) {
1542 SIVAL(p,0,reskey);
1543 p += 4;
1545 srv_put_dos_date2(p,0,create_date);
1546 srv_put_dos_date2(p,4,adate);
1547 srv_put_dos_date2(p,8,mdate);
1548 SIVAL(p,12,(uint32)file_size);
1549 SIVAL(p,16,(uint32)allocation_size);
1550 SSVAL(p,20,mode);
1551 p += 22; /* p now points to the EA area. */
1553 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1554 name_list = ea_list_union(name_list, file_list, &ea_len);
1556 /* We need to determine if this entry will fit in the space available. */
1557 /* Max string size is 255 bytes. */
1558 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1559 /* Move the dirptr back to prev_dirpos */
1560 dptr_SeekDir(conn->dirptr, prev_dirpos);
1561 *out_of_space = True;
1562 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1563 return False; /* Not finished - just out of space */
1566 /* Push the ea_data followed by the name. */
1567 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1568 nameptr = p;
1569 len = srvstr_push(base_data, flags2,
1570 p + 1, fname, PTR_DIFF(end_data, p+1),
1571 STR_TERMINATE | STR_NOALIGN);
1572 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1573 if (len > 2) {
1574 len -= 2;
1575 } else {
1576 len = 0;
1578 } else {
1579 if (len > 1) {
1580 len -= 1;
1581 } else {
1582 len = 0;
1585 SCVAL(nameptr,0,len);
1586 p += len + 1;
1587 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1588 break;
1591 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1592 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1593 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1594 p += 4;
1595 SIVAL(p,0,reskey); p += 4;
1596 put_long_date_timespec(p,create_date_ts); p += 8;
1597 put_long_date_timespec(p,adate_ts); p += 8;
1598 put_long_date_timespec(p,mdate_ts); p += 8;
1599 put_long_date_timespec(p,mdate_ts); p += 8;
1600 SOFF_T(p,0,file_size); p += 8;
1601 SOFF_T(p,0,allocation_size); p += 8;
1602 SIVAL(p,0,nt_extmode); p += 4;
1603 q = p; p += 4; /* q is placeholder for name length. */
1605 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1606 SIVAL(p,0,ea_size); /* Extended attributes */
1607 p += 4;
1609 /* Clear the short name buffer. This is
1610 * IMPORTANT as not doing so will trigger
1611 * a Win2k client bug. JRA.
1613 if (!was_8_3 && check_mangled_names) {
1614 if (!name_to_8_3(fname,mangled_name,True,
1615 conn->params)) {
1616 /* Error - mangle failed ! */
1617 memset(mangled_name,'\0',12);
1619 mangled_name[12] = 0;
1620 len = srvstr_push(base_data, flags2,
1621 p+2, mangled_name, 24,
1622 STR_UPPER|STR_UNICODE);
1623 if (len < 24) {
1624 memset(p + 2 + len,'\0',24 - len);
1626 SSVAL(p, 0, len);
1627 } else {
1628 memset(p,'\0',26);
1630 p += 2 + 24;
1631 len = srvstr_push(base_data, flags2, p,
1632 fname, PTR_DIFF(end_data, p),
1633 STR_TERMINATE_ASCII);
1634 SIVAL(q,0,len);
1635 p += len;
1636 SIVAL(p,0,0); /* Ensure any padding is null. */
1637 len = PTR_DIFF(p, pdata);
1638 len = (len + 3) & ~3;
1639 SIVAL(pdata,0,len);
1640 p = pdata + len;
1641 break;
1643 case SMB_FIND_FILE_DIRECTORY_INFO:
1644 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1645 p += 4;
1646 SIVAL(p,0,reskey); p += 4;
1647 put_long_date_timespec(p,create_date_ts); p += 8;
1648 put_long_date_timespec(p,adate_ts); p += 8;
1649 put_long_date_timespec(p,mdate_ts); p += 8;
1650 put_long_date_timespec(p,mdate_ts); p += 8;
1651 SOFF_T(p,0,file_size); p += 8;
1652 SOFF_T(p,0,allocation_size); p += 8;
1653 SIVAL(p,0,nt_extmode); p += 4;
1654 len = srvstr_push(base_data, flags2,
1655 p + 4, fname, PTR_DIFF(end_data, p+4),
1656 STR_TERMINATE_ASCII);
1657 SIVAL(p,0,len);
1658 p += 4 + len;
1659 SIVAL(p,0,0); /* Ensure any padding is null. */
1660 len = PTR_DIFF(p, pdata);
1661 len = (len + 3) & ~3;
1662 SIVAL(pdata,0,len);
1663 p = pdata + len;
1664 break;
1666 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1667 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1668 p += 4;
1669 SIVAL(p,0,reskey); p += 4;
1670 put_long_date_timespec(p,create_date_ts); p += 8;
1671 put_long_date_timespec(p,adate_ts); p += 8;
1672 put_long_date_timespec(p,mdate_ts); p += 8;
1673 put_long_date_timespec(p,mdate_ts); p += 8;
1674 SOFF_T(p,0,file_size); p += 8;
1675 SOFF_T(p,0,allocation_size); p += 8;
1676 SIVAL(p,0,nt_extmode); p += 4;
1677 q = p; p += 4; /* q is placeholder for name length. */
1679 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1680 SIVAL(p,0,ea_size); /* Extended attributes */
1681 p +=4;
1683 len = srvstr_push(base_data, flags2, p,
1684 fname, PTR_DIFF(end_data, p),
1685 STR_TERMINATE_ASCII);
1686 SIVAL(q, 0, len);
1687 p += len;
1689 SIVAL(p,0,0); /* Ensure any padding is null. */
1690 len = PTR_DIFF(p, pdata);
1691 len = (len + 3) & ~3;
1692 SIVAL(pdata,0,len);
1693 p = pdata + len;
1694 break;
1696 case SMB_FIND_FILE_NAMES_INFO:
1697 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1698 p += 4;
1699 SIVAL(p,0,reskey); p += 4;
1700 p += 4;
1701 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1702 acl on a dir (tridge) */
1703 len = srvstr_push(base_data, flags2, p,
1704 fname, PTR_DIFF(end_data, p),
1705 STR_TERMINATE_ASCII);
1706 SIVAL(p, -4, len);
1707 p += len;
1708 SIVAL(p,0,0); /* Ensure any padding is null. */
1709 len = PTR_DIFF(p, pdata);
1710 len = (len + 3) & ~3;
1711 SIVAL(pdata,0,len);
1712 p = pdata + len;
1713 break;
1715 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1716 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1717 p += 4;
1718 SIVAL(p,0,reskey); p += 4;
1719 put_long_date_timespec(p,create_date_ts); p += 8;
1720 put_long_date_timespec(p,adate_ts); p += 8;
1721 put_long_date_timespec(p,mdate_ts); p += 8;
1722 put_long_date_timespec(p,mdate_ts); p += 8;
1723 SOFF_T(p,0,file_size); p += 8;
1724 SOFF_T(p,0,allocation_size); p += 8;
1725 SIVAL(p,0,nt_extmode); p += 4;
1726 q = p; p += 4; /* q is placeholder for name length. */
1728 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1729 SIVAL(p,0,ea_size); /* Extended attributes */
1730 p +=4;
1732 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1733 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1734 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1735 len = srvstr_push(base_data, flags2, p,
1736 fname, PTR_DIFF(end_data, p),
1737 STR_TERMINATE_ASCII);
1738 SIVAL(q, 0, len);
1739 p += len;
1740 SIVAL(p,0,0); /* Ensure any padding is null. */
1741 len = PTR_DIFF(p, pdata);
1742 len = (len + 3) & ~3;
1743 SIVAL(pdata,0,len);
1744 p = pdata + len;
1745 break;
1747 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1748 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1749 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1750 p += 4;
1751 SIVAL(p,0,reskey); p += 4;
1752 put_long_date_timespec(p,create_date_ts); p += 8;
1753 put_long_date_timespec(p,adate_ts); p += 8;
1754 put_long_date_timespec(p,mdate_ts); p += 8;
1755 put_long_date_timespec(p,mdate_ts); p += 8;
1756 SOFF_T(p,0,file_size); p += 8;
1757 SOFF_T(p,0,allocation_size); p += 8;
1758 SIVAL(p,0,nt_extmode); p += 4;
1759 q = p; p += 4; /* q is placeholder for name length */
1761 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1762 SIVAL(p,0,ea_size); /* Extended attributes */
1763 p +=4;
1765 /* Clear the short name buffer. This is
1766 * IMPORTANT as not doing so will trigger
1767 * a Win2k client bug. JRA.
1769 if (!was_8_3 && check_mangled_names) {
1770 if (!name_to_8_3(fname,mangled_name,True,
1771 conn->params)) {
1772 /* Error - mangle failed ! */
1773 memset(mangled_name,'\0',12);
1775 mangled_name[12] = 0;
1776 len = srvstr_push(base_data, flags2,
1777 p+2, mangled_name, 24,
1778 STR_UPPER|STR_UNICODE);
1779 SSVAL(p, 0, len);
1780 if (len < 24) {
1781 memset(p + 2 + len,'\0',24 - len);
1783 SSVAL(p, 0, len);
1784 } else {
1785 memset(p,'\0',26);
1787 p += 26;
1788 SSVAL(p,0,0); p += 2; /* Reserved ? */
1789 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1790 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1791 len = srvstr_push(base_data, flags2, p,
1792 fname, PTR_DIFF(end_data, p),
1793 STR_TERMINATE_ASCII);
1794 SIVAL(q,0,len);
1795 p += len;
1796 SIVAL(p,0,0); /* Ensure any padding is null. */
1797 len = PTR_DIFF(p, pdata);
1798 len = (len + 3) & ~3;
1799 SIVAL(pdata,0,len);
1800 p = pdata + len;
1801 break;
1803 /* CIFS UNIX Extension. */
1805 case SMB_FIND_FILE_UNIX:
1806 case SMB_FIND_FILE_UNIX_INFO2:
1807 p+= 4;
1808 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1810 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1812 if (info_level == SMB_FIND_FILE_UNIX) {
1813 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1814 p = store_file_unix_basic(conn, p,
1815 NULL, &sbuf);
1816 len = srvstr_push(base_data, flags2, p,
1817 fname, PTR_DIFF(end_data, p),
1818 STR_TERMINATE);
1819 } else {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1821 p = store_file_unix_basic_info2(conn, p,
1822 NULL, &sbuf);
1823 nameptr = p;
1824 p += 4;
1825 len = srvstr_push(base_data, flags2, p, fname,
1826 PTR_DIFF(end_data, p), 0);
1827 SIVAL(nameptr, 0, len);
1830 p += len;
1831 SIVAL(p,0,0); /* Ensure any padding is null. */
1833 len = PTR_DIFF(p, pdata);
1834 len = (len + 3) & ~3;
1835 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1836 p = pdata + len;
1837 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1839 break;
1841 default:
1842 return(False);
1846 if (PTR_DIFF(p,pdata) > space_remaining) {
1847 /* Move the dirptr back to prev_dirpos */
1848 dptr_SeekDir(conn->dirptr, prev_dirpos);
1849 *out_of_space = True;
1850 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1851 return False; /* Not finished - just out of space */
1854 /* Setup the last entry pointer, as an offset from base_data */
1855 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1856 /* Advance the data pointer to the next slot */
1857 *ppdata = p;
1859 return(found);
1862 /****************************************************************************
1863 Reply to a TRANS2_FINDFIRST.
1864 ****************************************************************************/
1866 static void call_trans2findfirst(connection_struct *conn,
1867 struct smb_request *req,
1868 char **pparams, int total_params,
1869 char **ppdata, int total_data,
1870 unsigned int max_data_bytes)
1872 /* We must be careful here that we don't return more than the
1873 allowed number of data bytes. If this means returning fewer than
1874 maxentries then so be it. We assume that the redirector has
1875 enough room for the fixed number of parameter bytes it has
1876 requested. */
1877 char *params = *pparams;
1878 char *pdata = *ppdata;
1879 char *data_end;
1880 uint32 dirtype;
1881 int maxentries;
1882 uint16 findfirst_flags;
1883 bool close_after_first;
1884 bool close_if_end;
1885 bool requires_resume_key;
1886 int info_level;
1887 char *directory = NULL;
1888 char *mask = NULL;
1889 char *p;
1890 int last_entry_off=0;
1891 int dptr_num = -1;
1892 int numentries = 0;
1893 int i;
1894 bool finished = False;
1895 bool dont_descend = False;
1896 bool out_of_space = False;
1897 int space_remaining;
1898 bool mask_contains_wcard = False;
1899 SMB_STRUCT_STAT sbuf;
1900 struct ea_list *ea_list = NULL;
1901 NTSTATUS ntstatus = NT_STATUS_OK;
1902 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1903 TALLOC_CTX *ctx = talloc_tos();
1905 if (total_params < 13) {
1906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1907 return;
1910 dirtype = SVAL(params,0);
1911 maxentries = SVAL(params,2);
1912 findfirst_flags = SVAL(params,4);
1913 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1914 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1915 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1916 info_level = SVAL(params,6);
1918 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1919 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1920 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1921 info_level, max_data_bytes));
1923 if (!maxentries) {
1924 /* W2K3 seems to treat zero as 1. */
1925 maxentries = 1;
1928 switch (info_level) {
1929 case SMB_FIND_INFO_STANDARD:
1930 case SMB_FIND_EA_SIZE:
1931 case SMB_FIND_EA_LIST:
1932 case SMB_FIND_FILE_DIRECTORY_INFO:
1933 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1934 case SMB_FIND_FILE_NAMES_INFO:
1935 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1936 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1937 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1938 break;
1939 case SMB_FIND_FILE_UNIX:
1940 case SMB_FIND_FILE_UNIX_INFO2:
1941 /* Always use filesystem for UNIX mtime query. */
1942 ask_sharemode = false;
1943 if (!lp_unix_extensions()) {
1944 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1945 return;
1947 break;
1948 default:
1949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1950 return;
1953 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1954 params+12, total_params - 12,
1955 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1956 if (!NT_STATUS_IS_OK(ntstatus)) {
1957 reply_nterror(req, ntstatus);
1958 return;
1961 ntstatus = resolve_dfspath_wcard(ctx, conn,
1962 req->flags2 & FLAGS2_DFS_PATHNAMES,
1963 directory,
1964 &directory,
1965 &mask_contains_wcard);
1966 if (!NT_STATUS_IS_OK(ntstatus)) {
1967 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1968 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1969 ERRSRV, ERRbadpath);
1970 return;
1972 reply_nterror(req, ntstatus);
1973 return;
1976 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1977 if (!NT_STATUS_IS_OK(ntstatus)) {
1978 reply_nterror(req, ntstatus);
1979 return;
1982 ntstatus = check_name(conn, directory);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1985 return;
1988 p = strrchr_m(directory,'/');
1989 if(p == NULL) {
1990 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1991 if((directory[0] == '.') && (directory[1] == '\0')) {
1992 mask = talloc_strdup(ctx,"*");
1993 if (!mask) {
1994 reply_nterror(req, NT_STATUS_NO_MEMORY);
1995 return;
1997 mask_contains_wcard = True;
1999 directory = talloc_strdup(talloc_tos(), "./");
2000 if (!directory) {
2001 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 return;
2004 } else {
2005 *p = 0;
2008 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2010 if (info_level == SMB_FIND_EA_LIST) {
2011 uint32 ea_size;
2013 if (total_data < 4) {
2014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2015 return;
2018 ea_size = IVAL(pdata,0);
2019 if (ea_size != total_data) {
2020 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2021 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2023 return;
2026 if (!lp_ea_support(SNUM(conn))) {
2027 reply_doserror(req, ERRDOS, ERReasnotsupported);
2028 return;
2031 /* Pull out the list of names. */
2032 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2033 if (!ea_list) {
2034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2035 return;
2039 *ppdata = (char *)SMB_REALLOC(
2040 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2041 if(*ppdata == NULL ) {
2042 reply_nterror(req, NT_STATUS_NO_MEMORY);
2043 return;
2045 pdata = *ppdata;
2046 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2048 /* Realloc the params space */
2049 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2050 if (*pparams == NULL) {
2051 reply_nterror(req, NT_STATUS_NO_MEMORY);
2052 return;
2054 params = *pparams;
2056 /* Save the wildcard match and attribs we are using on this directory -
2057 needed as lanman2 assumes these are being saved between calls */
2059 ntstatus = dptr_create(conn,
2060 directory,
2061 False,
2062 True,
2063 req->smbpid,
2064 mask,
2065 mask_contains_wcard,
2066 dirtype,
2067 &conn->dirptr);
2069 if (!NT_STATUS_IS_OK(ntstatus)) {
2070 reply_nterror(req, ntstatus);
2071 return;
2074 dptr_num = dptr_dnum(conn->dirptr);
2075 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2077 /* We don't need to check for VOL here as this is returned by
2078 a different TRANS2 call. */
2080 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2081 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2082 dont_descend = True;
2084 p = pdata;
2085 space_remaining = max_data_bytes;
2086 out_of_space = False;
2088 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2089 bool got_exact_match = False;
2091 /* this is a heuristic to avoid seeking the dirptr except when
2092 absolutely necessary. It allows for a filename of about 40 chars */
2093 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2094 out_of_space = True;
2095 finished = False;
2096 } else {
2097 finished = !get_lanman2_dir_entry(ctx,
2098 conn,
2099 req->flags2,
2100 mask,dirtype,info_level,
2101 requires_resume_key,dont_descend,
2102 ask_sharemode,
2103 &p,pdata,data_end,
2104 space_remaining, &out_of_space,
2105 &got_exact_match,
2106 &last_entry_off, ea_list);
2109 if (finished && out_of_space)
2110 finished = False;
2112 if (!finished && !out_of_space)
2113 numentries++;
2116 * As an optimisation if we know we aren't looking
2117 * for a wildcard name (ie. the name matches the wildcard exactly)
2118 * then we can finish on any (first) match.
2119 * This speeds up large directory searches. JRA.
2122 if(got_exact_match)
2123 finished = True;
2125 /* Ensure space_remaining never goes -ve. */
2126 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2127 space_remaining = 0;
2128 out_of_space = true;
2129 } else {
2130 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2134 /* Check if we can close the dirptr */
2135 if(close_after_first || (finished && close_if_end)) {
2136 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2137 dptr_close(&dptr_num);
2141 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2142 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2143 * the protocol level is less than NT1. Tested with smbclient. JRA.
2144 * This should fix the OS/2 client bug #2335.
2147 if(numentries == 0) {
2148 dptr_close(&dptr_num);
2149 if (Protocol < PROTOCOL_NT1) {
2150 reply_doserror(req, ERRDOS, ERRnofiles);
2151 return;
2152 } else {
2153 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2154 ERRDOS, ERRbadfile);
2155 return;
2159 /* At this point pdata points to numentries directory entries. */
2161 /* Set up the return parameter block */
2162 SSVAL(params,0,dptr_num);
2163 SSVAL(params,2,numentries);
2164 SSVAL(params,4,finished);
2165 SSVAL(params,6,0); /* Never an EA error */
2166 SSVAL(params,8,last_entry_off);
2168 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2169 max_data_bytes);
2171 if ((! *directory) && dptr_path(dptr_num)) {
2172 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2173 if (!directory) {
2174 reply_nterror(req, NT_STATUS_NO_MEMORY);
2178 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2179 smb_fn_name(CVAL(req->inbuf,smb_com)),
2180 mask, directory, dirtype, numentries ) );
2183 * Force a name mangle here to ensure that the
2184 * mask as an 8.3 name is top of the mangled cache.
2185 * The reasons for this are subtle. Don't remove
2186 * this code unless you know what you are doing
2187 * (see PR#13758). JRA.
2190 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2191 char mangled_name[13];
2192 name_to_8_3(mask, mangled_name, True, conn->params);
2195 return;
2198 /****************************************************************************
2199 Reply to a TRANS2_FINDNEXT.
2200 ****************************************************************************/
2202 static void call_trans2findnext(connection_struct *conn,
2203 struct smb_request *req,
2204 char **pparams, int total_params,
2205 char **ppdata, int total_data,
2206 unsigned int max_data_bytes)
2208 /* We must be careful here that we don't return more than the
2209 allowed number of data bytes. If this means returning fewer than
2210 maxentries then so be it. We assume that the redirector has
2211 enough room for the fixed number of parameter bytes it has
2212 requested. */
2213 char *params = *pparams;
2214 char *pdata = *ppdata;
2215 char *data_end;
2216 int dptr_num;
2217 int maxentries;
2218 uint16 info_level;
2219 uint32 resume_key;
2220 uint16 findnext_flags;
2221 bool close_after_request;
2222 bool close_if_end;
2223 bool requires_resume_key;
2224 bool continue_bit;
2225 bool mask_contains_wcard = False;
2226 char *resume_name = NULL;
2227 const char *mask = NULL;
2228 const char *directory = NULL;
2229 char *p = NULL;
2230 uint16 dirtype;
2231 int numentries = 0;
2232 int i, last_entry_off=0;
2233 bool finished = False;
2234 bool dont_descend = False;
2235 bool out_of_space = False;
2236 int space_remaining;
2237 struct ea_list *ea_list = NULL;
2238 NTSTATUS ntstatus = NT_STATUS_OK;
2239 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2240 TALLOC_CTX *ctx = talloc_tos();
2242 if (total_params < 13) {
2243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2244 return;
2247 dptr_num = SVAL(params,0);
2248 maxentries = SVAL(params,2);
2249 info_level = SVAL(params,4);
2250 resume_key = IVAL(params,6);
2251 findnext_flags = SVAL(params,10);
2252 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2253 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2254 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2255 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2257 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2258 params+12,
2259 total_params - 12, STR_TERMINATE, &ntstatus,
2260 &mask_contains_wcard);
2261 if (!NT_STATUS_IS_OK(ntstatus)) {
2262 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2263 complain (it thinks we're asking for the directory above the shared
2264 path or an invalid name). Catch this as the resume name is only compared, never used in
2265 a file access. JRA. */
2266 srvstr_pull_talloc(ctx, params, req->flags2,
2267 &resume_name, params+12,
2268 total_params - 12,
2269 STR_TERMINATE);
2271 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2272 reply_nterror(req, ntstatus);
2273 return;
2277 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2278 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2279 resume_key = %d resume name = %s continue=%d level = %d\n",
2280 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2281 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2283 if (!maxentries) {
2284 /* W2K3 seems to treat zero as 1. */
2285 maxentries = 1;
2288 switch (info_level) {
2289 case SMB_FIND_INFO_STANDARD:
2290 case SMB_FIND_EA_SIZE:
2291 case SMB_FIND_EA_LIST:
2292 case SMB_FIND_FILE_DIRECTORY_INFO:
2293 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2294 case SMB_FIND_FILE_NAMES_INFO:
2295 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2296 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2297 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2298 break;
2299 case SMB_FIND_FILE_UNIX:
2300 case SMB_FIND_FILE_UNIX_INFO2:
2301 /* Always use filesystem for UNIX mtime query. */
2302 ask_sharemode = false;
2303 if (!lp_unix_extensions()) {
2304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2305 return;
2307 break;
2308 default:
2309 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2310 return;
2313 if (info_level == SMB_FIND_EA_LIST) {
2314 uint32 ea_size;
2316 if (total_data < 4) {
2317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2318 return;
2321 ea_size = IVAL(pdata,0);
2322 if (ea_size != total_data) {
2323 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2324 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2326 return;
2329 if (!lp_ea_support(SNUM(conn))) {
2330 reply_doserror(req, ERRDOS, ERReasnotsupported);
2331 return;
2334 /* Pull out the list of names. */
2335 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2336 if (!ea_list) {
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 return;
2342 *ppdata = (char *)SMB_REALLOC(
2343 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2344 if(*ppdata == NULL) {
2345 reply_nterror(req, NT_STATUS_NO_MEMORY);
2346 return;
2349 pdata = *ppdata;
2350 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2352 /* Realloc the params space */
2353 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2354 if(*pparams == NULL ) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 return;
2359 params = *pparams;
2361 /* Check that the dptr is valid */
2362 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2363 reply_doserror(req, ERRDOS, ERRnofiles);
2364 return;
2367 string_set(&conn->dirpath,dptr_path(dptr_num));
2369 /* Get the wildcard mask from the dptr */
2370 if((p = dptr_wcard(dptr_num))== NULL) {
2371 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2373 return;
2376 mask = p;
2377 directory = conn->dirpath;
2379 /* Get the attr mask from the dptr */
2380 dirtype = dptr_attr(dptr_num);
2382 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2383 dptr_num, mask, dirtype,
2384 (long)conn->dirptr,
2385 dptr_TellDir(conn->dirptr)));
2387 /* We don't need to check for VOL here as this is returned by
2388 a different TRANS2 call. */
2390 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2391 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2392 dont_descend = True;
2394 p = pdata;
2395 space_remaining = max_data_bytes;
2396 out_of_space = False;
2399 * Seek to the correct position. We no longer use the resume key but
2400 * depend on the last file name instead.
2403 if(*resume_name && !continue_bit) {
2404 SMB_STRUCT_STAT st;
2406 long current_pos = 0;
2408 * Remember, name_to_8_3 is called by
2409 * get_lanman2_dir_entry(), so the resume name
2410 * could be mangled. Ensure we check the unmangled name.
2413 if (mangle_is_mangled(resume_name, conn->params)) {
2414 char *new_resume_name = NULL;
2415 mangle_lookup_name_from_8_3(ctx,
2416 resume_name,
2417 &new_resume_name,
2418 conn->params);
2419 if (new_resume_name) {
2420 resume_name = new_resume_name;
2425 * Fix for NT redirector problem triggered by resume key indexes
2426 * changing between directory scans. We now return a resume key of 0
2427 * and instead look for the filename to continue from (also given
2428 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2429 * findfirst/findnext (as is usual) then the directory pointer
2430 * should already be at the correct place.
2433 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2434 } /* end if resume_name && !continue_bit */
2436 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2437 bool got_exact_match = False;
2439 /* this is a heuristic to avoid seeking the dirptr except when
2440 absolutely necessary. It allows for a filename of about 40 chars */
2441 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2442 out_of_space = True;
2443 finished = False;
2444 } else {
2445 finished = !get_lanman2_dir_entry(ctx,
2446 conn,
2447 req->flags2,
2448 mask,dirtype,info_level,
2449 requires_resume_key,dont_descend,
2450 ask_sharemode,
2451 &p,pdata,data_end,
2452 space_remaining, &out_of_space,
2453 &got_exact_match,
2454 &last_entry_off, ea_list);
2457 if (finished && out_of_space)
2458 finished = False;
2460 if (!finished && !out_of_space)
2461 numentries++;
2464 * As an optimisation if we know we aren't looking
2465 * for a wildcard name (ie. the name matches the wildcard exactly)
2466 * then we can finish on any (first) match.
2467 * This speeds up large directory searches. JRA.
2470 if(got_exact_match)
2471 finished = True;
2473 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2476 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2477 smb_fn_name(CVAL(req->inbuf,smb_com)),
2478 mask, directory, dirtype, numentries ) );
2480 /* Check if we can close the dirptr */
2481 if(close_after_request || (finished && close_if_end)) {
2482 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2483 dptr_close(&dptr_num); /* This frees up the saved mask */
2486 /* Set up the return parameter block */
2487 SSVAL(params,0,numentries);
2488 SSVAL(params,2,finished);
2489 SSVAL(params,4,0); /* Never an EA error */
2490 SSVAL(params,6,last_entry_off);
2492 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2493 max_data_bytes);
2495 return;
2498 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2500 E_md4hash(lp_servicename(SNUM(conn)),objid);
2501 return objid;
2504 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2506 SMB_ASSERT(extended_info != NULL);
2508 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2509 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2510 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2511 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2512 #ifdef SAMBA_VERSION_REVISION
2513 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2514 #endif
2515 extended_info->samba_subversion = 0;
2516 #ifdef SAMBA_VERSION_RC_RELEASE
2517 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2518 #else
2519 #ifdef SAMBA_VERSION_PRE_RELEASE
2520 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2521 #endif
2522 #endif
2523 #ifdef SAMBA_VERSION_VENDOR_PATCH
2524 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2525 #endif
2526 extended_info->samba_gitcommitdate = 0;
2527 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2528 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2529 #endif
2531 memset(extended_info->samba_version_string, 0,
2532 sizeof(extended_info->samba_version_string));
2534 snprintf (extended_info->samba_version_string,
2535 sizeof(extended_info->samba_version_string),
2536 "%s", samba_version_string());
2539 /****************************************************************************
2540 Reply to a TRANS2_QFSINFO (query filesystem info).
2541 ****************************************************************************/
2543 static void call_trans2qfsinfo(connection_struct *conn,
2544 struct smb_request *req,
2545 char **pparams, int total_params,
2546 char **ppdata, int total_data,
2547 unsigned int max_data_bytes)
2549 char *pdata, *end_data;
2550 char *params = *pparams;
2551 uint16 info_level;
2552 int data_len, len;
2553 SMB_STRUCT_STAT st;
2554 const char *vname = volume_label(SNUM(conn));
2555 int snum = SNUM(conn);
2556 char *fstype = lp_fstype(SNUM(conn));
2557 uint32 additional_flags = 0;
2559 if (total_params < 2) {
2560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2561 return;
2564 info_level = SVAL(params,0);
2566 if (IS_IPC(conn)) {
2567 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2568 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2569 "info level (0x%x) on IPC$.\n",
2570 (unsigned int)info_level));
2571 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2572 return;
2576 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2577 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2578 DEBUG(0,("call_trans2qfsinfo: encryption required "
2579 "and info level 0x%x sent.\n",
2580 (unsigned int)info_level));
2581 exit_server_cleanly("encryption required "
2582 "on connection");
2583 return;
2587 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2589 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2590 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2591 reply_doserror(req, ERRSRV, ERRinvdevice);
2592 return;
2595 *ppdata = (char *)SMB_REALLOC(
2596 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2597 if (*ppdata == NULL ) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2599 return;
2602 pdata = *ppdata;
2603 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2604 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2606 switch (info_level) {
2607 case SMB_INFO_ALLOCATION:
2609 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2610 data_len = 18;
2611 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2612 reply_unixerror(req, ERRHRD, ERRgeneral);
2613 return;
2616 block_size = lp_block_size(snum);
2617 if (bsize < block_size) {
2618 SMB_BIG_UINT factor = block_size/bsize;
2619 bsize = block_size;
2620 dsize /= factor;
2621 dfree /= factor;
2623 if (bsize > block_size) {
2624 SMB_BIG_UINT factor = bsize/block_size;
2625 bsize = block_size;
2626 dsize *= factor;
2627 dfree *= factor;
2629 bytes_per_sector = 512;
2630 sectors_per_unit = bsize/bytes_per_sector;
2632 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2633 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2634 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2636 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2637 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2638 SIVAL(pdata,l1_cUnit,dsize);
2639 SIVAL(pdata,l1_cUnitAvail,dfree);
2640 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2641 break;
2644 case SMB_INFO_VOLUME:
2645 /* Return volume name */
2647 * Add volume serial number - hash of a combination of
2648 * the called hostname and the service name.
2650 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2652 * Win2k3 and previous mess this up by sending a name length
2653 * one byte short. I believe only older clients (OS/2 Win9x) use
2654 * this call so try fixing this by adding a terminating null to
2655 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2657 len = srvstr_push(
2658 pdata, req->flags2,
2659 pdata+l2_vol_szVolLabel, vname,
2660 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2661 STR_NOALIGN|STR_TERMINATE);
2662 SCVAL(pdata,l2_vol_cch,len);
2663 data_len = l2_vol_szVolLabel + len;
2664 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2665 (unsigned)st.st_ctime, len, vname));
2666 break;
2668 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2669 case SMB_FS_ATTRIBUTE_INFORMATION:
2671 additional_flags = 0;
2672 #if defined(HAVE_SYS_QUOTAS)
2673 additional_flags |= FILE_VOLUME_QUOTAS;
2674 #endif
2676 if(lp_nt_acl_support(SNUM(conn))) {
2677 additional_flags |= FILE_PERSISTENT_ACLS;
2680 /* Capabilities are filled in at connection time through STATVFS call */
2681 additional_flags |= conn->fs_capabilities;
2683 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2684 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2685 additional_flags); /* FS ATTRIBUTES */
2687 SIVAL(pdata,4,255); /* Max filename component length */
2688 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2689 and will think we can't do long filenames */
2690 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2691 PTR_DIFF(end_data, pdata+12),
2692 STR_UNICODE);
2693 SIVAL(pdata,8,len);
2694 data_len = 12 + len;
2695 break;
2697 case SMB_QUERY_FS_LABEL_INFO:
2698 case SMB_FS_LABEL_INFORMATION:
2699 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2700 PTR_DIFF(end_data, pdata+4), 0);
2701 data_len = 4 + len;
2702 SIVAL(pdata,0,len);
2703 break;
2705 case SMB_QUERY_FS_VOLUME_INFO:
2706 case SMB_FS_VOLUME_INFORMATION:
2709 * Add volume serial number - hash of a combination of
2710 * the called hostname and the service name.
2712 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2713 (str_checksum(get_local_machine_name())<<16));
2715 /* Max label len is 32 characters. */
2716 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2717 PTR_DIFF(end_data, pdata+18),
2718 STR_UNICODE);
2719 SIVAL(pdata,12,len);
2720 data_len = 18+len;
2722 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2723 (int)strlen(vname),vname, lp_servicename(snum)));
2724 break;
2726 case SMB_QUERY_FS_SIZE_INFO:
2727 case SMB_FS_SIZE_INFORMATION:
2729 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2730 data_len = 24;
2731 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2732 reply_unixerror(req, ERRHRD, ERRgeneral);
2733 return;
2735 block_size = lp_block_size(snum);
2736 if (bsize < block_size) {
2737 SMB_BIG_UINT factor = block_size/bsize;
2738 bsize = block_size;
2739 dsize /= factor;
2740 dfree /= factor;
2742 if (bsize > block_size) {
2743 SMB_BIG_UINT factor = bsize/block_size;
2744 bsize = block_size;
2745 dsize *= factor;
2746 dfree *= factor;
2748 bytes_per_sector = 512;
2749 sectors_per_unit = bsize/bytes_per_sector;
2750 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2751 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2752 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2753 SBIG_UINT(pdata,0,dsize);
2754 SBIG_UINT(pdata,8,dfree);
2755 SIVAL(pdata,16,sectors_per_unit);
2756 SIVAL(pdata,20,bytes_per_sector);
2757 break;
2760 case SMB_FS_FULL_SIZE_INFORMATION:
2762 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2763 data_len = 32;
2764 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2765 reply_unixerror(req, ERRHRD, ERRgeneral);
2766 return;
2768 block_size = lp_block_size(snum);
2769 if (bsize < block_size) {
2770 SMB_BIG_UINT factor = block_size/bsize;
2771 bsize = block_size;
2772 dsize /= factor;
2773 dfree /= factor;
2775 if (bsize > block_size) {
2776 SMB_BIG_UINT factor = bsize/block_size;
2777 bsize = block_size;
2778 dsize *= factor;
2779 dfree *= factor;
2781 bytes_per_sector = 512;
2782 sectors_per_unit = bsize/bytes_per_sector;
2783 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2784 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2785 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2786 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2787 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2788 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2789 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2790 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2791 break;
2794 case SMB_QUERY_FS_DEVICE_INFO:
2795 case SMB_FS_DEVICE_INFORMATION:
2796 data_len = 8;
2797 SIVAL(pdata,0,0); /* dev type */
2798 SIVAL(pdata,4,0); /* characteristics */
2799 break;
2801 #ifdef HAVE_SYS_QUOTAS
2802 case SMB_FS_QUOTA_INFORMATION:
2804 * what we have to send --metze:
2806 * Unknown1: 24 NULL bytes
2807 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2808 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2809 * Quota Flags: 2 byte :
2810 * Unknown3: 6 NULL bytes
2812 * 48 bytes total
2814 * details for Quota Flags:
2816 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2817 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2818 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2819 * 0x0001 Enable Quotas: enable quota for this fs
2823 /* we need to fake up a fsp here,
2824 * because its not send in this call
2826 files_struct fsp;
2827 SMB_NTQUOTA_STRUCT quotas;
2829 ZERO_STRUCT(fsp);
2830 ZERO_STRUCT(quotas);
2832 fsp.conn = conn;
2833 fsp.fnum = -1;
2835 /* access check */
2836 if (current_user.ut.uid != 0) {
2837 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2838 lp_servicename(SNUM(conn)),conn->user));
2839 reply_doserror(req, ERRDOS, ERRnoaccess);
2840 return;
2843 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2844 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2845 reply_doserror(req, ERRSRV, ERRerror);
2846 return;
2849 data_len = 48;
2851 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2853 /* Unknown1 24 NULL bytes*/
2854 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2855 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2856 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2858 /* Default Soft Quota 8 bytes */
2859 SBIG_UINT(pdata,24,quotas.softlim);
2861 /* Default Hard Quota 8 bytes */
2862 SBIG_UINT(pdata,32,quotas.hardlim);
2864 /* Quota flag 2 bytes */
2865 SSVAL(pdata,40,quotas.qflags);
2867 /* Unknown3 6 NULL bytes */
2868 SSVAL(pdata,42,0);
2869 SIVAL(pdata,44,0);
2871 break;
2873 #endif /* HAVE_SYS_QUOTAS */
2874 case SMB_FS_OBJECTID_INFORMATION:
2876 unsigned char objid[16];
2877 struct smb_extended_info extended_info;
2878 memcpy(pdata,create_volume_objectid(conn, objid),16);
2879 samba_extended_info_version (&extended_info);
2880 SIVAL(pdata,16,extended_info.samba_magic);
2881 SIVAL(pdata,20,extended_info.samba_version);
2882 SIVAL(pdata,24,extended_info.samba_subversion);
2883 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2884 memcpy(pdata+36,extended_info.samba_version_string,28);
2885 data_len = 64;
2886 break;
2890 * Query the version and capabilities of the CIFS UNIX extensions
2891 * in use.
2894 case SMB_QUERY_CIFS_UNIX_INFO:
2896 bool large_write = lp_min_receive_file_size() &&
2897 !srv_is_signing_active();
2898 bool large_read = !srv_is_signing_active();
2899 int encrypt_caps = 0;
2901 if (!lp_unix_extensions()) {
2902 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2903 return;
2906 switch (conn->encrypt_level) {
2907 case 0:
2908 encrypt_caps = 0;
2909 break;
2910 case 1:
2911 case Auto:
2912 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2913 break;
2914 case Required:
2915 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2916 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2917 large_write = false;
2918 large_read = false;
2919 break;
2922 data_len = 12;
2923 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2924 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2926 /* We have POSIX ACLs, pathname, encryption,
2927 * large read/write, and locking capability. */
2929 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2930 CIFS_UNIX_POSIX_ACLS_CAP|
2931 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2932 CIFS_UNIX_FCNTL_LOCKS_CAP|
2933 CIFS_UNIX_EXTATTR_CAP|
2934 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2935 encrypt_caps|
2936 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2937 (large_write ?
2938 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2939 break;
2942 case SMB_QUERY_POSIX_FS_INFO:
2944 int rc;
2945 vfs_statvfs_struct svfs;
2947 if (!lp_unix_extensions()) {
2948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2949 return;
2952 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2954 if (!rc) {
2955 data_len = 56;
2956 SIVAL(pdata,0,svfs.OptimalTransferSize);
2957 SIVAL(pdata,4,svfs.BlockSize);
2958 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2959 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2960 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2961 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2962 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2963 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2964 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2965 #ifdef EOPNOTSUPP
2966 } else if (rc == EOPNOTSUPP) {
2967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2968 return;
2969 #endif /* EOPNOTSUPP */
2970 } else {
2971 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2972 reply_doserror(req, ERRSRV, ERRerror);
2973 return;
2975 break;
2978 case SMB_QUERY_POSIX_WHOAMI:
2980 uint32_t flags = 0;
2981 uint32_t sid_bytes;
2982 int i;
2984 if (!lp_unix_extensions()) {
2985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2986 return;
2989 if (max_data_bytes < 40) {
2990 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2991 return;
2994 /* We ARE guest if global_sid_Builtin_Guests is
2995 * in our list of SIDs.
2997 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2998 current_user.nt_user_token)) {
2999 flags |= SMB_WHOAMI_GUEST;
3002 /* We are NOT guest if global_sid_Authenticated_Users
3003 * is in our list of SIDs.
3005 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3006 current_user.nt_user_token)) {
3007 flags &= ~SMB_WHOAMI_GUEST;
3010 /* NOTE: 8 bytes for UID/GID, irrespective of native
3011 * platform size. This matches
3012 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3014 data_len = 4 /* flags */
3015 + 4 /* flag mask */
3016 + 8 /* uid */
3017 + 8 /* gid */
3018 + 4 /* ngroups */
3019 + 4 /* num_sids */
3020 + 4 /* SID bytes */
3021 + 4 /* pad/reserved */
3022 + (current_user.ut.ngroups * 8)
3023 /* groups list */
3024 + (current_user.nt_user_token->num_sids *
3025 SID_MAX_SIZE)
3026 /* SID list */;
3028 SIVAL(pdata, 0, flags);
3029 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3030 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3031 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3034 if (data_len >= max_data_bytes) {
3035 /* Potential overflow, skip the GIDs and SIDs. */
3037 SIVAL(pdata, 24, 0); /* num_groups */
3038 SIVAL(pdata, 28, 0); /* num_sids */
3039 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3040 SIVAL(pdata, 36, 0); /* reserved */
3042 data_len = 40;
3043 break;
3046 SIVAL(pdata, 24, current_user.ut.ngroups);
3047 SIVAL(pdata, 28,
3048 current_user.nt_user_token->num_sids);
3050 /* We walk the SID list twice, but this call is fairly
3051 * infrequent, and I don't expect that it's performance
3052 * sensitive -- jpeach
3054 for (i = 0, sid_bytes = 0;
3055 i < current_user.nt_user_token->num_sids; ++i) {
3056 sid_bytes += ndr_size_dom_sid(
3057 &current_user.nt_user_token->user_sids[i], 0);
3060 /* SID list byte count */
3061 SIVAL(pdata, 32, sid_bytes);
3063 /* 4 bytes pad/reserved - must be zero */
3064 SIVAL(pdata, 36, 0);
3065 data_len = 40;
3067 /* GID list */
3068 for (i = 0; i < current_user.ut.ngroups; ++i) {
3069 SBIG_UINT(pdata, data_len,
3070 (SMB_BIG_UINT)current_user.ut.groups[i]);
3071 data_len += 8;
3074 /* SID list */
3075 for (i = 0;
3076 i < current_user.nt_user_token->num_sids; ++i) {
3077 int sid_len = ndr_size_dom_sid(
3078 &current_user.nt_user_token->user_sids[i], 0);
3080 sid_linearize(pdata + data_len, sid_len,
3081 &current_user.nt_user_token->user_sids[i]);
3082 data_len += sid_len;
3085 break;
3088 case SMB_MAC_QUERY_FS_INFO:
3090 * Thursby MAC extension... ONLY on NTFS filesystems
3091 * once we do streams then we don't need this
3093 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3094 data_len = 88;
3095 SIVAL(pdata,84,0x100); /* Don't support mac... */
3096 break;
3098 /* drop through */
3099 default:
3100 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3101 return;
3105 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3106 max_data_bytes);
3108 DEBUG( 4, ( "%s info_level = %d\n",
3109 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3111 return;
3114 /****************************************************************************
3115 Reply to a TRANS2_SETFSINFO (set filesystem info).
3116 ****************************************************************************/
3118 static void call_trans2setfsinfo(connection_struct *conn,
3119 struct smb_request *req,
3120 char **pparams, int total_params,
3121 char **ppdata, int total_data,
3122 unsigned int max_data_bytes)
3124 char *pdata = *ppdata;
3125 char *params = *pparams;
3126 uint16 info_level;
3128 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3130 /* */
3131 if (total_params < 4) {
3132 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3133 total_params));
3134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3135 return;
3138 info_level = SVAL(params,2);
3140 if (IS_IPC(conn)) {
3141 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3142 info_level != SMB_SET_CIFS_UNIX_INFO) {
3143 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3144 "info level (0x%x) on IPC$.\n",
3145 (unsigned int)info_level));
3146 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3147 return;
3151 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3152 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3153 DEBUG(0,("call_trans2setfsinfo: encryption required "
3154 "and info level 0x%x sent.\n",
3155 (unsigned int)info_level));
3156 exit_server_cleanly("encryption required "
3157 "on connection");
3158 return;
3162 switch(info_level) {
3163 case SMB_SET_CIFS_UNIX_INFO:
3165 uint16 client_unix_major;
3166 uint16 client_unix_minor;
3167 uint32 client_unix_cap_low;
3168 uint32 client_unix_cap_high;
3170 if (!lp_unix_extensions()) {
3171 reply_nterror(req,
3172 NT_STATUS_INVALID_LEVEL);
3173 return;
3176 /* There should be 12 bytes of capabilities set. */
3177 if (total_data < 8) {
3178 reply_nterror(
3179 req,
3180 NT_STATUS_INVALID_PARAMETER);
3181 return;
3183 client_unix_major = SVAL(pdata,0);
3184 client_unix_minor = SVAL(pdata,2);
3185 client_unix_cap_low = IVAL(pdata,4);
3186 client_unix_cap_high = IVAL(pdata,8);
3187 /* Just print these values for now. */
3188 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3189 cap_low = 0x%x, cap_high = 0x%x\n",
3190 (unsigned int)client_unix_major,
3191 (unsigned int)client_unix_minor,
3192 (unsigned int)client_unix_cap_low,
3193 (unsigned int)client_unix_cap_high ));
3195 /* Here is where we must switch to posix pathname processing... */
3196 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3197 lp_set_posix_pathnames();
3198 mangle_change_to_posix();
3201 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3202 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3203 /* Client that knows how to do posix locks,
3204 * but not posix open/mkdir operations. Set a
3205 * default type for read/write checks. */
3207 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3210 break;
3213 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3215 NTSTATUS status;
3216 size_t param_len = 0;
3217 size_t data_len = total_data;
3219 if (!lp_unix_extensions()) {
3220 reply_nterror(
3221 req,
3222 NT_STATUS_INVALID_LEVEL);
3223 return;
3226 if (lp_smb_encrypt(SNUM(conn)) == false) {
3227 reply_nterror(
3228 req,
3229 NT_STATUS_NOT_SUPPORTED);
3230 return;
3233 DEBUG( 4,("call_trans2setfsinfo: "
3234 "request transport encryption.\n"));
3236 status = srv_request_encryption_setup(conn,
3237 (unsigned char **)ppdata,
3238 &data_len,
3239 (unsigned char **)pparams,
3240 &param_len);
3242 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3243 !NT_STATUS_IS_OK(status)) {
3244 reply_nterror(req, status);
3245 return;
3248 send_trans2_replies(conn, req,
3249 *pparams,
3250 param_len,
3251 *ppdata,
3252 data_len,
3253 max_data_bytes);
3255 if (NT_STATUS_IS_OK(status)) {
3256 /* Server-side transport
3257 * encryption is now *on*. */
3258 status = srv_encryption_start(conn);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 exit_server_cleanly(
3261 "Failure in setting "
3262 "up encrypted transport");
3265 return;
3268 case SMB_FS_QUOTA_INFORMATION:
3270 files_struct *fsp = NULL;
3271 SMB_NTQUOTA_STRUCT quotas;
3273 ZERO_STRUCT(quotas);
3275 /* access check */
3276 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3277 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3278 lp_servicename(SNUM(conn)),conn->user));
3279 reply_doserror(req, ERRSRV, ERRaccess);
3280 return;
3283 /* note: normaly there're 48 bytes,
3284 * but we didn't use the last 6 bytes for now
3285 * --metze
3287 fsp = file_fsp(SVAL(params,0));
3288 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3289 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3290 reply_nterror(
3291 req, NT_STATUS_INVALID_HANDLE);
3292 return;
3295 if (total_data < 42) {
3296 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3297 total_data));
3298 reply_nterror(
3299 req,
3300 NT_STATUS_INVALID_PARAMETER);
3301 return;
3304 /* unknown_1 24 NULL bytes in pdata*/
3306 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3307 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3308 #ifdef LARGE_SMB_OFF_T
3309 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3310 #else /* LARGE_SMB_OFF_T */
3311 if ((IVAL(pdata,28) != 0)&&
3312 ((quotas.softlim != 0xFFFFFFFF)||
3313 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3314 /* more than 32 bits? */
3315 reply_nterror(
3316 req,
3317 NT_STATUS_INVALID_PARAMETER);
3318 return;
3320 #endif /* LARGE_SMB_OFF_T */
3322 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3323 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3324 #ifdef LARGE_SMB_OFF_T
3325 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3326 #else /* LARGE_SMB_OFF_T */
3327 if ((IVAL(pdata,36) != 0)&&
3328 ((quotas.hardlim != 0xFFFFFFFF)||
3329 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3330 /* more than 32 bits? */
3331 reply_nterror(
3332 req,
3333 NT_STATUS_INVALID_PARAMETER);
3334 return;
3336 #endif /* LARGE_SMB_OFF_T */
3338 /* quota_flags 2 bytes **/
3339 quotas.qflags = SVAL(pdata,40);
3341 /* unknown_2 6 NULL bytes follow*/
3343 /* now set the quotas */
3344 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3345 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3346 reply_doserror(req, ERRSRV, ERRerror);
3347 return;
3350 break;
3352 default:
3353 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3354 info_level));
3355 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3356 return;
3357 break;
3361 * sending this reply works fine,
3362 * but I'm not sure it's the same
3363 * like windows do...
3364 * --metze
3366 reply_outbuf(req, 10, 0);
3369 #if defined(HAVE_POSIX_ACLS)
3370 /****************************************************************************
3371 Utility function to count the number of entries in a POSIX acl.
3372 ****************************************************************************/
3374 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3376 unsigned int ace_count = 0;
3377 int entry_id = SMB_ACL_FIRST_ENTRY;
3378 SMB_ACL_ENTRY_T entry;
3380 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3381 /* get_next... */
3382 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3383 entry_id = SMB_ACL_NEXT_ENTRY;
3385 ace_count++;
3387 return ace_count;
3390 /****************************************************************************
3391 Utility function to marshall a POSIX acl into wire format.
3392 ****************************************************************************/
3394 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3396 int entry_id = SMB_ACL_FIRST_ENTRY;
3397 SMB_ACL_ENTRY_T entry;
3399 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3400 SMB_ACL_TAG_T tagtype;
3401 SMB_ACL_PERMSET_T permset;
3402 unsigned char perms = 0;
3403 unsigned int own_grp;
3405 /* get_next... */
3406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3407 entry_id = SMB_ACL_NEXT_ENTRY;
3410 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3412 return False;
3415 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3416 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3417 return False;
3420 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3421 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3422 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3424 SCVAL(pdata,1,perms);
3426 switch (tagtype) {
3427 case SMB_ACL_USER_OBJ:
3428 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3429 own_grp = (unsigned int)pst->st_uid;
3430 SIVAL(pdata,2,own_grp);
3431 SIVAL(pdata,6,0);
3432 break;
3433 case SMB_ACL_USER:
3435 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3436 if (!puid) {
3437 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3438 return False;
3440 own_grp = (unsigned int)*puid;
3441 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3442 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3443 SIVAL(pdata,2,own_grp);
3444 SIVAL(pdata,6,0);
3445 break;
3447 case SMB_ACL_GROUP_OBJ:
3448 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3449 own_grp = (unsigned int)pst->st_gid;
3450 SIVAL(pdata,2,own_grp);
3451 SIVAL(pdata,6,0);
3452 break;
3453 case SMB_ACL_GROUP:
3455 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3456 if (!pgid) {
3457 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3458 return False;
3460 own_grp = (unsigned int)*pgid;
3461 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3462 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3463 SIVAL(pdata,2,own_grp);
3464 SIVAL(pdata,6,0);
3465 break;
3467 case SMB_ACL_MASK:
3468 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3469 SIVAL(pdata,2,0xFFFFFFFF);
3470 SIVAL(pdata,6,0xFFFFFFFF);
3471 break;
3472 case SMB_ACL_OTHER:
3473 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3474 SIVAL(pdata,2,0xFFFFFFFF);
3475 SIVAL(pdata,6,0xFFFFFFFF);
3476 break;
3477 default:
3478 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3479 return False;
3481 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3484 return True;
3486 #endif
3488 /****************************************************************************
3489 Store the FILE_UNIX_BASIC info.
3490 ****************************************************************************/
3492 static char *store_file_unix_basic(connection_struct *conn,
3493 char *pdata,
3494 files_struct *fsp,
3495 const SMB_STRUCT_STAT *psbuf)
3497 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3498 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3500 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3501 pdata += 8;
3503 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3504 pdata += 8;
3506 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3507 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3508 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3509 pdata += 24;
3511 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3512 SIVAL(pdata,4,0);
3513 pdata += 8;
3515 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3516 SIVAL(pdata,4,0);
3517 pdata += 8;
3519 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3520 pdata += 4;
3522 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3523 SIVAL(pdata,4,0);
3524 pdata += 8;
3526 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3527 SIVAL(pdata,4,0);
3528 pdata += 8;
3530 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3531 pdata += 8;
3533 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3534 SIVAL(pdata,4,0);
3535 pdata += 8;
3537 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3538 SIVAL(pdata,4,0);
3539 pdata += 8;
3541 return pdata;
3544 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3545 * the chflags(2) (or equivalent) flags.
3547 * XXX: this really should be behind the VFS interface. To do this, we would
3548 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3549 * Each VFS module could then implement its own mapping as appropriate for the
3550 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3552 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3553 info2_flags_map[] =
3555 #ifdef UF_NODUMP
3556 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3557 #endif
3559 #ifdef UF_IMMUTABLE
3560 { UF_IMMUTABLE, EXT_IMMUTABLE },
3561 #endif
3563 #ifdef UF_APPEND
3564 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3565 #endif
3567 #ifdef UF_HIDDEN
3568 { UF_HIDDEN, EXT_HIDDEN },
3569 #endif
3571 /* Do not remove. We need to guarantee that this array has at least one
3572 * entry to build on HP-UX.
3574 { 0, 0 }
3578 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3579 uint32 *smb_fflags, uint32 *smb_fmask)
3581 #ifdef HAVE_STAT_ST_FLAGS
3582 int i;
3584 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3585 *smb_fmask |= info2_flags_map[i].smb_fflag;
3586 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3587 *smb_fflags |= info2_flags_map[i].smb_fflag;
3590 #endif /* HAVE_STAT_ST_FLAGS */
3593 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3594 const uint32 smb_fflags,
3595 const uint32 smb_fmask,
3596 int *stat_fflags)
3598 #ifdef HAVE_STAT_ST_FLAGS
3599 uint32 max_fmask = 0;
3600 int i;
3602 *stat_fflags = psbuf->st_flags;
3604 /* For each flags requested in smb_fmask, check the state of the
3605 * corresponding flag in smb_fflags and set or clear the matching
3606 * stat flag.
3609 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3610 max_fmask |= info2_flags_map[i].smb_fflag;
3611 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3612 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3613 *stat_fflags |= info2_flags_map[i].stat_fflag;
3614 } else {
3615 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3620 /* If smb_fmask is asking to set any bits that are not supported by
3621 * our flag mappings, we should fail.
3623 if ((smb_fmask & max_fmask) != smb_fmask) {
3624 return False;
3627 return True;
3628 #else
3629 return False;
3630 #endif /* HAVE_STAT_ST_FLAGS */
3634 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3635 * of file flags and birth (create) time.
3637 static char *store_file_unix_basic_info2(connection_struct *conn,
3638 char *pdata,
3639 files_struct *fsp,
3640 const SMB_STRUCT_STAT *psbuf)
3642 uint32 file_flags = 0;
3643 uint32 flags_mask = 0;
3645 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3647 /* Create (birth) time 64 bit */
3648 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3649 pdata += 8;
3651 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3652 SIVAL(pdata, 0, file_flags); /* flags */
3653 SIVAL(pdata, 4, flags_mask); /* mask */
3654 pdata += 8;
3656 return pdata;
3659 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3660 const struct stream_struct *streams,
3661 char *data,
3662 unsigned int max_data_bytes,
3663 unsigned int *data_size)
3665 unsigned int i;
3666 unsigned int ofs = 0;
3668 for (i=0; i<num_streams; i++) {
3669 unsigned int next_offset;
3670 size_t namelen;
3671 smb_ucs2_t *namebuf;
3673 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3674 streams[i].name);
3676 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3677 return NT_STATUS_INVALID_PARAMETER;
3681 * name_buf is now null-terminated, we need to marshall as not
3682 * terminated
3685 namelen -= 2;
3687 if (ofs + 24 + namelen > max_data_bytes) {
3688 TALLOC_FREE(namebuf);
3689 return NT_STATUS_BUFFER_TOO_SMALL;
3692 SIVAL(data, ofs+4, namelen);
3693 SOFF_T(data, ofs+8, streams[i].size);
3694 SOFF_T(data, ofs+16, streams[i].alloc_size);
3695 memcpy(data+ofs+24, namebuf, namelen);
3696 TALLOC_FREE(namebuf);
3698 next_offset = ofs + 24 + namelen;
3700 if (i == num_streams-1) {
3701 SIVAL(data, ofs, 0);
3703 else {
3704 unsigned int align = ndr_align_size(next_offset, 8);
3706 if (next_offset + align > max_data_bytes) {
3707 return NT_STATUS_BUFFER_TOO_SMALL;
3710 memset(data+next_offset, 0, align);
3711 next_offset += align;
3713 SIVAL(data, ofs, next_offset - ofs);
3714 ofs = next_offset;
3717 ofs = next_offset;
3720 *data_size = ofs;
3722 return NT_STATUS_OK;
3725 /****************************************************************************
3726 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3727 ****************************************************************************/
3729 static void call_trans2qpipeinfo(connection_struct *conn,
3730 struct smb_request *req,
3731 unsigned int tran_call,
3732 char **pparams, int total_params,
3733 char **ppdata, int total_data,
3734 unsigned int max_data_bytes)
3736 char *params = *pparams;
3737 char *pdata = *ppdata;
3738 unsigned int data_size = 0;
3739 unsigned int param_size = 2;
3740 uint16 info_level;
3741 smb_np_struct *p_pipe = NULL;
3743 if (!params) {
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 return;
3748 if (total_params < 4) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750 return;
3753 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3754 if (p_pipe == NULL) {
3755 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3756 return;
3759 info_level = SVAL(params,2);
3761 *pparams = (char *)SMB_REALLOC(*pparams,2);
3762 if (*pparams == NULL) {
3763 reply_nterror(req, NT_STATUS_NO_MEMORY);
3764 return;
3766 params = *pparams;
3767 SSVAL(params,0,0);
3768 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3769 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3770 if (*ppdata == NULL ) {
3771 reply_nterror(req, NT_STATUS_NO_MEMORY);
3772 return;
3774 pdata = *ppdata;
3776 switch (info_level) {
3777 case SMB_FILE_STANDARD_INFORMATION:
3778 memset(pdata,0,24);
3779 SOFF_T(pdata,0,4096LL);
3780 SIVAL(pdata,16,1);
3781 SIVAL(pdata,20,1);
3782 data_size = 24;
3783 break;
3785 default:
3786 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3787 return;
3790 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3791 max_data_bytes);
3793 return;
3796 /****************************************************************************
3797 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3798 file name or file id).
3799 ****************************************************************************/
3801 static void call_trans2qfilepathinfo(connection_struct *conn,
3802 struct smb_request *req,
3803 unsigned int tran_call,
3804 char **pparams, int total_params,
3805 char **ppdata, int total_data,
3806 unsigned int max_data_bytes)
3808 char *params = *pparams;
3809 char *pdata = *ppdata;
3810 char *dstart, *dend;
3811 uint16 info_level;
3812 int mode=0;
3813 int nlink;
3814 SMB_OFF_T file_size=0;
3815 SMB_BIG_UINT allocation_size=0;
3816 unsigned int data_size = 0;
3817 unsigned int param_size = 2;
3818 SMB_STRUCT_STAT sbuf;
3819 char *dos_fname = NULL;
3820 char *fname = NULL;
3821 char *fullpathname;
3822 char *base_name;
3823 char *p;
3824 SMB_OFF_T pos = 0;
3825 bool delete_pending = False;
3826 int len;
3827 time_t create_time, mtime, atime;
3828 struct timespec create_time_ts, mtime_ts, atime_ts;
3829 struct timespec write_time_ts;
3830 files_struct *fsp = NULL;
3831 struct file_id fileid;
3832 struct ea_list *ea_list = NULL;
3833 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3834 char *lock_data = NULL;
3835 bool ms_dfs_link = false;
3836 TALLOC_CTX *ctx = talloc_tos();
3838 if (!params) {
3839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3840 return;
3843 ZERO_STRUCT(sbuf);
3844 ZERO_STRUCT(write_time_ts);
3846 if (tran_call == TRANSACT2_QFILEINFO) {
3847 if (total_params < 4) {
3848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3849 return;
3852 if (IS_IPC(conn)) {
3853 call_trans2qpipeinfo(conn, req, tran_call,
3854 pparams, total_params,
3855 ppdata, total_data,
3856 max_data_bytes);
3857 return;
3860 fsp = file_fsp(SVAL(params,0));
3861 info_level = SVAL(params,2);
3863 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3865 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3866 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3867 return;
3870 /* Initial check for valid fsp ptr. */
3871 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3872 return;
3875 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3876 if (!fname) {
3877 reply_nterror(req, NT_STATUS_NO_MEMORY);
3878 return;
3881 if(fsp->fake_file_handle) {
3883 * This is actually for the QUOTA_FAKE_FILE --metze
3886 /* We know this name is ok, it's already passed the checks. */
3888 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3890 * This is actually a QFILEINFO on a directory
3891 * handle (returned from an NT SMB). NT5.0 seems
3892 * to do this call. JRA.
3895 if (INFO_LEVEL_IS_UNIX(info_level)) {
3896 /* Always do lstat for UNIX calls. */
3897 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3898 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3899 reply_unixerror(req,ERRDOS,ERRbadpath);
3900 return;
3902 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3903 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3904 reply_unixerror(req, ERRDOS, ERRbadpath);
3905 return;
3908 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3909 get_file_infos(fileid, &delete_pending, &write_time_ts);
3910 } else {
3912 * Original code - this is an open file.
3914 if (!check_fsp(conn, req, fsp, &current_user)) {
3915 return;
3918 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3919 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3920 reply_unixerror(req, ERRDOS, ERRbadfid);
3921 return;
3923 pos = fsp->fh->position_information;
3924 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3925 get_file_infos(fileid, &delete_pending, &write_time_ts);
3926 access_mask = fsp->access_mask;
3929 } else {
3930 NTSTATUS status = NT_STATUS_OK;
3932 /* qpathinfo */
3933 if (total_params < 7) {
3934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3935 return;
3938 info_level = SVAL(params,0);
3940 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3942 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3943 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3944 return;
3947 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3948 total_params - 6,
3949 STR_TERMINATE, &status);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 reply_nterror(req, status);
3952 return;
3955 status = resolve_dfspath(ctx,
3956 conn,
3957 req->flags2 & FLAGS2_DFS_PATHNAMES,
3958 fname,
3959 &fname);
3960 if (!NT_STATUS_IS_OK(status)) {
3961 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3962 reply_botherror(req,
3963 NT_STATUS_PATH_NOT_COVERED,
3964 ERRSRV, ERRbadpath);
3966 reply_nterror(req, status);
3967 return;
3970 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 reply_nterror(req, status);
3973 return;
3975 status = check_name(conn, fname);
3976 if (!NT_STATUS_IS_OK(status)) {
3977 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3978 reply_nterror(req, status);
3979 return;
3982 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3983 && is_ntfs_stream_name(fname)) {
3984 char *base;
3985 SMB_STRUCT_STAT bsbuf;
3987 status = split_ntfs_stream_name(talloc_tos(), fname,
3988 &base, NULL);
3989 if (!NT_STATUS_IS_OK(status)) {
3990 DEBUG(10, ("create_file_unixpath: "
3991 "split_ntfs_stream_name failed: %s\n",
3992 nt_errstr(status)));
3993 reply_nterror(req, status);
3994 return;
3997 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3999 if (INFO_LEVEL_IS_UNIX(info_level)) {
4000 /* Always do lstat for UNIX calls. */
4001 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4002 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4003 reply_unixerror(req,ERRDOS,ERRbadpath);
4004 return;
4006 } else {
4007 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4008 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4009 reply_unixerror(req,ERRDOS,ERRbadpath);
4010 return;
4014 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4015 get_file_infos(fileid, &delete_pending, NULL);
4016 if (delete_pending) {
4017 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4018 return;
4022 if (INFO_LEVEL_IS_UNIX(info_level)) {
4023 /* Always do lstat for UNIX calls. */
4024 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4025 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4026 reply_unixerror(req, ERRDOS, ERRbadpath);
4027 return;
4030 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4031 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4033 if (!ms_dfs_link) {
4034 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4035 reply_unixerror(req, ERRDOS, ERRbadpath);
4036 return;
4040 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4041 get_file_infos(fileid, &delete_pending, &write_time_ts);
4042 if (delete_pending) {
4043 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4044 return;
4048 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4049 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4050 return;
4053 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4054 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4056 p = strrchr_m(fname,'/');
4057 if (!p)
4058 base_name = fname;
4059 else
4060 base_name = p+1;
4062 if (ms_dfs_link) {
4063 mode = dos_mode_msdfs(conn,fname,&sbuf);
4064 } else {
4065 mode = dos_mode(conn,fname,&sbuf);
4067 if (!mode)
4068 mode = FILE_ATTRIBUTE_NORMAL;
4070 nlink = sbuf.st_nlink;
4072 if (nlink && (mode&aDIR)) {
4073 nlink = 1;
4076 if ((nlink > 0) && delete_pending) {
4077 nlink -= 1;
4080 fullpathname = fname;
4081 if (!(mode & aDIR))
4082 file_size = get_file_size(sbuf);
4084 /* Pull out any data sent here before we realloc. */
4085 switch (info_level) {
4086 case SMB_INFO_QUERY_EAS_FROM_LIST:
4088 /* Pull any EA list from the data portion. */
4089 uint32 ea_size;
4091 if (total_data < 4) {
4092 reply_nterror(
4093 req, NT_STATUS_INVALID_PARAMETER);
4094 return;
4096 ea_size = IVAL(pdata,0);
4098 if (total_data > 0 && ea_size != total_data) {
4099 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4100 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4101 reply_nterror(
4102 req, NT_STATUS_INVALID_PARAMETER);
4103 return;
4106 if (!lp_ea_support(SNUM(conn))) {
4107 reply_doserror(req, ERRDOS,
4108 ERReasnotsupported);
4109 return;
4112 /* Pull out the list of names. */
4113 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4114 if (!ea_list) {
4115 reply_nterror(
4116 req, NT_STATUS_INVALID_PARAMETER);
4117 return;
4119 break;
4122 case SMB_QUERY_POSIX_LOCK:
4124 if (fsp == NULL || fsp->fh->fd == -1) {
4125 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4126 return;
4129 if (total_data != POSIX_LOCK_DATA_SIZE) {
4130 reply_nterror(
4131 req, NT_STATUS_INVALID_PARAMETER);
4132 return;
4135 /* Copy the lock range data. */
4136 lock_data = (char *)TALLOC_MEMDUP(
4137 ctx, pdata, total_data);
4138 if (!lock_data) {
4139 reply_nterror(req, NT_STATUS_NO_MEMORY);
4140 return;
4143 default:
4144 break;
4147 *pparams = (char *)SMB_REALLOC(*pparams,2);
4148 if (*pparams == NULL) {
4149 reply_nterror(req, NT_STATUS_NO_MEMORY);
4150 return;
4152 params = *pparams;
4153 SSVAL(params,0,0);
4154 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4155 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4156 if (*ppdata == NULL ) {
4157 reply_nterror(req, NT_STATUS_NO_MEMORY);
4158 return;
4160 pdata = *ppdata;
4161 dstart = pdata;
4162 dend = dstart + data_size - 1;
4164 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4165 mtime_ts = get_mtimespec(&sbuf);
4166 atime_ts = get_atimespec(&sbuf);
4168 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4170 if (!fsp) {
4171 /* Do we have this path open ? */
4172 files_struct *fsp1;
4173 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4174 fsp1 = file_find_di_first(fileid);
4175 if (fsp1 && fsp1->initial_allocation_size) {
4176 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4180 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4181 mtime_ts = write_time_ts;
4184 if (lp_dos_filetime_resolution(SNUM(conn))) {
4185 dos_filetime_timespec(&create_time_ts);
4186 dos_filetime_timespec(&mtime_ts);
4187 dos_filetime_timespec(&atime_ts);
4190 create_time = convert_timespec_to_time_t(create_time_ts);
4191 mtime = convert_timespec_to_time_t(mtime_ts);
4192 atime = convert_timespec_to_time_t(atime_ts);
4194 /* NT expects the name to be in an exact form of the *full*
4195 filename. See the trans2 torture test */
4196 if (ISDOT(base_name)) {
4197 dos_fname = talloc_strdup(ctx, "\\");
4198 if (!dos_fname) {
4199 reply_nterror(req, NT_STATUS_NO_MEMORY);
4200 return;
4202 } else {
4203 dos_fname = talloc_asprintf(ctx,
4204 "\\%s",
4205 fname);
4206 if (!dos_fname) {
4207 reply_nterror(req, NT_STATUS_NO_MEMORY);
4208 return;
4210 string_replace(dos_fname, '/', '\\');
4213 switch (info_level) {
4214 case SMB_INFO_STANDARD:
4215 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4216 data_size = 22;
4217 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4218 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4219 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4220 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4221 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4222 SSVAL(pdata,l1_attrFile,mode);
4223 break;
4225 case SMB_INFO_QUERY_EA_SIZE:
4227 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4228 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4229 data_size = 26;
4230 srv_put_dos_date2(pdata,0,create_time);
4231 srv_put_dos_date2(pdata,4,atime);
4232 srv_put_dos_date2(pdata,8,mtime); /* write time */
4233 SIVAL(pdata,12,(uint32)file_size);
4234 SIVAL(pdata,16,(uint32)allocation_size);
4235 SSVAL(pdata,20,mode);
4236 SIVAL(pdata,22,ea_size);
4237 break;
4240 case SMB_INFO_IS_NAME_VALID:
4241 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4242 if (tran_call == TRANSACT2_QFILEINFO) {
4243 /* os/2 needs this ? really ?*/
4244 reply_doserror(req, ERRDOS, ERRbadfunc);
4245 return;
4247 data_size = 0;
4248 param_size = 0;
4249 break;
4251 case SMB_INFO_QUERY_EAS_FROM_LIST:
4253 size_t total_ea_len = 0;
4254 struct ea_list *ea_file_list = NULL;
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4258 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4259 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4261 if (!ea_list || (total_ea_len > data_size)) {
4262 data_size = 4;
4263 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4264 break;
4267 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4268 break;
4271 case SMB_INFO_QUERY_ALL_EAS:
4273 /* We have data_size bytes to put EA's into. */
4274 size_t total_ea_len = 0;
4276 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4278 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4279 if (!ea_list || (total_ea_len > data_size)) {
4280 data_size = 4;
4281 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4282 break;
4285 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4286 break;
4289 case SMB_FILE_BASIC_INFORMATION:
4290 case SMB_QUERY_FILE_BASIC_INFO:
4292 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4293 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4294 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4295 } else {
4296 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4297 data_size = 40;
4298 SIVAL(pdata,36,0);
4300 put_long_date_timespec(pdata,create_time_ts);
4301 put_long_date_timespec(pdata+8,atime_ts);
4302 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4303 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4304 SIVAL(pdata,32,mode);
4306 DEBUG(5,("SMB_QFBI - "));
4307 DEBUG(5,("create: %s ", ctime(&create_time)));
4308 DEBUG(5,("access: %s ", ctime(&atime)));
4309 DEBUG(5,("write: %s ", ctime(&mtime)));
4310 DEBUG(5,("change: %s ", ctime(&mtime)));
4311 DEBUG(5,("mode: %x\n", mode));
4312 break;
4314 case SMB_FILE_STANDARD_INFORMATION:
4315 case SMB_QUERY_FILE_STANDARD_INFO:
4317 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4318 data_size = 24;
4319 SOFF_T(pdata,0,allocation_size);
4320 SOFF_T(pdata,8,file_size);
4321 SIVAL(pdata,16,nlink);
4322 SCVAL(pdata,20,delete_pending?1:0);
4323 SCVAL(pdata,21,(mode&aDIR)?1:0);
4324 SSVAL(pdata,22,0); /* Padding. */
4325 break;
4327 case SMB_FILE_EA_INFORMATION:
4328 case SMB_QUERY_FILE_EA_INFO:
4330 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4332 data_size = 4;
4333 SIVAL(pdata,0,ea_size);
4334 break;
4337 /* Get the 8.3 name - used if NT SMB was negotiated. */
4338 case SMB_QUERY_FILE_ALT_NAME_INFO:
4339 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4341 char mangled_name[13];
4342 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4343 if (!name_to_8_3(base_name,mangled_name,
4344 True,conn->params)) {
4345 reply_nterror(
4346 req,
4347 NT_STATUS_NO_MEMORY);
4349 len = srvstr_push(dstart, req->flags2,
4350 pdata+4, mangled_name,
4351 PTR_DIFF(dend, pdata+4),
4352 STR_UNICODE);
4353 data_size = 4 + len;
4354 SIVAL(pdata,0,len);
4355 break;
4358 case SMB_QUERY_FILE_NAME_INFO:
4360 this must be *exactly* right for ACLs on mapped drives to work
4362 len = srvstr_push(dstart, req->flags2,
4363 pdata+4, dos_fname,
4364 PTR_DIFF(dend, pdata+4),
4365 STR_UNICODE);
4366 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4367 data_size = 4 + len;
4368 SIVAL(pdata,0,len);
4369 break;
4371 case SMB_FILE_ALLOCATION_INFORMATION:
4372 case SMB_QUERY_FILE_ALLOCATION_INFO:
4373 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4374 data_size = 8;
4375 SOFF_T(pdata,0,allocation_size);
4376 break;
4378 case SMB_FILE_END_OF_FILE_INFORMATION:
4379 case SMB_QUERY_FILE_END_OF_FILEINFO:
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4381 data_size = 8;
4382 SOFF_T(pdata,0,file_size);
4383 break;
4385 case SMB_QUERY_FILE_ALL_INFO:
4386 case SMB_FILE_ALL_INFORMATION:
4388 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4389 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4390 put_long_date_timespec(pdata,create_time_ts);
4391 put_long_date_timespec(pdata+8,atime_ts);
4392 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4393 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4394 SIVAL(pdata,32,mode);
4395 SIVAL(pdata,36,0); /* padding. */
4396 pdata += 40;
4397 SOFF_T(pdata,0,allocation_size);
4398 SOFF_T(pdata,8,file_size);
4399 SIVAL(pdata,16,nlink);
4400 SCVAL(pdata,20,delete_pending);
4401 SCVAL(pdata,21,(mode&aDIR)?1:0);
4402 SSVAL(pdata,22,0);
4403 pdata += 24;
4404 SIVAL(pdata,0,ea_size);
4405 pdata += 4; /* EA info */
4406 len = srvstr_push(dstart, req->flags2,
4407 pdata+4, dos_fname,
4408 PTR_DIFF(dend, pdata+4),
4409 STR_UNICODE);
4410 SIVAL(pdata,0,len);
4411 pdata += 4 + len;
4412 data_size = PTR_DIFF(pdata,(*ppdata));
4413 break;
4415 case SMB_FILE_INTERNAL_INFORMATION:
4416 /* This should be an index number - looks like
4417 dev/ino to me :-)
4419 I think this causes us to fail the IFSKIT
4420 BasicFileInformationTest. -tpot */
4422 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4423 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4424 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4425 data_size = 8;
4426 break;
4428 case SMB_FILE_ACCESS_INFORMATION:
4429 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4430 SIVAL(pdata,0,access_mask);
4431 data_size = 4;
4432 break;
4434 case SMB_FILE_NAME_INFORMATION:
4435 /* Pathname with leading '\'. */
4437 size_t byte_len;
4438 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4439 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4440 SIVAL(pdata,0,byte_len);
4441 data_size = 4 + byte_len;
4442 break;
4445 case SMB_FILE_DISPOSITION_INFORMATION:
4446 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4447 data_size = 1;
4448 SCVAL(pdata,0,delete_pending);
4449 break;
4451 case SMB_FILE_POSITION_INFORMATION:
4452 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4453 data_size = 8;
4454 SOFF_T(pdata,0,pos);
4455 break;
4457 case SMB_FILE_MODE_INFORMATION:
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4459 SIVAL(pdata,0,mode);
4460 data_size = 4;
4461 break;
4463 case SMB_FILE_ALIGNMENT_INFORMATION:
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4465 SIVAL(pdata,0,0); /* No alignment needed. */
4466 data_size = 4;
4467 break;
4470 * NT4 server just returns "invalid query" to this - if we try
4471 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4472 * want this. JRA.
4474 /* The first statement above is false - verified using Thursby
4475 * client against NT4 -- gcolley.
4477 case SMB_QUERY_FILE_STREAM_INFO:
4478 case SMB_FILE_STREAM_INFORMATION: {
4479 unsigned int num_streams;
4480 struct stream_struct *streams;
4481 NTSTATUS status;
4483 DEBUG(10,("call_trans2qfilepathinfo: "
4484 "SMB_FILE_STREAM_INFORMATION\n"));
4486 status = SMB_VFS_STREAMINFO(
4487 conn, fsp, fname, talloc_tos(),
4488 &num_streams, &streams);
4490 if (!NT_STATUS_IS_OK(status)) {
4491 DEBUG(10, ("could not get stream info: %s\n",
4492 nt_errstr(status)));
4493 reply_nterror(req, status);
4494 return;
4497 status = marshall_stream_info(num_streams, streams,
4498 pdata, max_data_bytes,
4499 &data_size);
4501 if (!NT_STATUS_IS_OK(status)) {
4502 DEBUG(10, ("marshall_stream_info failed: %s\n",
4503 nt_errstr(status)));
4504 reply_nterror(req, status);
4505 return;
4508 TALLOC_FREE(streams);
4510 break;
4512 case SMB_QUERY_COMPRESSION_INFO:
4513 case SMB_FILE_COMPRESSION_INFORMATION:
4514 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4515 SOFF_T(pdata,0,file_size);
4516 SIVAL(pdata,8,0); /* ??? */
4517 SIVAL(pdata,12,0); /* ??? */
4518 data_size = 16;
4519 break;
4521 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4522 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4523 put_long_date_timespec(pdata,create_time_ts);
4524 put_long_date_timespec(pdata+8,atime_ts);
4525 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4526 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4527 SOFF_T(pdata,32,allocation_size);
4528 SOFF_T(pdata,40,file_size);
4529 SIVAL(pdata,48,mode);
4530 SIVAL(pdata,52,0); /* ??? */
4531 data_size = 56;
4532 break;
4534 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4535 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4536 SIVAL(pdata,0,mode);
4537 SIVAL(pdata,4,0);
4538 data_size = 8;
4539 break;
4542 * CIFS UNIX Extensions.
4545 case SMB_QUERY_FILE_UNIX_BASIC:
4547 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4548 data_size = PTR_DIFF(pdata,(*ppdata));
4551 int i;
4552 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4554 for (i=0; i<100; i++)
4555 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4556 DEBUG(4,("\n"));
4559 break;
4561 case SMB_QUERY_FILE_UNIX_INFO2:
4563 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4564 data_size = PTR_DIFF(pdata,(*ppdata));
4567 int i;
4568 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4570 for (i=0; i<100; i++)
4571 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4572 DEBUG(4,("\n"));
4575 break;
4577 case SMB_QUERY_FILE_UNIX_LINK:
4579 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4581 if (!buffer) {
4582 reply_nterror(req, NT_STATUS_NO_MEMORY);
4583 return;
4586 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4587 #ifdef S_ISLNK
4588 if(!S_ISLNK(sbuf.st_mode)) {
4589 reply_unixerror(req, ERRSRV,
4590 ERRbadlink);
4591 return;
4593 #else
4594 reply_unixerror(req, ERRDOS, ERRbadlink);
4595 return;
4596 #endif
4597 len = SMB_VFS_READLINK(conn,fullpathname,
4598 buffer, PATH_MAX);
4599 if (len == -1) {
4600 reply_unixerror(req, ERRDOS,
4601 ERRnoaccess);
4602 return;
4604 buffer[len] = 0;
4605 len = srvstr_push(dstart, req->flags2,
4606 pdata, buffer,
4607 PTR_DIFF(dend, pdata),
4608 STR_TERMINATE);
4609 pdata += len;
4610 data_size = PTR_DIFF(pdata,(*ppdata));
4612 break;
4615 #if defined(HAVE_POSIX_ACLS)
4616 case SMB_QUERY_POSIX_ACL:
4618 SMB_ACL_T file_acl = NULL;
4619 SMB_ACL_T def_acl = NULL;
4620 uint16 num_file_acls = 0;
4621 uint16 num_def_acls = 0;
4623 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4624 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4625 } else {
4626 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4629 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4630 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4631 fname ));
4632 reply_nterror(
4633 req,
4634 NT_STATUS_NOT_IMPLEMENTED);
4635 return;
4638 if (S_ISDIR(sbuf.st_mode)) {
4639 if (fsp && fsp->is_directory) {
4640 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4641 } else {
4642 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4644 def_acl = free_empty_sys_acl(conn, def_acl);
4647 num_file_acls = count_acl_entries(conn, file_acl);
4648 num_def_acls = count_acl_entries(conn, def_acl);
4650 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4651 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4652 data_size,
4653 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4654 SMB_POSIX_ACL_HEADER_SIZE) ));
4655 if (file_acl) {
4656 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4658 if (def_acl) {
4659 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4661 reply_nterror(
4662 req,
4663 NT_STATUS_BUFFER_TOO_SMALL);
4664 return;
4667 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4668 SSVAL(pdata,2,num_file_acls);
4669 SSVAL(pdata,4,num_def_acls);
4670 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4671 if (file_acl) {
4672 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4674 if (def_acl) {
4675 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4677 reply_nterror(
4678 req, NT_STATUS_INTERNAL_ERROR);
4679 return;
4681 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4682 if (file_acl) {
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4685 if (def_acl) {
4686 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4688 reply_nterror(
4689 req,
4690 NT_STATUS_INTERNAL_ERROR);
4691 return;
4694 if (file_acl) {
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4697 if (def_acl) {
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4700 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4701 break;
4703 #endif
4706 case SMB_QUERY_POSIX_LOCK:
4708 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4709 SMB_BIG_UINT count;
4710 SMB_BIG_UINT offset;
4711 uint32 lock_pid;
4712 enum brl_type lock_type;
4714 if (total_data != POSIX_LOCK_DATA_SIZE) {
4715 reply_nterror(
4716 req, NT_STATUS_INVALID_PARAMETER);
4717 return;
4720 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4721 case POSIX_LOCK_TYPE_READ:
4722 lock_type = READ_LOCK;
4723 break;
4724 case POSIX_LOCK_TYPE_WRITE:
4725 lock_type = WRITE_LOCK;
4726 break;
4727 case POSIX_LOCK_TYPE_UNLOCK:
4728 default:
4729 /* There's no point in asking for an unlock... */
4730 reply_nterror(
4731 req,
4732 NT_STATUS_INVALID_PARAMETER);
4733 return;
4736 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4737 #if defined(HAVE_LONGLONG)
4738 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4739 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4740 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4741 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4742 #else /* HAVE_LONGLONG */
4743 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4744 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4745 #endif /* HAVE_LONGLONG */
4747 status = query_lock(fsp,
4748 &lock_pid,
4749 &count,
4750 &offset,
4751 &lock_type,
4752 POSIX_LOCK);
4754 if (ERROR_WAS_LOCK_DENIED(status)) {
4755 /* Here we need to report who has it locked... */
4756 data_size = POSIX_LOCK_DATA_SIZE;
4758 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4759 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4760 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4761 #if defined(HAVE_LONGLONG)
4762 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4763 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4764 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4765 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4766 #else /* HAVE_LONGLONG */
4767 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4768 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4769 #endif /* HAVE_LONGLONG */
4771 } else if (NT_STATUS_IS_OK(status)) {
4772 /* For success we just return a copy of what we sent
4773 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4774 data_size = POSIX_LOCK_DATA_SIZE;
4775 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4776 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4777 } else {
4778 reply_nterror(req, status);
4779 return;
4781 break;
4784 default:
4785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4786 return;
4789 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4790 max_data_bytes);
4792 return;
4795 /****************************************************************************
4796 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4797 code.
4798 ****************************************************************************/
4800 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4801 connection_struct *conn,
4802 const char *oldname_in,
4803 const char *newname_in)
4805 SMB_STRUCT_STAT sbuf1, sbuf2;
4806 char *last_component_oldname = NULL;
4807 char *last_component_newname = NULL;
4808 char *oldname = NULL;
4809 char *newname = NULL;
4810 NTSTATUS status = NT_STATUS_OK;
4812 ZERO_STRUCT(sbuf1);
4813 ZERO_STRUCT(sbuf2);
4815 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4816 &last_component_oldname, &sbuf1);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 return status;
4821 status = check_name(conn, oldname);
4822 if (!NT_STATUS_IS_OK(status)) {
4823 return status;
4826 /* source must already exist. */
4827 if (!VALID_STAT(sbuf1)) {
4828 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4831 status = unix_convert(ctx, conn, newname_in, False, &newname,
4832 &last_component_newname, &sbuf2);
4833 if (!NT_STATUS_IS_OK(status)) {
4834 return status;
4837 status = check_name(conn, newname);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 return status;
4842 /* Disallow if newname already exists. */
4843 if (VALID_STAT(sbuf2)) {
4844 return NT_STATUS_OBJECT_NAME_COLLISION;
4847 /* No links from a directory. */
4848 if (S_ISDIR(sbuf1.st_mode)) {
4849 return NT_STATUS_FILE_IS_A_DIRECTORY;
4852 /* Ensure this is within the share. */
4853 status = check_reduced_name(conn, oldname);
4854 if (!NT_STATUS_IS_OK(status)) {
4855 return status;
4858 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4860 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4861 status = map_nt_error_from_unix(errno);
4862 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4863 nt_errstr(status), newname, oldname));
4866 return status;
4869 /****************************************************************************
4870 Deal with setting the time from any of the setfilepathinfo functions.
4871 ****************************************************************************/
4873 NTSTATUS smb_set_file_time(connection_struct *conn,
4874 files_struct *fsp,
4875 const char *fname,
4876 const SMB_STRUCT_STAT *psbuf,
4877 struct timespec ts[2],
4878 bool setting_write_time)
4880 uint32 action =
4881 FILE_NOTIFY_CHANGE_LAST_ACCESS
4882 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4884 if (!VALID_STAT(*psbuf)) {
4885 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4888 /* get some defaults (no modifications) if any info is zero or -1. */
4889 if (null_timespec(ts[0])) {
4890 ts[0] = get_atimespec(psbuf);
4891 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4894 if (null_timespec(ts[1])) {
4895 ts[1] = get_mtimespec(psbuf);
4896 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4899 if (!setting_write_time) {
4900 /* ts[1] comes from change time, not write time. */
4901 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4904 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4905 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4908 * Try and set the times of this file if
4909 * they are different from the current values.
4913 struct timespec mts = get_mtimespec(psbuf);
4914 struct timespec ats = get_atimespec(psbuf);
4915 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4916 return NT_STATUS_OK;
4920 if (setting_write_time) {
4922 * This was a setfileinfo on an open file.
4923 * NT does this a lot. We also need to
4924 * set the time here, as it can be read by
4925 * FindFirst/FindNext and with the patch for bug #2045
4926 * in smbd/fileio.c it ensures that this timestamp is
4927 * kept sticky even after a write. We save the request
4928 * away and will set it on file close and after a write. JRA.
4931 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4932 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4934 if (fsp != NULL) {
4935 set_sticky_write_time_fsp(fsp, ts[1]);
4936 } else {
4937 set_sticky_write_time_path(conn, fname,
4938 vfs_file_id_from_sbuf(conn, psbuf),
4939 ts[1]);
4943 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4945 if(file_ntimes(conn, fname, ts)!=0) {
4946 return map_nt_error_from_unix(errno);
4948 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4950 return NT_STATUS_OK;
4953 /****************************************************************************
4954 Deal with setting the dosmode from any of the setfilepathinfo functions.
4955 ****************************************************************************/
4957 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4958 const char *fname,
4959 SMB_STRUCT_STAT *psbuf,
4960 uint32 dosmode)
4962 if (!VALID_STAT(*psbuf)) {
4963 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4966 if (dosmode) {
4967 if (S_ISDIR(psbuf->st_mode)) {
4968 dosmode |= aDIR;
4969 } else {
4970 dosmode &= ~aDIR;
4974 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4976 /* check the mode isn't different, before changing it */
4977 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4979 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4980 fname, (unsigned int)dosmode ));
4982 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4983 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4984 fname, strerror(errno)));
4985 return map_nt_error_from_unix(errno);
4988 return NT_STATUS_OK;
4991 /****************************************************************************
4992 Deal with setting the size from any of the setfilepathinfo functions.
4993 ****************************************************************************/
4995 static NTSTATUS smb_set_file_size(connection_struct *conn,
4996 struct smb_request *req,
4997 files_struct *fsp,
4998 const char *fname,
4999 SMB_STRUCT_STAT *psbuf,
5000 SMB_OFF_T size)
5002 NTSTATUS status = NT_STATUS_OK;
5003 files_struct *new_fsp = NULL;
5005 if (!VALID_STAT(*psbuf)) {
5006 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5009 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5011 if (size == get_file_size(*psbuf)) {
5012 return NT_STATUS_OK;
5015 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5016 fname, (double)size ));
5018 if (fsp && fsp->fh->fd != -1) {
5019 /* Handle based call. */
5020 if (vfs_set_filelen(fsp, size) == -1) {
5021 return map_nt_error_from_unix(errno);
5023 trigger_write_time_update_immediate(fsp);
5024 return NT_STATUS_OK;
5027 status = open_file_ntcreate(conn, req, fname, psbuf,
5028 FILE_WRITE_ATTRIBUTES,
5029 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5030 FILE_OPEN,
5032 FILE_ATTRIBUTE_NORMAL,
5033 FORCE_OPLOCK_BREAK_TO_NONE,
5034 NULL, &new_fsp);
5036 if (!NT_STATUS_IS_OK(status)) {
5037 /* NB. We check for open_was_deferred in the caller. */
5038 return status;
5041 if (vfs_set_filelen(new_fsp, size) == -1) {
5042 status = map_nt_error_from_unix(errno);
5043 close_file(new_fsp,NORMAL_CLOSE);
5044 return status;
5047 trigger_write_time_update_immediate(new_fsp);
5048 close_file(new_fsp,NORMAL_CLOSE);
5049 return NT_STATUS_OK;
5052 /****************************************************************************
5053 Deal with SMB_INFO_SET_EA.
5054 ****************************************************************************/
5056 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5057 const char *pdata,
5058 int total_data,
5059 files_struct *fsp,
5060 const char *fname)
5062 struct ea_list *ea_list = NULL;
5063 TALLOC_CTX *ctx = NULL;
5064 NTSTATUS status = NT_STATUS_OK;
5066 if (total_data < 10) {
5068 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5069 length. They seem to have no effect. Bug #3212. JRA */
5071 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5072 /* We're done. We only get EA info in this call. */
5073 return NT_STATUS_OK;
5076 return NT_STATUS_INVALID_PARAMETER;
5079 if (IVAL(pdata,0) > total_data) {
5080 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5081 IVAL(pdata,0), (unsigned int)total_data));
5082 return NT_STATUS_INVALID_PARAMETER;
5085 ctx = talloc_tos();
5086 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5087 if (!ea_list) {
5088 return NT_STATUS_INVALID_PARAMETER;
5090 status = set_ea(conn, fsp, fname, ea_list);
5092 return status;
5095 /****************************************************************************
5096 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5097 ****************************************************************************/
5099 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5100 const char *pdata,
5101 int total_data,
5102 files_struct *fsp,
5103 const char *fname,
5104 SMB_STRUCT_STAT *psbuf)
5106 NTSTATUS status = NT_STATUS_OK;
5107 bool delete_on_close;
5108 uint32 dosmode = 0;
5110 if (total_data < 1) {
5111 return NT_STATUS_INVALID_PARAMETER;
5114 if (fsp == NULL) {
5115 return NT_STATUS_INVALID_HANDLE;
5118 delete_on_close = (CVAL(pdata,0) ? True : False);
5119 dosmode = dos_mode(conn, fname, psbuf);
5121 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5122 "delete_on_close = %u\n",
5123 fsp->fsp_name,
5124 (unsigned int)dosmode,
5125 (unsigned int)delete_on_close ));
5127 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5129 if (!NT_STATUS_IS_OK(status)) {
5130 return status;
5133 /* The set is across all open files on this dev/inode pair. */
5134 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
5135 return NT_STATUS_ACCESS_DENIED;
5137 return NT_STATUS_OK;
5140 /****************************************************************************
5141 Deal with SMB_FILE_POSITION_INFORMATION.
5142 ****************************************************************************/
5144 static NTSTATUS smb_file_position_information(connection_struct *conn,
5145 const char *pdata,
5146 int total_data,
5147 files_struct *fsp)
5149 SMB_BIG_UINT position_information;
5151 if (total_data < 8) {
5152 return NT_STATUS_INVALID_PARAMETER;
5155 if (fsp == NULL) {
5156 /* Ignore on pathname based set. */
5157 return NT_STATUS_OK;
5160 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5161 #ifdef LARGE_SMB_OFF_T
5162 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5163 #else /* LARGE_SMB_OFF_T */
5164 if (IVAL(pdata,4) != 0) {
5165 /* more than 32 bits? */
5166 return NT_STATUS_INVALID_PARAMETER;
5168 #endif /* LARGE_SMB_OFF_T */
5170 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5171 fsp->fsp_name, (double)position_information ));
5172 fsp->fh->position_information = position_information;
5173 return NT_STATUS_OK;
5176 /****************************************************************************
5177 Deal with SMB_FILE_MODE_INFORMATION.
5178 ****************************************************************************/
5180 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5181 const char *pdata,
5182 int total_data)
5184 uint32 mode;
5186 if (total_data < 4) {
5187 return NT_STATUS_INVALID_PARAMETER;
5189 mode = IVAL(pdata,0);
5190 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5191 return NT_STATUS_INVALID_PARAMETER;
5193 return NT_STATUS_OK;
5196 /****************************************************************************
5197 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5198 ****************************************************************************/
5200 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5201 struct smb_request *req,
5202 const char *pdata,
5203 int total_data,
5204 const char *fname)
5206 char *link_target = NULL;
5207 const char *newname = fname;
5208 NTSTATUS status = NT_STATUS_OK;
5209 TALLOC_CTX *ctx = talloc_tos();
5211 /* Set a symbolic link. */
5212 /* Don't allow this if follow links is false. */
5214 if (total_data == 0) {
5215 return NT_STATUS_INVALID_PARAMETER;
5218 if (!lp_symlinks(SNUM(conn))) {
5219 return NT_STATUS_ACCESS_DENIED;
5222 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5223 total_data, STR_TERMINATE);
5225 if (!link_target) {
5226 return NT_STATUS_INVALID_PARAMETER;
5229 /* !widelinks forces the target path to be within the share. */
5230 /* This means we can interpret the target as a pathname. */
5231 if (!lp_widelinks(SNUM(conn))) {
5232 char *rel_name = NULL;
5233 char *last_dirp = NULL;
5235 if (*link_target == '/') {
5236 /* No absolute paths allowed. */
5237 return NT_STATUS_ACCESS_DENIED;
5239 rel_name = talloc_strdup(ctx,newname);
5240 if (!rel_name) {
5241 return NT_STATUS_NO_MEMORY;
5243 last_dirp = strrchr_m(rel_name, '/');
5244 if (last_dirp) {
5245 last_dirp[1] = '\0';
5246 } else {
5247 rel_name = talloc_strdup(ctx,"./");
5248 if (!rel_name) {
5249 return NT_STATUS_NO_MEMORY;
5252 rel_name = talloc_asprintf_append(rel_name,
5253 "%s",
5254 link_target);
5255 if (!rel_name) {
5256 return NT_STATUS_NO_MEMORY;
5259 status = check_name(conn, rel_name);
5260 if (!NT_STATUS_IS_OK(status)) {
5261 return status;
5265 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5266 newname, link_target ));
5268 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5269 return map_nt_error_from_unix(errno);
5272 return NT_STATUS_OK;
5275 /****************************************************************************
5276 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5277 ****************************************************************************/
5279 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5280 struct smb_request *req,
5281 const char *pdata, int total_data,
5282 const char *fname)
5284 char *oldname = NULL;
5285 TALLOC_CTX *ctx = talloc_tos();
5286 NTSTATUS status = NT_STATUS_OK;
5288 /* Set a hard link. */
5289 if (total_data == 0) {
5290 return NT_STATUS_INVALID_PARAMETER;
5293 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5294 total_data, STR_TERMINATE, &status);
5295 if (!NT_STATUS_IS_OK(status)) {
5296 return status;
5299 status = resolve_dfspath(ctx, conn,
5300 req->flags2 & FLAGS2_DFS_PATHNAMES,
5301 oldname,
5302 &oldname);
5303 if (!NT_STATUS_IS_OK(status)) {
5304 return status;
5307 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5308 fname, oldname));
5310 return hardlink_internals(ctx, conn, oldname, fname);
5313 /****************************************************************************
5314 Deal with SMB_FILE_RENAME_INFORMATION.
5315 ****************************************************************************/
5317 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5318 struct smb_request *req,
5319 const char *pdata,
5320 int total_data,
5321 files_struct *fsp,
5322 const char *fname)
5324 bool overwrite;
5325 uint32 root_fid;
5326 uint32 len;
5327 char *newname = NULL;
5328 char *base_name = NULL;
5329 bool dest_has_wcard = False;
5330 NTSTATUS status = NT_STATUS_OK;
5331 char *p;
5332 TALLOC_CTX *ctx = talloc_tos();
5334 if (total_data < 13) {
5335 return NT_STATUS_INVALID_PARAMETER;
5338 overwrite = (CVAL(pdata,0) ? True : False);
5339 root_fid = IVAL(pdata,4);
5340 len = IVAL(pdata,8);
5342 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5343 return NT_STATUS_INVALID_PARAMETER;
5346 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5347 len, 0, &status,
5348 &dest_has_wcard);
5349 if (!NT_STATUS_IS_OK(status)) {
5350 return status;
5353 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5354 newname));
5356 status = resolve_dfspath_wcard(ctx, conn,
5357 req->flags2 & FLAGS2_DFS_PATHNAMES,
5358 newname,
5359 &newname,
5360 &dest_has_wcard);
5361 if (!NT_STATUS_IS_OK(status)) {
5362 return status;
5365 /* Check the new name has no '/' characters. */
5366 if (strchr_m(newname, '/')) {
5367 return NT_STATUS_NOT_SUPPORTED;
5370 if (fsp && fsp->base_fsp) {
5371 if (newname[0] != ':') {
5372 return NT_STATUS_NOT_SUPPORTED;
5374 base_name = talloc_asprintf(ctx, "%s%s",
5375 fsp->base_fsp->fsp_name,
5376 newname);
5377 if (!base_name) {
5378 return NT_STATUS_NO_MEMORY;
5380 } else {
5381 if (is_ntfs_stream_name(newname)) {
5382 return NT_STATUS_NOT_SUPPORTED;
5385 /* Create the base directory. */
5386 base_name = talloc_strdup(ctx, fname);
5387 if (!base_name) {
5388 return NT_STATUS_NO_MEMORY;
5390 p = strrchr_m(base_name, '/');
5391 if (p) {
5392 p[1] = '\0';
5393 } else {
5394 base_name = talloc_strdup(ctx, "./");
5395 if (!base_name) {
5396 return NT_STATUS_NO_MEMORY;
5399 /* Append the new name. */
5400 base_name = talloc_asprintf_append(base_name,
5401 "%s",
5402 newname);
5403 if (!base_name) {
5404 return NT_STATUS_NO_MEMORY;
5408 if (fsp) {
5409 SMB_STRUCT_STAT sbuf;
5410 char *newname_last_component = NULL;
5412 ZERO_STRUCT(sbuf);
5414 status = unix_convert(ctx, conn, newname, False,
5415 &newname,
5416 &newname_last_component,
5417 &sbuf);
5419 /* If an error we expect this to be
5420 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5422 if (!NT_STATUS_IS_OK(status)
5423 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5424 status)) {
5425 return status;
5428 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5429 fsp->fnum, fsp->fsp_name, base_name ));
5430 status = rename_internals_fsp(conn, fsp, base_name,
5431 newname_last_component, 0,
5432 overwrite);
5433 } else {
5434 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5435 fname, base_name ));
5436 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5437 overwrite, False, dest_has_wcard,
5438 FILE_WRITE_ATTRIBUTES);
5441 return status;
5444 /****************************************************************************
5445 Deal with SMB_SET_POSIX_ACL.
5446 ****************************************************************************/
5448 #if defined(HAVE_POSIX_ACLS)
5449 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5450 const char *pdata,
5451 int total_data,
5452 files_struct *fsp,
5453 const char *fname,
5454 SMB_STRUCT_STAT *psbuf)
5456 uint16 posix_acl_version;
5457 uint16 num_file_acls;
5458 uint16 num_def_acls;
5459 bool valid_file_acls = True;
5460 bool valid_def_acls = True;
5462 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5463 return NT_STATUS_INVALID_PARAMETER;
5465 posix_acl_version = SVAL(pdata,0);
5466 num_file_acls = SVAL(pdata,2);
5467 num_def_acls = SVAL(pdata,4);
5469 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5470 valid_file_acls = False;
5471 num_file_acls = 0;
5474 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5475 valid_def_acls = False;
5476 num_def_acls = 0;
5479 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5480 return NT_STATUS_INVALID_PARAMETER;
5483 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5484 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5485 return NT_STATUS_INVALID_PARAMETER;
5488 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5489 fname ? fname : fsp->fsp_name,
5490 (unsigned int)num_file_acls,
5491 (unsigned int)num_def_acls));
5493 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5494 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5495 return map_nt_error_from_unix(errno);
5498 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5499 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5500 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5501 return map_nt_error_from_unix(errno);
5503 return NT_STATUS_OK;
5505 #endif
5507 /****************************************************************************
5508 Deal with SMB_SET_POSIX_LOCK.
5509 ****************************************************************************/
5511 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5512 const struct smb_request *req,
5513 const char *pdata,
5514 int total_data,
5515 files_struct *fsp)
5517 SMB_BIG_UINT count;
5518 SMB_BIG_UINT offset;
5519 uint32 lock_pid;
5520 bool blocking_lock = False;
5521 enum brl_type lock_type;
5523 NTSTATUS status = NT_STATUS_OK;
5525 if (fsp == NULL || fsp->fh->fd == -1) {
5526 return NT_STATUS_INVALID_HANDLE;
5529 if (total_data != POSIX_LOCK_DATA_SIZE) {
5530 return NT_STATUS_INVALID_PARAMETER;
5533 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5534 case POSIX_LOCK_TYPE_READ:
5535 lock_type = READ_LOCK;
5536 break;
5537 case POSIX_LOCK_TYPE_WRITE:
5538 /* Return the right POSIX-mappable error code for files opened read-only. */
5539 if (!fsp->can_write) {
5540 return NT_STATUS_INVALID_HANDLE;
5542 lock_type = WRITE_LOCK;
5543 break;
5544 case POSIX_LOCK_TYPE_UNLOCK:
5545 lock_type = UNLOCK_LOCK;
5546 break;
5547 default:
5548 return NT_STATUS_INVALID_PARAMETER;
5551 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5552 blocking_lock = False;
5553 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5554 blocking_lock = True;
5555 } else {
5556 return NT_STATUS_INVALID_PARAMETER;
5559 if (!lp_blocking_locks(SNUM(conn))) {
5560 blocking_lock = False;
5563 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5564 #if defined(HAVE_LONGLONG)
5565 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5566 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5567 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5568 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5569 #else /* HAVE_LONGLONG */
5570 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5571 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5572 #endif /* HAVE_LONGLONG */
5574 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5575 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5576 fsp->fsp_name,
5577 (unsigned int)lock_type,
5578 (unsigned int)lock_pid,
5579 (double)count,
5580 (double)offset ));
5582 if (lock_type == UNLOCK_LOCK) {
5583 status = do_unlock(smbd_messaging_context(),
5584 fsp,
5585 lock_pid,
5586 count,
5587 offset,
5588 POSIX_LOCK);
5589 } else {
5590 uint32 block_smbpid;
5592 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5593 fsp,
5594 lock_pid,
5595 count,
5596 offset,
5597 lock_type,
5598 POSIX_LOCK,
5599 blocking_lock,
5600 &status,
5601 &block_smbpid);
5603 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5605 * A blocking lock was requested. Package up
5606 * this smb into a queued request and push it
5607 * onto the blocking lock queue.
5609 if(push_blocking_lock_request(br_lck,
5610 req,
5611 fsp,
5612 -1, /* infinite timeout. */
5614 lock_pid,
5615 lock_type,
5616 POSIX_LOCK,
5617 offset,
5618 count,
5619 block_smbpid)) {
5620 TALLOC_FREE(br_lck);
5621 return status;
5624 TALLOC_FREE(br_lck);
5627 return status;
5630 /****************************************************************************
5631 Deal with SMB_INFO_STANDARD.
5632 ****************************************************************************/
5634 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5635 const char *pdata,
5636 int total_data,
5637 files_struct *fsp,
5638 const char *fname,
5639 const SMB_STRUCT_STAT *psbuf)
5641 struct timespec ts[2];
5643 if (total_data < 12) {
5644 return NT_STATUS_INVALID_PARAMETER;
5647 /* access time */
5648 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5649 /* write time */
5650 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5652 DEBUG(10,("smb_set_info_standard: file %s\n",
5653 fname ? fname : fsp->fsp_name ));
5655 return smb_set_file_time(conn,
5656 fsp,
5657 fname,
5658 psbuf,
5660 true);
5663 /****************************************************************************
5664 Deal with SMB_SET_FILE_BASIC_INFO.
5665 ****************************************************************************/
5667 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5668 const char *pdata,
5669 int total_data,
5670 files_struct *fsp,
5671 const char *fname,
5672 SMB_STRUCT_STAT *psbuf)
5674 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5675 struct timespec write_time;
5676 struct timespec changed_time;
5677 uint32 dosmode = 0;
5678 struct timespec ts[2];
5679 NTSTATUS status = NT_STATUS_OK;
5680 bool setting_write_time = true;
5682 if (total_data < 36) {
5683 return NT_STATUS_INVALID_PARAMETER;
5686 /* Set the attributes */
5687 dosmode = IVAL(pdata,32);
5688 status = smb_set_file_dosmode(conn,
5689 fname,
5690 psbuf,
5691 dosmode);
5692 if (!NT_STATUS_IS_OK(status)) {
5693 return status;
5696 /* Ignore create time at offset pdata. */
5698 /* access time */
5699 ts[0] = interpret_long_date(pdata+8);
5701 write_time = interpret_long_date(pdata+16);
5702 changed_time = interpret_long_date(pdata+24);
5704 /* mtime */
5705 ts[1] = timespec_min(&write_time, &changed_time);
5707 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5708 ts[1] = write_time;
5711 /* Prefer a defined time to an undefined one. */
5712 if (null_timespec(ts[1])) {
5713 if (null_timespec(write_time)) {
5714 ts[1] = changed_time;
5715 setting_write_time = false;
5716 } else {
5717 ts[1] = write_time;
5721 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5722 fname ? fname : fsp->fsp_name ));
5724 return smb_set_file_time(conn,
5725 fsp,
5726 fname,
5727 psbuf,
5729 setting_write_time);
5732 /****************************************************************************
5733 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5734 ****************************************************************************/
5736 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5737 struct smb_request *req,
5738 const char *pdata,
5739 int total_data,
5740 files_struct *fsp,
5741 const char *fname,
5742 SMB_STRUCT_STAT *psbuf)
5744 SMB_BIG_UINT allocation_size = 0;
5745 NTSTATUS status = NT_STATUS_OK;
5746 files_struct *new_fsp = NULL;
5748 if (!VALID_STAT(*psbuf)) {
5749 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5752 if (total_data < 8) {
5753 return NT_STATUS_INVALID_PARAMETER;
5756 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5757 #ifdef LARGE_SMB_OFF_T
5758 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5759 #else /* LARGE_SMB_OFF_T */
5760 if (IVAL(pdata,4) != 0) {
5761 /* more than 32 bits? */
5762 return NT_STATUS_INVALID_PARAMETER;
5764 #endif /* LARGE_SMB_OFF_T */
5766 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5767 fname, (double)allocation_size ));
5769 if (allocation_size) {
5770 allocation_size = smb_roundup(conn, allocation_size);
5773 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5774 fname, (double)allocation_size ));
5776 if (fsp && fsp->fh->fd != -1) {
5777 /* Open file handle. */
5778 /* Only change if needed. */
5779 if (allocation_size != get_file_size(*psbuf)) {
5780 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5781 return map_nt_error_from_unix(errno);
5784 /* But always update the time. */
5786 * This is equivalent to a write. Ensure it's seen immediately
5787 * if there are no pending writes.
5789 trigger_write_time_update_immediate(fsp);
5790 return NT_STATUS_OK;
5793 /* Pathname or stat or directory file. */
5795 status = open_file_ntcreate(conn, req, fname, psbuf,
5796 FILE_WRITE_DATA,
5797 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5798 FILE_OPEN,
5800 FILE_ATTRIBUTE_NORMAL,
5801 FORCE_OPLOCK_BREAK_TO_NONE,
5802 NULL, &new_fsp);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 /* NB. We check for open_was_deferred in the caller. */
5806 return status;
5809 /* Only change if needed. */
5810 if (allocation_size != get_file_size(*psbuf)) {
5811 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5812 status = map_nt_error_from_unix(errno);
5813 close_file(new_fsp,NORMAL_CLOSE);
5814 return status;
5818 /* Changing the allocation size should set the last mod time. */
5820 * This is equivalent to a write. Ensure it's seen immediately
5821 * if there are no pending writes.
5823 trigger_write_time_update_immediate(new_fsp);
5825 close_file(new_fsp,NORMAL_CLOSE);
5826 return NT_STATUS_OK;
5829 /****************************************************************************
5830 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5831 ****************************************************************************/
5833 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5834 struct smb_request *req,
5835 const char *pdata,
5836 int total_data,
5837 files_struct *fsp,
5838 const char *fname,
5839 SMB_STRUCT_STAT *psbuf)
5841 SMB_OFF_T size;
5843 if (total_data < 8) {
5844 return NT_STATUS_INVALID_PARAMETER;
5847 size = IVAL(pdata,0);
5848 #ifdef LARGE_SMB_OFF_T
5849 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5850 #else /* LARGE_SMB_OFF_T */
5851 if (IVAL(pdata,4) != 0) {
5852 /* more than 32 bits? */
5853 return NT_STATUS_INVALID_PARAMETER;
5855 #endif /* LARGE_SMB_OFF_T */
5856 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5857 "file %s to %.0f\n", fname, (double)size ));
5859 return smb_set_file_size(conn, req,
5860 fsp,
5861 fname,
5862 psbuf,
5863 size);
5866 /****************************************************************************
5867 Allow a UNIX info mknod.
5868 ****************************************************************************/
5870 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5871 const char *pdata,
5872 int total_data,
5873 const char *fname,
5874 SMB_STRUCT_STAT *psbuf)
5876 uint32 file_type = IVAL(pdata,56);
5877 #if defined(HAVE_MAKEDEV)
5878 uint32 dev_major = IVAL(pdata,60);
5879 uint32 dev_minor = IVAL(pdata,68);
5880 #endif
5881 SMB_DEV_T dev = (SMB_DEV_T)0;
5882 uint32 raw_unixmode = IVAL(pdata,84);
5883 NTSTATUS status;
5884 mode_t unixmode;
5886 if (total_data < 100) {
5887 return NT_STATUS_INVALID_PARAMETER;
5890 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5891 if (!NT_STATUS_IS_OK(status)) {
5892 return status;
5895 #if defined(HAVE_MAKEDEV)
5896 dev = makedev(dev_major, dev_minor);
5897 #endif
5899 switch (file_type) {
5900 #if defined(S_IFIFO)
5901 case UNIX_TYPE_FIFO:
5902 unixmode |= S_IFIFO;
5903 break;
5904 #endif
5905 #if defined(S_IFSOCK)
5906 case UNIX_TYPE_SOCKET:
5907 unixmode |= S_IFSOCK;
5908 break;
5909 #endif
5910 #if defined(S_IFCHR)
5911 case UNIX_TYPE_CHARDEV:
5912 unixmode |= S_IFCHR;
5913 break;
5914 #endif
5915 #if defined(S_IFBLK)
5916 case UNIX_TYPE_BLKDEV:
5917 unixmode |= S_IFBLK;
5918 break;
5919 #endif
5920 default:
5921 return NT_STATUS_INVALID_PARAMETER;
5924 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5925 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5927 /* Ok - do the mknod. */
5928 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5929 return map_nt_error_from_unix(errno);
5932 /* If any of the other "set" calls fail we
5933 * don't want to end up with a half-constructed mknod.
5936 if (lp_inherit_perms(SNUM(conn))) {
5937 inherit_access_acl(
5938 conn, parent_dirname(fname),
5939 fname, unixmode);
5942 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5943 status = map_nt_error_from_unix(errno);
5944 SMB_VFS_UNLINK(conn,fname);
5945 return status;
5947 return NT_STATUS_OK;
5950 /****************************************************************************
5951 Deal with SMB_SET_FILE_UNIX_BASIC.
5952 ****************************************************************************/
5954 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5955 struct smb_request *req,
5956 const char *pdata,
5957 int total_data,
5958 files_struct *fsp,
5959 const char *fname,
5960 SMB_STRUCT_STAT *psbuf)
5962 struct timespec ts[2];
5963 uint32 raw_unixmode;
5964 mode_t unixmode;
5965 SMB_OFF_T size = 0;
5966 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5967 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5968 NTSTATUS status = NT_STATUS_OK;
5969 bool delete_on_fail = False;
5970 enum perm_type ptype;
5972 if (total_data < 100) {
5973 return NT_STATUS_INVALID_PARAMETER;
5976 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5977 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5978 size=IVAL(pdata,0); /* first 8 Bytes are size */
5979 #ifdef LARGE_SMB_OFF_T
5980 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5981 #else /* LARGE_SMB_OFF_T */
5982 if (IVAL(pdata,4) != 0) {
5983 /* more than 32 bits? */
5984 return NT_STATUS_INVALID_PARAMETER;
5986 #endif /* LARGE_SMB_OFF_T */
5989 ts[0] = interpret_long_date(pdata+24); /* access_time */
5990 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5991 set_owner = (uid_t)IVAL(pdata,40);
5992 set_grp = (gid_t)IVAL(pdata,48);
5993 raw_unixmode = IVAL(pdata,84);
5995 if (VALID_STAT(*psbuf)) {
5996 if (S_ISDIR(psbuf->st_mode)) {
5997 ptype = PERM_EXISTING_DIR;
5998 } else {
5999 ptype = PERM_EXISTING_FILE;
6001 } else {
6002 ptype = PERM_NEW_FILE;
6005 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6006 if (!NT_STATUS_IS_OK(status)) {
6007 return status;
6010 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6011 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6012 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6014 if (!VALID_STAT(*psbuf)) {
6016 * The only valid use of this is to create character and block
6017 * devices, and named pipes. This is deprecated (IMHO) and
6018 * a new info level should be used for mknod. JRA.
6021 status = smb_unix_mknod(conn,
6022 pdata,
6023 total_data,
6024 fname,
6025 psbuf);
6026 if (!NT_STATUS_IS_OK(status)) {
6027 return status;
6030 /* Ensure we don't try and change anything else. */
6031 raw_unixmode = SMB_MODE_NO_CHANGE;
6032 size = get_file_size(*psbuf);
6033 ts[0] = get_atimespec(psbuf);
6034 ts[1] = get_mtimespec(psbuf);
6036 * We continue here as we might want to change the
6037 * owner uid/gid.
6039 delete_on_fail = True;
6042 #if 1
6043 /* Horrible backwards compatibility hack as an old server bug
6044 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6045 * */
6047 if (!size) {
6048 size = get_file_size(*psbuf);
6050 #endif
6053 * Deal with the UNIX specific mode set.
6056 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6057 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6058 (unsigned int)unixmode, fname ));
6059 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6060 return map_nt_error_from_unix(errno);
6065 * Deal with the UNIX specific uid set.
6068 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6069 int ret;
6071 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6072 (unsigned int)set_owner, fname ));
6074 if (S_ISLNK(psbuf->st_mode)) {
6075 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6076 } else {
6077 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6080 if (ret != 0) {
6081 status = map_nt_error_from_unix(errno);
6082 if (delete_on_fail) {
6083 SMB_VFS_UNLINK(conn,fname);
6085 return status;
6090 * Deal with the UNIX specific gid set.
6093 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6094 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6095 (unsigned int)set_owner, fname ));
6096 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6097 status = map_nt_error_from_unix(errno);
6098 if (delete_on_fail) {
6099 SMB_VFS_UNLINK(conn,fname);
6101 return status;
6105 /* Deal with any size changes. */
6107 status = smb_set_file_size(conn, req,
6108 fsp,
6109 fname,
6110 psbuf,
6111 size);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 return status;
6116 /* Deal with any time changes. */
6118 return smb_set_file_time(conn,
6119 fsp,
6120 fname,
6121 psbuf,
6123 true);
6126 /****************************************************************************
6127 Deal with SMB_SET_FILE_UNIX_INFO2.
6128 ****************************************************************************/
6130 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6131 struct smb_request *req,
6132 const char *pdata,
6133 int total_data,
6134 files_struct *fsp,
6135 const char *fname,
6136 SMB_STRUCT_STAT *psbuf)
6138 NTSTATUS status;
6139 uint32 smb_fflags;
6140 uint32 smb_fmask;
6142 if (total_data < 116) {
6143 return NT_STATUS_INVALID_PARAMETER;
6146 /* Start by setting all the fields that are common between UNIX_BASIC
6147 * and UNIX_INFO2.
6149 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6150 fsp, fname, psbuf);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 return status;
6155 smb_fflags = IVAL(pdata, 108);
6156 smb_fmask = IVAL(pdata, 112);
6158 /* NB: We should only attempt to alter the file flags if the client
6159 * sends a non-zero mask.
6161 if (smb_fmask != 0) {
6162 int stat_fflags = 0;
6164 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6165 &stat_fflags)) {
6166 /* Client asked to alter a flag we don't understand. */
6167 return NT_STATUS_INVALID_PARAMETER;
6170 if (fsp && fsp->fh->fd != -1) {
6171 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6172 return NT_STATUS_NOT_SUPPORTED;
6173 } else {
6174 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6175 return map_nt_error_from_unix(errno);
6180 /* XXX: need to add support for changing the create_time here. You
6181 * can do this for paths on Darwin with setattrlist(2). The right way
6182 * to hook this up is probably by extending the VFS utimes interface.
6185 return NT_STATUS_OK;
6188 /****************************************************************************
6189 Create a directory with POSIX semantics.
6190 ****************************************************************************/
6192 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6193 struct smb_request *req,
6194 char **ppdata,
6195 int total_data,
6196 const char *fname,
6197 SMB_STRUCT_STAT *psbuf,
6198 int *pdata_return_size)
6200 NTSTATUS status = NT_STATUS_OK;
6201 uint32 raw_unixmode = 0;
6202 uint32 mod_unixmode = 0;
6203 mode_t unixmode = (mode_t)0;
6204 files_struct *fsp = NULL;
6205 uint16 info_level_return = 0;
6206 int info;
6207 char *pdata = *ppdata;
6209 if (total_data < 18) {
6210 return NT_STATUS_INVALID_PARAMETER;
6213 raw_unixmode = IVAL(pdata,8);
6214 /* Next 4 bytes are not yet defined. */
6216 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 return status;
6221 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6223 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6224 fname, (unsigned int)unixmode ));
6226 status = open_directory(conn, req,
6227 fname,
6228 psbuf,
6229 FILE_READ_ATTRIBUTES, /* Just a stat open */
6230 FILE_SHARE_NONE, /* Ignored for stat opens */
6231 FILE_CREATE,
6233 mod_unixmode,
6234 &info,
6235 &fsp);
6237 if (NT_STATUS_IS_OK(status)) {
6238 close_file(fsp, NORMAL_CLOSE);
6241 info_level_return = SVAL(pdata,16);
6243 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6244 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6245 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6246 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6247 } else {
6248 *pdata_return_size = 12;
6251 /* Realloc the data size */
6252 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6253 if (*ppdata == NULL) {
6254 *pdata_return_size = 0;
6255 return NT_STATUS_NO_MEMORY;
6257 pdata = *ppdata;
6259 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6260 SSVAL(pdata,2,0); /* No fnum. */
6261 SIVAL(pdata,4,info); /* Was directory created. */
6263 switch (info_level_return) {
6264 case SMB_QUERY_FILE_UNIX_BASIC:
6265 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6266 SSVAL(pdata,10,0); /* Padding. */
6267 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6268 break;
6269 case SMB_QUERY_FILE_UNIX_INFO2:
6270 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6271 SSVAL(pdata,10,0); /* Padding. */
6272 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6273 break;
6274 default:
6275 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6276 SSVAL(pdata,10,0); /* Padding. */
6277 break;
6280 return status;
6283 /****************************************************************************
6284 Open/Create a file with POSIX semantics.
6285 ****************************************************************************/
6287 static NTSTATUS smb_posix_open(connection_struct *conn,
6288 struct smb_request *req,
6289 char **ppdata,
6290 int total_data,
6291 const char *fname,
6292 SMB_STRUCT_STAT *psbuf,
6293 int *pdata_return_size)
6295 bool extended_oplock_granted = False;
6296 char *pdata = *ppdata;
6297 uint32 flags = 0;
6298 uint32 wire_open_mode = 0;
6299 uint32 raw_unixmode = 0;
6300 uint32 mod_unixmode = 0;
6301 uint32 create_disp = 0;
6302 uint32 access_mask = 0;
6303 uint32 create_options = 0;
6304 NTSTATUS status = NT_STATUS_OK;
6305 mode_t unixmode = (mode_t)0;
6306 files_struct *fsp = NULL;
6307 int oplock_request = 0;
6308 int info = 0;
6309 uint16 info_level_return = 0;
6311 if (total_data < 18) {
6312 return NT_STATUS_INVALID_PARAMETER;
6315 flags = IVAL(pdata,0);
6316 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6317 if (oplock_request) {
6318 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6321 wire_open_mode = IVAL(pdata,4);
6323 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6324 return smb_posix_mkdir(conn, req,
6325 ppdata,
6326 total_data,
6327 fname,
6328 psbuf,
6329 pdata_return_size);
6332 switch (wire_open_mode & SMB_ACCMODE) {
6333 case SMB_O_RDONLY:
6334 access_mask = FILE_READ_DATA;
6335 break;
6336 case SMB_O_WRONLY:
6337 access_mask = FILE_WRITE_DATA;
6338 break;
6339 case SMB_O_RDWR:
6340 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6341 break;
6342 default:
6343 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6344 (unsigned int)wire_open_mode ));
6345 return NT_STATUS_INVALID_PARAMETER;
6348 wire_open_mode &= ~SMB_ACCMODE;
6350 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6351 create_disp = FILE_CREATE;
6352 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6353 create_disp = FILE_OVERWRITE_IF;
6354 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6355 create_disp = FILE_OPEN_IF;
6356 } else {
6357 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6358 (unsigned int)wire_open_mode ));
6359 return NT_STATUS_INVALID_PARAMETER;
6362 raw_unixmode = IVAL(pdata,8);
6363 /* Next 4 bytes are not yet defined. */
6365 status = unix_perms_from_wire(conn,
6366 psbuf,
6367 raw_unixmode,
6368 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6369 &unixmode);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 return status;
6375 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6377 if (wire_open_mode & SMB_O_SYNC) {
6378 create_options |= FILE_WRITE_THROUGH;
6380 if (wire_open_mode & SMB_O_APPEND) {
6381 access_mask |= FILE_APPEND_DATA;
6383 if (wire_open_mode & SMB_O_DIRECT) {
6384 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6387 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6388 fname,
6389 (unsigned int)wire_open_mode,
6390 (unsigned int)unixmode ));
6392 status = open_file_ntcreate(conn, req,
6393 fname,
6394 psbuf,
6395 access_mask,
6396 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6397 create_disp,
6398 0, /* no create options yet. */
6399 mod_unixmode,
6400 oplock_request,
6401 &info,
6402 &fsp);
6404 if (!NT_STATUS_IS_OK(status)) {
6405 return status;
6408 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6409 extended_oplock_granted = True;
6412 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6413 extended_oplock_granted = True;
6416 info_level_return = SVAL(pdata,16);
6418 /* Allocate the correct return size. */
6420 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6421 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6422 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6423 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6424 } else {
6425 *pdata_return_size = 12;
6428 /* Realloc the data size */
6429 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6430 if (*ppdata == NULL) {
6431 close_file(fsp,ERROR_CLOSE);
6432 *pdata_return_size = 0;
6433 return NT_STATUS_NO_MEMORY;
6435 pdata = *ppdata;
6437 if (extended_oplock_granted) {
6438 if (flags & REQUEST_BATCH_OPLOCK) {
6439 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6440 } else {
6441 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6443 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6444 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6445 } else {
6446 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6449 SSVAL(pdata,2,fsp->fnum);
6450 SIVAL(pdata,4,info); /* Was file created etc. */
6452 switch (info_level_return) {
6453 case SMB_QUERY_FILE_UNIX_BASIC:
6454 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6455 SSVAL(pdata,10,0); /* padding. */
6456 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6457 break;
6458 case SMB_QUERY_FILE_UNIX_INFO2:
6459 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6460 SSVAL(pdata,10,0); /* padding. */
6461 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6462 break;
6463 default:
6464 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6465 SSVAL(pdata,10,0); /* padding. */
6466 break;
6468 return NT_STATUS_OK;
6471 /****************************************************************************
6472 Delete a file with POSIX semantics.
6473 ****************************************************************************/
6475 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6476 struct smb_request *req,
6477 const char *pdata,
6478 int total_data,
6479 const char *fname,
6480 SMB_STRUCT_STAT *psbuf)
6482 NTSTATUS status = NT_STATUS_OK;
6483 files_struct *fsp = NULL;
6484 uint16 flags = 0;
6485 char del = 1;
6486 int info = 0;
6487 int i;
6488 struct share_mode_lock *lck = NULL;
6490 if (total_data < 2) {
6491 return NT_STATUS_INVALID_PARAMETER;
6494 flags = SVAL(pdata,0);
6496 if (!VALID_STAT(*psbuf)) {
6497 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6500 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6501 !VALID_STAT_OF_DIR(*psbuf)) {
6502 return NT_STATUS_NOT_A_DIRECTORY;
6505 DEBUG(10,("smb_posix_unlink: %s %s\n",
6506 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6507 fname));
6509 if (VALID_STAT_OF_DIR(*psbuf)) {
6510 status = open_directory(conn, req,
6511 fname,
6512 psbuf,
6513 DELETE_ACCESS,
6514 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6515 FILE_OPEN,
6517 FILE_FLAG_POSIX_SEMANTICS|0777,
6518 &info,
6519 &fsp);
6520 } else {
6522 status = open_file_ntcreate(conn, req,
6523 fname,
6524 psbuf,
6525 DELETE_ACCESS,
6526 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6527 FILE_OPEN,
6529 FILE_FLAG_POSIX_SEMANTICS|0777,
6530 0, /* No oplock, but break existing ones. */
6531 &info,
6532 &fsp);
6535 if (!NT_STATUS_IS_OK(status)) {
6536 return status;
6540 * Don't lie to client. If we can't really delete due to
6541 * non-POSIX opens return SHARING_VIOLATION.
6544 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6545 NULL);
6546 if (lck == NULL) {
6547 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6548 "lock for file %s\n", fsp->fsp_name));
6549 close_file(fsp, NORMAL_CLOSE);
6550 return NT_STATUS_INVALID_PARAMETER;
6554 * See if others still have the file open. If this is the case, then
6555 * don't delete. If all opens are POSIX delete we can set the delete
6556 * on close disposition.
6558 for (i=0; i<lck->num_share_modes; i++) {
6559 struct share_mode_entry *e = &lck->share_modes[i];
6560 if (is_valid_share_mode_entry(e)) {
6561 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6562 continue;
6564 /* Fail with sharing violation. */
6565 close_file(fsp, NORMAL_CLOSE);
6566 TALLOC_FREE(lck);
6567 return NT_STATUS_SHARING_VIOLATION;
6572 * Set the delete on close.
6574 status = smb_set_file_disposition_info(conn,
6575 &del,
6577 fsp,
6578 fname,
6579 psbuf);
6581 if (!NT_STATUS_IS_OK(status)) {
6582 close_file(fsp, NORMAL_CLOSE);
6583 TALLOC_FREE(lck);
6584 return status;
6586 TALLOC_FREE(lck);
6587 return close_file(fsp, NORMAL_CLOSE);
6590 /****************************************************************************
6591 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6592 ****************************************************************************/
6594 static void call_trans2setfilepathinfo(connection_struct *conn,
6595 struct smb_request *req,
6596 unsigned int tran_call,
6597 char **pparams, int total_params,
6598 char **ppdata, int total_data,
6599 unsigned int max_data_bytes)
6601 char *params = *pparams;
6602 char *pdata = *ppdata;
6603 uint16 info_level;
6604 SMB_STRUCT_STAT sbuf;
6605 char *fname = NULL;
6606 files_struct *fsp = NULL;
6607 NTSTATUS status = NT_STATUS_OK;
6608 int data_return_size = 0;
6609 TALLOC_CTX *ctx = talloc_tos();
6611 if (!params) {
6612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6613 return;
6616 ZERO_STRUCT(sbuf);
6618 if (tran_call == TRANSACT2_SETFILEINFO) {
6619 if (total_params < 4) {
6620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6621 return;
6624 fsp = file_fsp(SVAL(params,0));
6625 /* Basic check for non-null fsp. */
6626 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6627 return;
6629 info_level = SVAL(params,2);
6631 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6632 if (!fname) {
6633 reply_nterror(req, NT_STATUS_NO_MEMORY);
6634 return;
6637 if(fsp->is_directory || fsp->fh->fd == -1) {
6639 * This is actually a SETFILEINFO on a directory
6640 * handle (returned from an NT SMB). NT5.0 seems
6641 * to do this call. JRA.
6643 if (INFO_LEVEL_IS_UNIX(info_level)) {
6644 /* Always do lstat for UNIX calls. */
6645 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6646 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6647 reply_unixerror(req,ERRDOS,ERRbadpath);
6648 return;
6650 } else {
6651 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6652 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6653 reply_unixerror(req,ERRDOS,ERRbadpath);
6654 return;
6657 } else if (fsp->print_file) {
6659 * Doing a DELETE_ON_CLOSE should cancel a print job.
6661 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6662 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6664 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6666 SSVAL(params,0,0);
6667 send_trans2_replies(conn, req, params, 2,
6668 *ppdata, 0,
6669 max_data_bytes);
6670 return;
6671 } else {
6672 reply_unixerror(req, ERRDOS, ERRbadpath);
6673 return;
6675 } else {
6677 * Original code - this is an open file.
6679 if (!check_fsp(conn, req, fsp, &current_user)) {
6680 return;
6683 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6684 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6685 reply_unixerror(req, ERRDOS, ERRbadfid);
6686 return;
6689 } else {
6690 /* set path info */
6691 if (total_params < 7) {
6692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6693 return;
6696 info_level = SVAL(params,0);
6697 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6698 total_params - 6, STR_TERMINATE,
6699 &status);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 reply_nterror(req, status);
6702 return;
6705 status = resolve_dfspath(ctx, conn,
6706 req->flags2 & FLAGS2_DFS_PATHNAMES,
6707 fname,
6708 &fname);
6709 if (!NT_STATUS_IS_OK(status)) {
6710 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6711 reply_botherror(req,
6712 NT_STATUS_PATH_NOT_COVERED,
6713 ERRSRV, ERRbadpath);
6714 return;
6716 reply_nterror(req, status);
6717 return;
6720 status = unix_convert(ctx, conn, fname, False,
6721 &fname, NULL, &sbuf);
6722 if (!NT_STATUS_IS_OK(status)) {
6723 reply_nterror(req, status);
6724 return;
6727 status = check_name(conn, fname);
6728 if (!NT_STATUS_IS_OK(status)) {
6729 reply_nterror(req, status);
6730 return;
6733 if (INFO_LEVEL_IS_UNIX(info_level)) {
6735 * For CIFS UNIX extensions the target name may not exist.
6738 /* Always do lstat for UNIX calls. */
6739 SMB_VFS_LSTAT(conn,fname,&sbuf);
6741 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6742 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6743 reply_unixerror(req, ERRDOS, ERRbadpath);
6744 return;
6748 if (!CAN_WRITE(conn)) {
6749 reply_doserror(req, ERRSRV, ERRaccess);
6750 return;
6753 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6754 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6755 return;
6758 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6759 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6761 /* Realloc the parameter size */
6762 *pparams = (char *)SMB_REALLOC(*pparams,2);
6763 if (*pparams == NULL) {
6764 reply_nterror(req, NT_STATUS_NO_MEMORY);
6765 return;
6767 params = *pparams;
6769 SSVAL(params,0,0);
6771 switch (info_level) {
6773 case SMB_INFO_STANDARD:
6775 status = smb_set_info_standard(conn,
6776 pdata,
6777 total_data,
6778 fsp,
6779 fname,
6780 &sbuf);
6781 break;
6784 case SMB_INFO_SET_EA:
6786 status = smb_info_set_ea(conn,
6787 pdata,
6788 total_data,
6789 fsp,
6790 fname);
6791 break;
6794 case SMB_SET_FILE_BASIC_INFO:
6795 case SMB_FILE_BASIC_INFORMATION:
6797 status = smb_set_file_basic_info(conn,
6798 pdata,
6799 total_data,
6800 fsp,
6801 fname,
6802 &sbuf);
6803 break;
6806 case SMB_FILE_ALLOCATION_INFORMATION:
6807 case SMB_SET_FILE_ALLOCATION_INFO:
6809 status = smb_set_file_allocation_info(conn, req,
6810 pdata,
6811 total_data,
6812 fsp,
6813 fname,
6814 &sbuf);
6815 break;
6818 case SMB_FILE_END_OF_FILE_INFORMATION:
6819 case SMB_SET_FILE_END_OF_FILE_INFO:
6821 status = smb_set_file_end_of_file_info(conn, req,
6822 pdata,
6823 total_data,
6824 fsp,
6825 fname,
6826 &sbuf);
6827 break;
6830 case SMB_FILE_DISPOSITION_INFORMATION:
6831 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6833 #if 0
6834 /* JRA - We used to just ignore this on a path ?
6835 * Shouldn't this be invalid level on a pathname
6836 * based call ?
6838 if (tran_call != TRANSACT2_SETFILEINFO) {
6839 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6841 #endif
6842 status = smb_set_file_disposition_info(conn,
6843 pdata,
6844 total_data,
6845 fsp,
6846 fname,
6847 &sbuf);
6848 break;
6851 case SMB_FILE_POSITION_INFORMATION:
6853 status = smb_file_position_information(conn,
6854 pdata,
6855 total_data,
6856 fsp);
6857 break;
6860 /* From tridge Samba4 :
6861 * MODE_INFORMATION in setfileinfo (I have no
6862 * idea what "mode information" on a file is - it takes a value of 0,
6863 * 2, 4 or 6. What could it be?).
6866 case SMB_FILE_MODE_INFORMATION:
6868 status = smb_file_mode_information(conn,
6869 pdata,
6870 total_data);
6871 break;
6875 * CIFS UNIX extensions.
6878 case SMB_SET_FILE_UNIX_BASIC:
6880 status = smb_set_file_unix_basic(conn, req,
6881 pdata,
6882 total_data,
6883 fsp,
6884 fname,
6885 &sbuf);
6886 break;
6889 case SMB_SET_FILE_UNIX_INFO2:
6891 status = smb_set_file_unix_info2(conn, req,
6892 pdata,
6893 total_data,
6894 fsp,
6895 fname,
6896 &sbuf);
6897 break;
6900 case SMB_SET_FILE_UNIX_LINK:
6902 if (tran_call != TRANSACT2_SETPATHINFO) {
6903 /* We must have a pathname for this. */
6904 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6905 return;
6907 status = smb_set_file_unix_link(conn, req, pdata,
6908 total_data, fname);
6909 break;
6912 case SMB_SET_FILE_UNIX_HLINK:
6914 if (tran_call != TRANSACT2_SETPATHINFO) {
6915 /* We must have a pathname for this. */
6916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6917 return;
6919 status = smb_set_file_unix_hlink(conn, req,
6920 pdata, total_data,
6921 fname);
6922 break;
6925 case SMB_FILE_RENAME_INFORMATION:
6927 status = smb_file_rename_information(conn, req,
6928 pdata, total_data,
6929 fsp, fname);
6930 break;
6933 #if defined(HAVE_POSIX_ACLS)
6934 case SMB_SET_POSIX_ACL:
6936 status = smb_set_posix_acl(conn,
6937 pdata,
6938 total_data,
6939 fsp,
6940 fname,
6941 &sbuf);
6942 break;
6944 #endif
6946 case SMB_SET_POSIX_LOCK:
6948 if (tran_call != TRANSACT2_SETFILEINFO) {
6949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6950 return;
6952 status = smb_set_posix_lock(conn, req,
6953 pdata, total_data, fsp);
6954 break;
6957 case SMB_POSIX_PATH_OPEN:
6959 if (tran_call != TRANSACT2_SETPATHINFO) {
6960 /* We must have a pathname for this. */
6961 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6962 return;
6965 status = smb_posix_open(conn, req,
6966 ppdata,
6967 total_data,
6968 fname,
6969 &sbuf,
6970 &data_return_size);
6971 break;
6974 case SMB_POSIX_PATH_UNLINK:
6976 if (tran_call != TRANSACT2_SETPATHINFO) {
6977 /* We must have a pathname for this. */
6978 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6979 return;
6982 status = smb_posix_unlink(conn, req,
6983 pdata,
6984 total_data,
6985 fname,
6986 &sbuf);
6987 break;
6990 default:
6991 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6992 return;
6996 if (!NT_STATUS_IS_OK(status)) {
6997 if (open_was_deferred(req->mid)) {
6998 /* We have re-scheduled this call. */
6999 return;
7001 if (blocking_lock_was_deferred(req->mid)) {
7002 /* We have re-scheduled this call. */
7003 return;
7005 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7006 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7007 ERRSRV, ERRbadpath);
7008 return;
7010 if (info_level == SMB_POSIX_PATH_OPEN) {
7011 reply_openerror(req, status);
7012 return;
7015 reply_nterror(req, status);
7016 return;
7019 SSVAL(params,0,0);
7020 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7021 max_data_bytes);
7023 return;
7026 /****************************************************************************
7027 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7028 ****************************************************************************/
7030 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7031 char **pparams, int total_params,
7032 char **ppdata, int total_data,
7033 unsigned int max_data_bytes)
7035 char *params = *pparams;
7036 char *pdata = *ppdata;
7037 char *directory = NULL;
7038 SMB_STRUCT_STAT sbuf;
7039 NTSTATUS status = NT_STATUS_OK;
7040 struct ea_list *ea_list = NULL;
7041 TALLOC_CTX *ctx = talloc_tos();
7043 if (!CAN_WRITE(conn)) {
7044 reply_doserror(req, ERRSRV, ERRaccess);
7045 return;
7048 if (total_params < 5) {
7049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7050 return;
7053 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7054 total_params - 4, STR_TERMINATE,
7055 &status);
7056 if (!NT_STATUS_IS_OK(status)) {
7057 reply_nterror(req, status);
7058 return;
7061 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7063 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7064 if (!NT_STATUS_IS_OK(status)) {
7065 reply_nterror(req, status);
7066 return;
7069 status = check_name(conn, directory);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7072 reply_nterror(req, status);
7073 return;
7076 /* Any data in this call is an EA list. */
7077 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7078 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7079 return;
7083 * OS/2 workplace shell seems to send SET_EA requests of "null"
7084 * length (4 bytes containing IVAL 4).
7085 * They seem to have no effect. Bug #3212. JRA.
7088 if (total_data != 4) {
7089 if (total_data < 10) {
7090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7091 return;
7094 if (IVAL(pdata,0) > total_data) {
7095 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7096 IVAL(pdata,0), (unsigned int)total_data));
7097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7098 return;
7101 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7102 total_data - 4);
7103 if (!ea_list) {
7104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7105 return;
7108 /* If total_data == 4 Windows doesn't care what values
7109 * are placed in that field, it just ignores them.
7110 * The System i QNTC IBM SMB client puts bad values here,
7111 * so ignore them. */
7113 status = create_directory(conn, req, directory);
7115 if (!NT_STATUS_IS_OK(status)) {
7116 reply_nterror(req, status);
7117 return;
7120 /* Try and set any given EA. */
7121 if (ea_list) {
7122 status = set_ea(conn, NULL, directory, ea_list);
7123 if (!NT_STATUS_IS_OK(status)) {
7124 reply_nterror(req, status);
7125 return;
7129 /* Realloc the parameter and data sizes */
7130 *pparams = (char *)SMB_REALLOC(*pparams,2);
7131 if(*pparams == NULL) {
7132 reply_nterror(req, NT_STATUS_NO_MEMORY);
7133 return;
7135 params = *pparams;
7137 SSVAL(params,0,0);
7139 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7141 return;
7144 /****************************************************************************
7145 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7146 We don't actually do this - we just send a null response.
7147 ****************************************************************************/
7149 static void call_trans2findnotifyfirst(connection_struct *conn,
7150 struct smb_request *req,
7151 char **pparams, int total_params,
7152 char **ppdata, int total_data,
7153 unsigned int max_data_bytes)
7155 static uint16 fnf_handle = 257;
7156 char *params = *pparams;
7157 uint16 info_level;
7159 if (total_params < 6) {
7160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7161 return;
7164 info_level = SVAL(params,4);
7165 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7167 switch (info_level) {
7168 case 1:
7169 case 2:
7170 break;
7171 default:
7172 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7173 return;
7176 /* Realloc the parameter and data sizes */
7177 *pparams = (char *)SMB_REALLOC(*pparams,6);
7178 if (*pparams == NULL) {
7179 reply_nterror(req, NT_STATUS_NO_MEMORY);
7180 return;
7182 params = *pparams;
7184 SSVAL(params,0,fnf_handle);
7185 SSVAL(params,2,0); /* No changes */
7186 SSVAL(params,4,0); /* No EA errors */
7188 fnf_handle++;
7190 if(fnf_handle == 0)
7191 fnf_handle = 257;
7193 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7195 return;
7198 /****************************************************************************
7199 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7200 changes). Currently this does nothing.
7201 ****************************************************************************/
7203 static void call_trans2findnotifynext(connection_struct *conn,
7204 struct smb_request *req,
7205 char **pparams, int total_params,
7206 char **ppdata, int total_data,
7207 unsigned int max_data_bytes)
7209 char *params = *pparams;
7211 DEBUG(3,("call_trans2findnotifynext\n"));
7213 /* Realloc the parameter and data sizes */
7214 *pparams = (char *)SMB_REALLOC(*pparams,4);
7215 if (*pparams == NULL) {
7216 reply_nterror(req, NT_STATUS_NO_MEMORY);
7217 return;
7219 params = *pparams;
7221 SSVAL(params,0,0); /* No changes */
7222 SSVAL(params,2,0); /* No EA errors */
7224 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7226 return;
7229 /****************************************************************************
7230 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7231 ****************************************************************************/
7233 static void call_trans2getdfsreferral(connection_struct *conn,
7234 struct smb_request *req,
7235 char **pparams, int total_params,
7236 char **ppdata, int total_data,
7237 unsigned int max_data_bytes)
7239 char *params = *pparams;
7240 char *pathname = NULL;
7241 int reply_size = 0;
7242 int max_referral_level;
7243 NTSTATUS status = NT_STATUS_OK;
7244 TALLOC_CTX *ctx = talloc_tos();
7246 DEBUG(10,("call_trans2getdfsreferral\n"));
7248 if (total_params < 3) {
7249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7250 return;
7253 max_referral_level = SVAL(params,0);
7255 if(!lp_host_msdfs()) {
7256 reply_doserror(req, ERRDOS, ERRbadfunc);
7257 return;
7260 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7261 total_params - 2, STR_TERMINATE);
7262 if (!pathname) {
7263 reply_nterror(req, NT_STATUS_NOT_FOUND);
7264 return;
7266 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7267 ppdata,&status)) < 0) {
7268 reply_nterror(req, status);
7269 return;
7272 SSVAL(req->inbuf, smb_flg2,
7273 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7274 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7276 return;
7279 #define LMCAT_SPL 0x53
7280 #define LMFUNC_GETJOBID 0x60
7282 /****************************************************************************
7283 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7284 ****************************************************************************/
7286 static void call_trans2ioctl(connection_struct *conn,
7287 struct smb_request *req,
7288 char **pparams, int total_params,
7289 char **ppdata, int total_data,
7290 unsigned int max_data_bytes)
7292 char *pdata = *ppdata;
7293 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7295 /* check for an invalid fid before proceeding */
7297 if (!fsp) {
7298 reply_doserror(req, ERRDOS, ERRbadfid);
7299 return;
7302 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7303 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7304 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7305 if (*ppdata == NULL) {
7306 reply_nterror(req, NT_STATUS_NO_MEMORY);
7307 return;
7309 pdata = *ppdata;
7311 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7312 CAN ACCEPT THIS IN UNICODE. JRA. */
7314 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7315 srvstr_push(pdata, req->flags2, pdata + 2,
7316 global_myname(), 15,
7317 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7318 srvstr_push(pdata, req->flags2, pdata+18,
7319 lp_servicename(SNUM(conn)), 13,
7320 STR_ASCII|STR_TERMINATE); /* Service name */
7321 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7322 max_data_bytes);
7323 return;
7326 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7327 reply_doserror(req, ERRSRV, ERRerror);
7330 /****************************************************************************
7331 Reply to a SMBfindclose (stop trans2 directory search).
7332 ****************************************************************************/
7334 void reply_findclose(struct smb_request *req)
7336 int dptr_num;
7338 START_PROFILE(SMBfindclose);
7340 if (req->wct < 1) {
7341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7342 END_PROFILE(SMBfindclose);
7343 return;
7346 dptr_num = SVALS(req->inbuf,smb_vwv0);
7348 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7350 dptr_close(&dptr_num);
7352 reply_outbuf(req, 0, 0);
7354 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7356 END_PROFILE(SMBfindclose);
7357 return;
7360 /****************************************************************************
7361 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7362 ****************************************************************************/
7364 void reply_findnclose(struct smb_request *req)
7366 int dptr_num;
7368 START_PROFILE(SMBfindnclose);
7370 if (req->wct < 1) {
7371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7372 END_PROFILE(SMBfindnclose);
7373 return;
7376 dptr_num = SVAL(req->inbuf,smb_vwv0);
7378 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7380 /* We never give out valid handles for a
7381 findnotifyfirst - so any dptr_num is ok here.
7382 Just ignore it. */
7384 reply_outbuf(req, 0, 0);
7386 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7388 END_PROFILE(SMBfindnclose);
7389 return;
7392 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7393 struct trans_state *state)
7395 if (Protocol >= PROTOCOL_NT1) {
7396 req->flags2 |= 0x40; /* IS_LONG_NAME */
7397 SSVAL(req->inbuf,smb_flg2,req->flags2);
7400 if (conn->encrypt_level == Required && !req->encrypted) {
7401 if (state->call != TRANSACT2_QFSINFO &&
7402 state->call != TRANSACT2_SETFSINFO) {
7403 DEBUG(0,("handle_trans2: encryption required "
7404 "with call 0x%x\n",
7405 (unsigned int)state->call));
7406 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7407 return;
7411 /* Now we must call the relevant TRANS2 function */
7412 switch(state->call) {
7413 case TRANSACT2_OPEN:
7415 START_PROFILE(Trans2_open);
7416 call_trans2open(conn, req,
7417 &state->param, state->total_param,
7418 &state->data, state->total_data,
7419 state->max_data_return);
7420 END_PROFILE(Trans2_open);
7421 break;
7424 case TRANSACT2_FINDFIRST:
7426 START_PROFILE(Trans2_findfirst);
7427 call_trans2findfirst(conn, req,
7428 &state->param, state->total_param,
7429 &state->data, state->total_data,
7430 state->max_data_return);
7431 END_PROFILE(Trans2_findfirst);
7432 break;
7435 case TRANSACT2_FINDNEXT:
7437 START_PROFILE(Trans2_findnext);
7438 call_trans2findnext(conn, req,
7439 &state->param, state->total_param,
7440 &state->data, state->total_data,
7441 state->max_data_return);
7442 END_PROFILE(Trans2_findnext);
7443 break;
7446 case TRANSACT2_QFSINFO:
7448 START_PROFILE(Trans2_qfsinfo);
7449 call_trans2qfsinfo(conn, req,
7450 &state->param, state->total_param,
7451 &state->data, state->total_data,
7452 state->max_data_return);
7453 END_PROFILE(Trans2_qfsinfo);
7454 break;
7457 case TRANSACT2_SETFSINFO:
7459 START_PROFILE(Trans2_setfsinfo);
7460 call_trans2setfsinfo(conn, req,
7461 &state->param, state->total_param,
7462 &state->data, state->total_data,
7463 state->max_data_return);
7464 END_PROFILE(Trans2_setfsinfo);
7465 break;
7468 case TRANSACT2_QPATHINFO:
7469 case TRANSACT2_QFILEINFO:
7471 START_PROFILE(Trans2_qpathinfo);
7472 call_trans2qfilepathinfo(conn, req, state->call,
7473 &state->param, state->total_param,
7474 &state->data, state->total_data,
7475 state->max_data_return);
7476 END_PROFILE(Trans2_qpathinfo);
7477 break;
7480 case TRANSACT2_SETPATHINFO:
7481 case TRANSACT2_SETFILEINFO:
7483 START_PROFILE(Trans2_setpathinfo);
7484 call_trans2setfilepathinfo(conn, req, state->call,
7485 &state->param, state->total_param,
7486 &state->data, state->total_data,
7487 state->max_data_return);
7488 END_PROFILE(Trans2_setpathinfo);
7489 break;
7492 case TRANSACT2_FINDNOTIFYFIRST:
7494 START_PROFILE(Trans2_findnotifyfirst);
7495 call_trans2findnotifyfirst(conn, req,
7496 &state->param, state->total_param,
7497 &state->data, state->total_data,
7498 state->max_data_return);
7499 END_PROFILE(Trans2_findnotifyfirst);
7500 break;
7503 case TRANSACT2_FINDNOTIFYNEXT:
7505 START_PROFILE(Trans2_findnotifynext);
7506 call_trans2findnotifynext(conn, req,
7507 &state->param, state->total_param,
7508 &state->data, state->total_data,
7509 state->max_data_return);
7510 END_PROFILE(Trans2_findnotifynext);
7511 break;
7514 case TRANSACT2_MKDIR:
7516 START_PROFILE(Trans2_mkdir);
7517 call_trans2mkdir(conn, req,
7518 &state->param, state->total_param,
7519 &state->data, state->total_data,
7520 state->max_data_return);
7521 END_PROFILE(Trans2_mkdir);
7522 break;
7525 case TRANSACT2_GET_DFS_REFERRAL:
7527 START_PROFILE(Trans2_get_dfs_referral);
7528 call_trans2getdfsreferral(conn, req,
7529 &state->param, state->total_param,
7530 &state->data, state->total_data,
7531 state->max_data_return);
7532 END_PROFILE(Trans2_get_dfs_referral);
7533 break;
7536 case TRANSACT2_IOCTL:
7538 START_PROFILE(Trans2_ioctl);
7539 call_trans2ioctl(conn, req,
7540 &state->param, state->total_param,
7541 &state->data, state->total_data,
7542 state->max_data_return);
7543 END_PROFILE(Trans2_ioctl);
7544 break;
7547 default:
7548 /* Error in request */
7549 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7550 reply_doserror(req, ERRSRV,ERRerror);
7554 /****************************************************************************
7555 Reply to a SMBtrans2.
7556 ****************************************************************************/
7558 void reply_trans2(struct smb_request *req)
7560 connection_struct *conn = req->conn;
7561 unsigned int dsoff;
7562 unsigned int dscnt;
7563 unsigned int psoff;
7564 unsigned int pscnt;
7565 unsigned int tran_call;
7566 unsigned int size;
7567 unsigned int av_size;
7568 struct trans_state *state;
7569 NTSTATUS result;
7571 START_PROFILE(SMBtrans2);
7573 if (req->wct < 14) {
7574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7575 END_PROFILE(SMBtrans2);
7576 return;
7579 dsoff = SVAL(req->inbuf, smb_dsoff);
7580 dscnt = SVAL(req->inbuf, smb_dscnt);
7581 psoff = SVAL(req->inbuf, smb_psoff);
7582 pscnt = SVAL(req->inbuf, smb_pscnt);
7583 tran_call = SVAL(req->inbuf, smb_setup0);
7584 size = smb_len(req->inbuf) + 4;
7585 av_size = smb_len(req->inbuf);
7587 result = allow_new_trans(conn->pending_trans, req->mid);
7588 if (!NT_STATUS_IS_OK(result)) {
7589 DEBUG(2, ("Got invalid trans2 request: %s\n",
7590 nt_errstr(result)));
7591 reply_nterror(req, result);
7592 END_PROFILE(SMBtrans2);
7593 return;
7596 if (IS_IPC(conn)) {
7597 switch (tran_call) {
7598 /* List the allowed trans2 calls on IPC$ */
7599 case TRANSACT2_OPEN:
7600 case TRANSACT2_GET_DFS_REFERRAL:
7601 case TRANSACT2_QFILEINFO:
7602 case TRANSACT2_QFSINFO:
7603 case TRANSACT2_SETFSINFO:
7604 break;
7605 default:
7606 reply_doserror(req, ERRSRV, ERRaccess);
7607 END_PROFILE(SMBtrans2);
7608 return;
7612 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7613 DEBUG(0, ("talloc failed\n"));
7614 reply_nterror(req, NT_STATUS_NO_MEMORY);
7615 END_PROFILE(SMBtrans2);
7616 return;
7619 state->cmd = SMBtrans2;
7621 state->mid = req->mid;
7622 state->vuid = req->vuid;
7623 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7624 state->setup = NULL;
7625 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7626 state->param = NULL;
7627 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7628 state->data = NULL;
7629 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7630 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7631 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7632 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7633 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7635 state->call = tran_call;
7637 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7638 is so as a sanity check */
7639 if (state->setup_count != 1) {
7641 * Need to have rc=0 for ioctl to get job id for OS/2.
7642 * Network printing will fail if function is not successful.
7643 * Similar function in reply.c will be used if protocol
7644 * is LANMAN1.0 instead of LM1.2X002.
7645 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7646 * outbuf doesn't have to be set(only job id is used).
7648 if ( (state->setup_count == 4)
7649 && (tran_call == TRANSACT2_IOCTL)
7650 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7651 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7652 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7653 } else {
7654 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7655 DEBUG(2,("Transaction is %d\n",tran_call));
7656 TALLOC_FREE(state);
7657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7658 END_PROFILE(SMBtrans2);
7659 return;
7663 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7664 goto bad_param;
7666 if (state->total_data) {
7667 /* Can't use talloc here, the core routines do realloc on the
7668 * params and data. */
7669 state->data = (char *)SMB_MALLOC(state->total_data);
7670 if (state->data == NULL) {
7671 DEBUG(0,("reply_trans2: data malloc fail for %u "
7672 "bytes !\n", (unsigned int)state->total_data));
7673 TALLOC_FREE(state);
7674 reply_nterror(req, NT_STATUS_NO_MEMORY);
7675 END_PROFILE(SMBtrans2);
7676 return;
7679 if (dscnt > state->total_data ||
7680 dsoff+dscnt < dsoff) {
7681 goto bad_param;
7684 if (dsoff > av_size ||
7685 dscnt > av_size ||
7686 dsoff+dscnt > av_size) {
7687 goto bad_param;
7690 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7693 if (state->total_param) {
7694 /* Can't use talloc here, the core routines do realloc on the
7695 * params and data. */
7696 state->param = (char *)SMB_MALLOC(state->total_param);
7697 if (state->param == NULL) {
7698 DEBUG(0,("reply_trans: param malloc fail for %u "
7699 "bytes !\n", (unsigned int)state->total_param));
7700 SAFE_FREE(state->data);
7701 TALLOC_FREE(state);
7702 reply_nterror(req, NT_STATUS_NO_MEMORY);
7703 END_PROFILE(SMBtrans2);
7704 return;
7707 if (pscnt > state->total_param ||
7708 psoff+pscnt < psoff) {
7709 goto bad_param;
7712 if (psoff > av_size ||
7713 pscnt > av_size ||
7714 psoff+pscnt > av_size) {
7715 goto bad_param;
7718 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7721 state->received_data = dscnt;
7722 state->received_param = pscnt;
7724 if ((state->received_param == state->total_param) &&
7725 (state->received_data == state->total_data)) {
7727 handle_trans2(conn, req, state);
7729 SAFE_FREE(state->data);
7730 SAFE_FREE(state->param);
7731 TALLOC_FREE(state);
7732 END_PROFILE(SMBtrans2);
7733 return;
7736 DLIST_ADD(conn->pending_trans, state);
7738 /* We need to send an interim response then receive the rest
7739 of the parameter/data bytes */
7740 reply_outbuf(req, 0, 0);
7741 show_msg((char *)req->outbuf);
7742 END_PROFILE(SMBtrans2);
7743 return;
7745 bad_param:
7747 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7748 SAFE_FREE(state->data);
7749 SAFE_FREE(state->param);
7750 TALLOC_FREE(state);
7751 END_PROFILE(SMBtrans2);
7752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7756 /****************************************************************************
7757 Reply to a SMBtranss2
7758 ****************************************************************************/
7760 void reply_transs2(struct smb_request *req)
7762 connection_struct *conn = req->conn;
7763 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7764 struct trans_state *state;
7765 unsigned int size;
7766 unsigned int av_size;
7768 START_PROFILE(SMBtranss2);
7770 show_msg((char *)req->inbuf);
7772 if (req->wct < 8) {
7773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7774 END_PROFILE(SMBtranss2);
7775 return;
7778 size = smb_len(req->inbuf)+4;
7779 av_size = smb_len(req->inbuf);
7781 for (state = conn->pending_trans; state != NULL;
7782 state = state->next) {
7783 if (state->mid == req->mid) {
7784 break;
7788 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7790 END_PROFILE(SMBtranss2);
7791 return;
7794 /* Revise state->total_param and state->total_data in case they have
7795 changed downwards */
7797 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7798 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7799 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7800 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7802 pcnt = SVAL(req->inbuf, smb_spscnt);
7803 poff = SVAL(req->inbuf, smb_spsoff);
7804 pdisp = SVAL(req->inbuf, smb_spsdisp);
7806 dcnt = SVAL(req->inbuf, smb_sdscnt);
7807 doff = SVAL(req->inbuf, smb_sdsoff);
7808 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7810 state->received_param += pcnt;
7811 state->received_data += dcnt;
7813 if ((state->received_data > state->total_data) ||
7814 (state->received_param > state->total_param))
7815 goto bad_param;
7817 if (pcnt) {
7818 if (pdisp > state->total_param ||
7819 pcnt > state->total_param ||
7820 pdisp+pcnt > state->total_param ||
7821 pdisp+pcnt < pdisp) {
7822 goto bad_param;
7825 if (poff > av_size ||
7826 pcnt > av_size ||
7827 poff+pcnt > av_size ||
7828 poff+pcnt < poff) {
7829 goto bad_param;
7832 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7833 pcnt);
7836 if (dcnt) {
7837 if (ddisp > state->total_data ||
7838 dcnt > state->total_data ||
7839 ddisp+dcnt > state->total_data ||
7840 ddisp+dcnt < ddisp) {
7841 goto bad_param;
7844 if (doff > av_size ||
7845 dcnt > av_size ||
7846 doff+dcnt > av_size ||
7847 doff+dcnt < doff) {
7848 goto bad_param;
7851 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7852 dcnt);
7855 if ((state->received_param < state->total_param) ||
7856 (state->received_data < state->total_data)) {
7857 END_PROFILE(SMBtranss2);
7858 return;
7862 * construct_reply_common will copy smb_com from inbuf to
7863 * outbuf. SMBtranss2 is wrong here.
7865 SCVAL(req->inbuf,smb_com,SMBtrans2);
7867 handle_trans2(conn, req, state);
7869 DLIST_REMOVE(conn->pending_trans, state);
7870 SAFE_FREE(state->data);
7871 SAFE_FREE(state->param);
7872 TALLOC_FREE(state);
7874 END_PROFILE(SMBtranss2);
7875 return;
7877 bad_param:
7879 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7880 DLIST_REMOVE(conn->pending_trans, state);
7881 SAFE_FREE(state->data);
7882 SAFE_FREE(state->param);
7883 TALLOC_FREE(state);
7884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7885 END_PROFILE(SMBtranss2);
7886 return;