Fix bug 7104 - "wide links" and "unix extensions" are incompatible.
[Samba.git] / source / smbd / trans2.c
blob96dcc2b40f752e06c456ab0287bc8e55442970fd
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;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
52 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
64 account sparse files.
65 ********************************************************************/
67 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
69 SMB_BIG_UINT ret;
71 if(S_ISDIR(sbuf->st_mode)) {
72 return 0;
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
77 #else
78 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
79 #endif
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char *prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 NULL
103 int i;
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
107 return true;
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 return true;
113 return false;
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
126 char *val = NULL;
127 ssize_t sizeret;
129 again:
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (!val) {
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 } else {
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 attr_size = 65536;
144 goto again;
147 if (sizeret == -1) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
154 pea->flags = 0;
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 } else {
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
161 TALLOC_FREE(val);
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
166 return NT_STATUS_OK;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
177 char *p;
178 char **names, **tmp;
179 size_t num_names;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
183 *pnames = NULL;
184 *pnum_names = 0;
185 return NT_STATUS_OK;
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
193 if (names == NULL) {
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
204 TALLOC_FREE(names);
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
210 ea_namelist_size);
211 } else {
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
213 ea_namelist_size);
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
219 else {
220 break;
224 if (sizeret == -1) {
225 TALLOC_FREE(names);
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
232 if (sizeret == 0) {
233 TALLOC_FREE(names);
234 *pnames = NULL;
235 *pnum_names = 0;
236 return NT_STATUS_OK;
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
244 TALLOC_FREE(names);
245 return NT_STATUS_INTERNAL_ERROR;
249 * count the names
251 num_names = 0;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
254 num_names += 1;
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 if (tmp == NULL) {
259 DEBUG(0, ("talloc failed\n"));
260 TALLOC_FREE(names);
261 return NT_STATUS_NO_MEMORY;
264 names = tmp;
265 num_names = 0;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
271 *pnames = names;
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
401 return 0;
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
405 return total_ea_len;
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
414 size_t total_ea_len;
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
423 break;
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
439 int ret;
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
460 } else {
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
465 #ifdef ENOATTR
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
469 unix_ea_name));
470 ret = 0;
472 #endif
473 } else {
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
479 } else {
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
487 if (ret == -1) {
488 #ifdef ENOTSUP
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
492 #endif
493 return map_nt_error_from_unix(errno);
497 return NT_STATUS_OK;
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
518 break;
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
522 return NULL;
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
525 &converted_size)) {
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
529 if (!eal->ea.name) {
530 return NULL;
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 return ea_list_head;
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
548 uint16 val_len;
549 unsigned int namelen;
550 size_t converted_size;
552 if (!eal) {
553 return NULL;
556 if (data_size < 6) {
557 return NULL;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
565 return NULL;
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
570 return NULL;
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
574 strerror(errno)));
576 if (!eal->ea.name) {
577 return NULL;
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
582 return NULL;
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
592 if (pbytes_used) {
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
599 return eal;
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
609 size_t offset = 0;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
615 if (!eal) {
616 return NULL;
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
623 return ea_list_head;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
632 fstring dos_ea_name;
633 struct ea_list *listp;
634 size_t ret = 0;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
641 if (ret) {
642 ret += 4;
645 return ret;
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
661 break;
665 if (flistp) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
669 } else {
670 /* Null entry. */
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
677 return name_list;
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
689 const char *params,
690 int paramsize,
691 const char *pdata,
692 int datasize,
693 int max_data_bytes)
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
703 int useable_space;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
714 for OS/2. */
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
720 overflow = True;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
728 return;
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
743 + 2 * 10 /* wct */
744 + alignment_offset
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
771 /* Set total params and data to be sent */
772 SSVAL(req->outbuf,smb_tprcnt,paramsize);
773 SSVAL(req->outbuf,smb_tdrcnt,datasize);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime = MIN(params_to_send,useable_space);
780 data_sent_thistime = useable_space - params_sent_thistime;
781 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
783 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req->outbuf,smb_proff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf)));
794 if(params_sent_thistime == 0)
795 SSVAL(req->outbuf,smb_prdisp,0);
796 else
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req->outbuf,smb_prdisp,pp - params);
800 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
801 if(data_sent_thistime == 0) {
802 SSVAL(req->outbuf,smb_droff,0);
803 SSVAL(req->outbuf,smb_drdisp, 0);
804 } else {
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req->outbuf, smb_droff,
808 ((smb_buf(req->outbuf)+alignment_offset)
809 - smb_base(req->outbuf))
810 + params_sent_thistime + data_alignment_offset);
811 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
814 /* Initialize the padding for alignment */
816 if (alignment_offset != 0) {
817 memset(smb_buf(req->outbuf), 0, alignment_offset);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime) {
823 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
824 params_sent_thistime);
827 /* Copy in the data bytes */
828 if(data_sent_thistime) {
829 if (data_alignment_offset != 0) {
830 memset((smb_buf(req->outbuf)+alignment_offset+
831 params_sent_thistime), 0,
832 data_alignment_offset);
834 memcpy(smb_buf(req->outbuf)+alignment_offset
835 +params_sent_thistime+data_alignment_offset,
836 pd,data_sent_thistime);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime, data_sent_thistime, useable_space));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send, data_to_send, paramsize, datasize));
844 if (overflow) {
845 error_packet_set((char *)req->outbuf,
846 ERRDOS,ERRbufferoverflow,
847 STATUS_BUFFER_OVERFLOW,
848 __LINE__,__FILE__);
851 /* Send the packet */
852 show_msg((char *)req->outbuf);
853 if (!srv_send_smb(smbd_server_fd(),
854 (char *)req->outbuf,
855 IS_CONN_ENCRYPTED(conn)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req->outbuf);
860 pp += params_sent_thistime;
861 pd += data_sent_thistime;
863 params_to_send -= params_sent_thistime;
864 data_to_send -= data_sent_thistime;
866 /* Sanity check */
867 if(params_to_send < 0 || data_to_send < 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send, data_to_send));
870 return;
874 return;
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct *conn,
882 struct smb_request *req,
883 char **pparams, int total_params,
884 char **ppdata, int total_data,
885 unsigned int max_data_bytes)
887 char *params = *pparams;
888 char *pdata = *ppdata;
889 int deny_mode;
890 int32 open_attr;
891 bool oplock_request;
892 #if 0
893 bool return_additional_info;
894 int16 open_sattr;
895 time_t open_time;
896 #endif
897 int open_ofun;
898 uint32 open_size;
899 char *pname;
900 char *fname = NULL;
901 SMB_OFF_T size=0;
902 int fattr=0,mtime=0;
903 SMB_INO_T inode = 0;
904 SMB_STRUCT_STAT sbuf;
905 int smb_action = 0;
906 files_struct *fsp;
907 struct ea_list *ea_list = NULL;
908 uint16 flags = 0;
909 NTSTATUS status;
910 uint32 access_mask;
911 uint32 share_mode;
912 uint32 create_disposition;
913 uint32 create_options = 0;
914 TALLOC_CTX *ctx = talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params < 29) {
921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
922 return;
925 flags = SVAL(params, 0);
926 deny_mode = SVAL(params, 2);
927 open_attr = SVAL(params,6);
928 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
929 if (oplock_request) {
930 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
933 #if 0
934 return_additional_info = BITSETW(params,0);
935 open_sattr = SVAL(params, 4);
936 open_time = make_unix_date3(params+8);
937 #endif
938 open_ofun = SVAL(params,12);
939 open_size = IVAL(params,14);
940 pname = &params[28];
942 if (IS_IPC(conn)) {
943 reply_doserror(req, ERRSRV, ERRaccess);
944 return;
947 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
948 total_params - 28, STR_TERMINATE,
949 &status);
950 if (!NT_STATUS_IS_OK(status)) {
951 reply_nterror(req, status);
952 return;
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
957 (unsigned int)open_ofun, open_size));
959 if (open_ofun == 0) {
960 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
961 return;
964 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
965 &access_mask,
966 &share_mode,
967 &create_disposition,
968 &create_options)) {
969 reply_doserror(req, ERRDOS, ERRbadaccess);
970 return;
973 /* Any data in this call is an EA list. */
974 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
975 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
976 return;
979 if (total_data != 4) {
980 if (total_data < 10) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 return;
985 if (IVAL(pdata,0) > total_data) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata,0), (unsigned int)total_data));
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 return;
992 ea_list = read_ea_list(talloc_tos(), pdata + 4,
993 total_data - 4);
994 if (!ea_list) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 return;
998 } else if (IVAL(pdata,0) != 4) {
999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1000 return;
1003 status = create_file(conn, /* conn */
1004 req, /* req */
1005 0, /* root_dir_fid */
1006 fname, /* fname */
1007 access_mask, /* access_mask */
1008 share_mode, /* share_access */
1009 create_disposition, /* create_disposition*/
1010 create_options, /* create_options */
1011 open_attr, /* file_attributes */
1012 oplock_request, /* oplock_request */
1013 open_size, /* allocation_size */
1014 NULL, /* sd */
1015 ea_list, /* ea_list */
1016 &fsp, /* result */
1017 &smb_action, /* pinfo */
1018 &sbuf); /* psbuf */
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (open_was_deferred(req->mid)) {
1022 /* We have re-scheduled this call. */
1023 return;
1025 reply_openerror(req, status);
1026 return;
1029 size = get_file_size(sbuf);
1030 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1031 mtime = sbuf.st_mtime;
1032 inode = sbuf.st_ino;
1033 if (fattr & aDIR) {
1034 close_file(fsp,ERROR_CLOSE);
1035 reply_doserror(req, ERRDOS,ERRnoaccess);
1036 return;
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1041 if(*pparams == NULL ) {
1042 reply_nterror(req, NT_STATUS_NO_MEMORY);
1043 return;
1045 params = *pparams;
1047 SSVAL(params,0,fsp->fnum);
1048 SSVAL(params,2,fattr);
1049 srv_put_dos_date2(params,4, mtime);
1050 SIVAL(params,8, (uint32)size);
1051 SSVAL(params,12,deny_mode);
1052 SSVAL(params,14,0); /* open_type - file or directory. */
1053 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1059 SSVAL(params,18,smb_action);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params,20,inode);
1065 SSVAL(params,24,0); /* Padding. */
1066 if (flags & 8) {
1067 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1068 SIVAL(params, 26, ea_size);
1069 } else {
1070 SIVAL(params, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct *conn,
1085 const char *str,
1086 const char *mask)
1088 if (mask[0] == '.' && mask[1] == 0)
1089 return False;
1090 if (dptr_has_wild(conn->dirptr)) {
1091 return False;
1093 if (conn->case_sensitive)
1094 return strcmp(str,mask)==0;
1095 else
1096 return StrCaseCmp(str,mask) == 0;
1099 /****************************************************************************
1100 Return the filetype for UNIX extensions.
1101 ****************************************************************************/
1103 static uint32 unix_filetype(mode_t mode)
1105 if(S_ISREG(mode))
1106 return UNIX_TYPE_FILE;
1107 else if(S_ISDIR(mode))
1108 return UNIX_TYPE_DIR;
1109 #ifdef S_ISLNK
1110 else if(S_ISLNK(mode))
1111 return UNIX_TYPE_SYMLINK;
1112 #endif
1113 #ifdef S_ISCHR
1114 else if(S_ISCHR(mode))
1115 return UNIX_TYPE_CHARDEV;
1116 #endif
1117 #ifdef S_ISBLK
1118 else if(S_ISBLK(mode))
1119 return UNIX_TYPE_BLKDEV;
1120 #endif
1121 #ifdef S_ISFIFO
1122 else if(S_ISFIFO(mode))
1123 return UNIX_TYPE_FIFO;
1124 #endif
1125 #ifdef S_ISSOCK
1126 else if(S_ISSOCK(mode))
1127 return UNIX_TYPE_SOCKET;
1128 #endif
1130 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1131 return UNIX_TYPE_UNKNOWN;
1134 /****************************************************************************
1135 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1136 ****************************************************************************/
1138 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1140 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1141 SMB_STRUCT_STAT *psbuf,
1142 uint32 perms,
1143 enum perm_type ptype,
1144 mode_t *ret_perms)
1146 mode_t ret = 0;
1148 if (perms == SMB_MODE_NO_CHANGE) {
1149 if (!VALID_STAT(*psbuf)) {
1150 return NT_STATUS_INVALID_PARAMETER;
1151 } else {
1152 *ret_perms = psbuf->st_mode;
1153 return NT_STATUS_OK;
1157 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1158 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1159 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1160 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1161 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1162 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1163 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1164 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1165 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1166 #ifdef S_ISVTX
1167 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1168 #endif
1169 #ifdef S_ISGID
1170 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1171 #endif
1172 #ifdef S_ISUID
1173 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1174 #endif
1176 switch (ptype) {
1177 case PERM_NEW_FILE:
1178 /* Apply mode mask */
1179 ret &= lp_create_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_create_mode(SNUM(conn));
1182 break;
1183 case PERM_NEW_DIR:
1184 ret &= lp_dir_mask(SNUM(conn));
1185 /* Add in force bits */
1186 ret |= lp_force_dir_mode(SNUM(conn));
1187 break;
1188 case PERM_EXISTING_FILE:
1189 /* Apply mode mask */
1190 ret &= lp_security_mask(SNUM(conn));
1191 /* Add in force bits */
1192 ret |= lp_force_security_mode(SNUM(conn));
1193 break;
1194 case PERM_EXISTING_DIR:
1195 /* Apply mode mask */
1196 ret &= lp_dir_security_mask(SNUM(conn));
1197 /* Add in force bits */
1198 ret |= lp_force_dir_security_mode(SNUM(conn));
1199 break;
1202 *ret_perms = ret;
1203 return NT_STATUS_OK;
1206 /****************************************************************************
1207 Needed to show the msdfs symlinks as directories. Modifies psbuf
1208 to be a directory if it's a msdfs link.
1209 ****************************************************************************/
1211 static bool check_msdfs_link(connection_struct *conn,
1212 const char *pathname,
1213 SMB_STRUCT_STAT *psbuf)
1215 int saved_errno = errno;
1216 if(lp_host_msdfs() &&
1217 lp_msdfs_root(SNUM(conn)) &&
1218 is_msdfs_link(conn, pathname, psbuf)) {
1220 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1221 "as a directory\n",
1222 pathname));
1223 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1224 errno = saved_errno;
1225 return true;
1227 errno = saved_errno;
1228 return false;
1232 /****************************************************************************
1233 Get a level dependent lanman2 dir entry.
1234 ****************************************************************************/
1236 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1237 connection_struct *conn,
1238 uint16 flags2,
1239 const char *path_mask,
1240 uint32 dirtype,
1241 int info_level,
1242 int requires_resume_key,
1243 bool dont_descend,
1244 bool ask_sharemode,
1245 char **ppdata,
1246 char *base_data,
1247 char *end_data,
1248 int space_remaining,
1249 bool *out_of_space,
1250 bool *got_exact_match,
1251 int *last_entry_off,
1252 struct ea_list *name_list)
1254 const char *dname;
1255 bool found = False;
1256 SMB_STRUCT_STAT sbuf;
1257 const char *mask = NULL;
1258 char *pathreal = NULL;
1259 const char *fname = NULL;
1260 char *p, *q, *pdata = *ppdata;
1261 uint32 reskey=0;
1262 long prev_dirpos=0;
1263 uint32 mode=0;
1264 SMB_OFF_T file_size = 0;
1265 SMB_BIG_UINT allocation_size = 0;
1266 uint32 len;
1267 struct timespec mdate_ts, adate_ts, create_date_ts;
1268 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1269 char *nameptr;
1270 char *last_entry_ptr;
1271 bool was_8_3;
1272 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1273 bool check_mangled_names = lp_manglednames(conn->params);
1274 char mangled_name[13]; /* mangled 8.3 name. */
1276 *out_of_space = False;
1277 *got_exact_match = False;
1279 ZERO_STRUCT(mdate_ts);
1280 ZERO_STRUCT(adate_ts);
1281 ZERO_STRUCT(create_date_ts);
1283 if (!conn->dirptr) {
1284 return(False);
1287 p = strrchr_m(path_mask,'/');
1288 if(p != NULL) {
1289 if(p[1] == '\0') {
1290 mask = talloc_strdup(ctx,"*.*");
1291 } else {
1292 mask = p+1;
1294 } else {
1295 mask = path_mask;
1298 while (!found) {
1299 bool got_match;
1300 bool ms_dfs_link = False;
1302 /* Needed if we run out of space */
1303 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1304 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1307 * Due to bugs in NT client redirectors we are not using
1308 * resume keys any more - set them to zero.
1309 * Check out the related comments in findfirst/findnext.
1310 * JRA.
1313 reskey = 0;
1315 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1316 (long)conn->dirptr,curr_dirpos));
1318 if (!dname) {
1319 return(False);
1323 * fname may get mangled, dname is never mangled.
1324 * Whenever we're accessing the filesystem we use
1325 * pathreal which is composed from dname.
1328 pathreal = NULL;
1329 fname = dname;
1331 /* Mangle fname if it's an illegal name. */
1332 if (mangle_must_mangle(dname,conn->params)) {
1333 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1334 continue; /* Error - couldn't mangle. */
1336 fname = mangled_name;
1339 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1340 got_match = mask_match(fname, mask, conn->case_sensitive);
1343 if(!got_match && check_mangled_names &&
1344 !mangle_is_8_3(fname, False, conn->params)) {
1346 * It turns out that NT matches wildcards against
1347 * both long *and* short names. This may explain some
1348 * of the wildcard wierdness from old DOS clients
1349 * that some people have been seeing.... JRA.
1351 /* Force the mangling into 8.3. */
1352 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1353 continue; /* Error - couldn't mangle. */
1356 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1357 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1361 if (got_match) {
1362 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1364 if (dont_descend && !isdots) {
1365 continue;
1368 if (needslash) {
1369 pathreal = NULL;
1370 pathreal = talloc_asprintf(ctx,
1371 "%s/%s",
1372 conn->dirpath,
1373 dname);
1374 } else {
1375 pathreal = talloc_asprintf(ctx,
1376 "%s%s",
1377 conn->dirpath,
1378 dname);
1381 if (!pathreal) {
1382 return False;
1385 if (INFO_LEVEL_IS_UNIX(info_level)) {
1386 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1387 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1388 pathreal,strerror(errno)));
1389 TALLOC_FREE(pathreal);
1390 continue;
1392 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1393 /* Needed to show the msdfs symlinks as
1394 * directories */
1396 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1397 if (!ms_dfs_link) {
1398 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1399 pathreal,strerror(errno)));
1400 TALLOC_FREE(pathreal);
1401 continue;
1405 if (ms_dfs_link) {
1406 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1407 } else {
1408 mode = dos_mode(conn,pathreal,&sbuf);
1411 if (!dir_check_ftype(conn,mode,dirtype)) {
1412 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1413 TALLOC_FREE(pathreal);
1414 continue;
1417 if (!(mode & aDIR)) {
1418 file_size = get_file_size(sbuf);
1420 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1422 mdate_ts = get_mtimespec(&sbuf);
1423 adate_ts = get_atimespec(&sbuf);
1424 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1426 if (ask_sharemode) {
1427 struct timespec write_time_ts;
1428 struct file_id fileid;
1430 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1431 get_file_infos(fileid, NULL, &write_time_ts);
1432 if (!null_timespec(write_time_ts)) {
1433 mdate_ts = write_time_ts;
1437 if (lp_dos_filetime_resolution(SNUM(conn))) {
1438 dos_filetime_timespec(&create_date_ts);
1439 dos_filetime_timespec(&mdate_ts);
1440 dos_filetime_timespec(&adate_ts);
1443 create_date = convert_timespec_to_time_t(create_date_ts);
1444 mdate = convert_timespec_to_time_t(mdate_ts);
1445 adate = convert_timespec_to_time_t(adate_ts);
1447 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1449 found = True;
1451 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1455 p = pdata;
1456 last_entry_ptr = p;
1458 switch (info_level) {
1459 case SMB_FIND_INFO_STANDARD:
1460 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1461 if(requires_resume_key) {
1462 SIVAL(p,0,reskey);
1463 p += 4;
1465 srv_put_dos_date2(p,0,create_date);
1466 srv_put_dos_date2(p,4,adate);
1467 srv_put_dos_date2(p,8,mdate);
1468 SIVAL(p,12,(uint32)file_size);
1469 SIVAL(p,16,(uint32)allocation_size);
1470 SSVAL(p,20,mode);
1471 p += 23;
1472 nameptr = p;
1473 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1474 p += ucs2_align(base_data, p, 0);
1476 len = srvstr_push(base_data, flags2, p,
1477 fname, PTR_DIFF(end_data, p),
1478 STR_TERMINATE);
1479 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1480 if (len > 2) {
1481 SCVAL(nameptr, -1, len - 2);
1482 } else {
1483 SCVAL(nameptr, -1, 0);
1485 } else {
1486 if (len > 1) {
1487 SCVAL(nameptr, -1, len - 1);
1488 } else {
1489 SCVAL(nameptr, -1, 0);
1492 p += len;
1493 break;
1495 case SMB_FIND_EA_SIZE:
1496 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1497 if(requires_resume_key) {
1498 SIVAL(p,0,reskey);
1499 p += 4;
1501 srv_put_dos_date2(p,0,create_date);
1502 srv_put_dos_date2(p,4,adate);
1503 srv_put_dos_date2(p,8,mdate);
1504 SIVAL(p,12,(uint32)file_size);
1505 SIVAL(p,16,(uint32)allocation_size);
1506 SSVAL(p,20,mode);
1508 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1509 SIVAL(p,22,ea_size); /* Extended attributes */
1511 p += 27;
1512 nameptr = p - 1;
1513 len = srvstr_push(base_data, flags2,
1514 p, fname, PTR_DIFF(end_data, p),
1515 STR_TERMINATE | STR_NOALIGN);
1516 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1517 if (len > 2) {
1518 len -= 2;
1519 } else {
1520 len = 0;
1522 } else {
1523 if (len > 1) {
1524 len -= 1;
1525 } else {
1526 len = 0;
1529 SCVAL(nameptr,0,len);
1530 p += len;
1531 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1532 break;
1534 case SMB_FIND_EA_LIST:
1536 struct ea_list *file_list = NULL;
1537 size_t ea_len = 0;
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1540 if (!name_list) {
1541 return False;
1543 if(requires_resume_key) {
1544 SIVAL(p,0,reskey);
1545 p += 4;
1547 srv_put_dos_date2(p,0,create_date);
1548 srv_put_dos_date2(p,4,adate);
1549 srv_put_dos_date2(p,8,mdate);
1550 SIVAL(p,12,(uint32)file_size);
1551 SIVAL(p,16,(uint32)allocation_size);
1552 SSVAL(p,20,mode);
1553 p += 22; /* p now points to the EA area. */
1555 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1556 name_list = ea_list_union(name_list, file_list, &ea_len);
1558 /* We need to determine if this entry will fit in the space available. */
1559 /* Max string size is 255 bytes. */
1560 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1561 /* Move the dirptr back to prev_dirpos */
1562 dptr_SeekDir(conn->dirptr, prev_dirpos);
1563 *out_of_space = True;
1564 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1565 return False; /* Not finished - just out of space */
1568 /* Push the ea_data followed by the name. */
1569 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1570 nameptr = p;
1571 len = srvstr_push(base_data, flags2,
1572 p + 1, fname, PTR_DIFF(end_data, p+1),
1573 STR_TERMINATE | STR_NOALIGN);
1574 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1575 if (len > 2) {
1576 len -= 2;
1577 } else {
1578 len = 0;
1580 } else {
1581 if (len > 1) {
1582 len -= 1;
1583 } else {
1584 len = 0;
1587 SCVAL(nameptr,0,len);
1588 p += len + 1;
1589 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1590 break;
1593 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1594 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1595 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1596 p += 4;
1597 SIVAL(p,0,reskey); p += 4;
1598 put_long_date_timespec(p,create_date_ts); p += 8;
1599 put_long_date_timespec(p,adate_ts); p += 8;
1600 put_long_date_timespec(p,mdate_ts); p += 8;
1601 put_long_date_timespec(p,mdate_ts); p += 8;
1602 SOFF_T(p,0,file_size); p += 8;
1603 SOFF_T(p,0,allocation_size); p += 8;
1604 SIVAL(p,0,mode); p += 4;
1605 q = p; p += 4; /* q is placeholder for name length. */
1607 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1608 SIVAL(p,0,ea_size); /* Extended attributes */
1609 p += 4;
1611 /* Clear the short name buffer. This is
1612 * IMPORTANT as not doing so will trigger
1613 * a Win2k client bug. JRA.
1615 if (!was_8_3 && check_mangled_names) {
1616 if (!name_to_8_3(fname,mangled_name,True,
1617 conn->params)) {
1618 /* Error - mangle failed ! */
1619 memset(mangled_name,'\0',12);
1621 mangled_name[12] = 0;
1622 len = srvstr_push(base_data, flags2,
1623 p+2, mangled_name, 24,
1624 STR_UPPER|STR_UNICODE);
1625 if (len < 24) {
1626 memset(p + 2 + len,'\0',24 - len);
1628 SSVAL(p, 0, len);
1629 } else {
1630 memset(p,'\0',26);
1632 p += 2 + 24;
1633 len = srvstr_push(base_data, flags2, p,
1634 fname, PTR_DIFF(end_data, p),
1635 STR_TERMINATE_ASCII);
1636 SIVAL(q,0,len);
1637 p += len;
1638 SIVAL(p,0,0); /* Ensure any padding is null. */
1639 len = PTR_DIFF(p, pdata);
1640 len = (len + 3) & ~3;
1641 SIVAL(pdata,0,len);
1642 p = pdata + len;
1643 break;
1645 case SMB_FIND_FILE_DIRECTORY_INFO:
1646 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1647 p += 4;
1648 SIVAL(p,0,reskey); p += 4;
1649 put_long_date_timespec(p,create_date_ts); p += 8;
1650 put_long_date_timespec(p,adate_ts); p += 8;
1651 put_long_date_timespec(p,mdate_ts); p += 8;
1652 put_long_date_timespec(p,mdate_ts); p += 8;
1653 SOFF_T(p,0,file_size); p += 8;
1654 SOFF_T(p,0,allocation_size); p += 8;
1655 SIVAL(p,0,mode); p += 4;
1656 len = srvstr_push(base_data, flags2,
1657 p + 4, fname, PTR_DIFF(end_data, p+4),
1658 STR_TERMINATE_ASCII);
1659 SIVAL(p,0,len);
1660 p += 4 + len;
1661 SIVAL(p,0,0); /* Ensure any padding is null. */
1662 len = PTR_DIFF(p, pdata);
1663 len = (len + 3) & ~3;
1664 SIVAL(pdata,0,len);
1665 p = pdata + len;
1666 break;
1668 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1669 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1670 p += 4;
1671 SIVAL(p,0,reskey); p += 4;
1672 put_long_date_timespec(p,create_date_ts); p += 8;
1673 put_long_date_timespec(p,adate_ts); p += 8;
1674 put_long_date_timespec(p,mdate_ts); p += 8;
1675 put_long_date_timespec(p,mdate_ts); p += 8;
1676 SOFF_T(p,0,file_size); p += 8;
1677 SOFF_T(p,0,allocation_size); p += 8;
1678 SIVAL(p,0,mode); p += 4;
1679 q = p; p += 4; /* q is placeholder for name length. */
1681 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1682 SIVAL(p,0,ea_size); /* Extended attributes */
1683 p +=4;
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE_ASCII);
1688 SIVAL(q, 0, len);
1689 p += len;
1691 SIVAL(p,0,0); /* Ensure any padding is null. */
1692 len = PTR_DIFF(p, pdata);
1693 len = (len + 3) & ~3;
1694 SIVAL(pdata,0,len);
1695 p = pdata + len;
1696 break;
1698 case SMB_FIND_FILE_NAMES_INFO:
1699 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1700 p += 4;
1701 SIVAL(p,0,reskey); p += 4;
1702 p += 4;
1703 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1704 acl on a dir (tridge) */
1705 len = srvstr_push(base_data, flags2, p,
1706 fname, PTR_DIFF(end_data, p),
1707 STR_TERMINATE_ASCII);
1708 SIVAL(p, -4, len);
1709 p += len;
1710 SIVAL(p,0,0); /* Ensure any padding is null. */
1711 len = PTR_DIFF(p, pdata);
1712 len = (len + 3) & ~3;
1713 SIVAL(pdata,0,len);
1714 p = pdata + len;
1715 break;
1717 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1718 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1719 p += 4;
1720 SIVAL(p,0,reskey); p += 4;
1721 put_long_date_timespec(p,create_date_ts); p += 8;
1722 put_long_date_timespec(p,adate_ts); p += 8;
1723 put_long_date_timespec(p,mdate_ts); p += 8;
1724 put_long_date_timespec(p,mdate_ts); p += 8;
1725 SOFF_T(p,0,file_size); p += 8;
1726 SOFF_T(p,0,allocation_size); p += 8;
1727 SIVAL(p,0,mode); p += 4;
1728 q = p; p += 4; /* q is placeholder for name length. */
1730 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1731 SIVAL(p,0,ea_size); /* Extended attributes */
1732 p +=4;
1734 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1735 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1736 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1737 len = srvstr_push(base_data, flags2, p,
1738 fname, PTR_DIFF(end_data, p),
1739 STR_TERMINATE_ASCII);
1740 SIVAL(q, 0, len);
1741 p += len;
1742 SIVAL(p,0,0); /* Ensure any padding is null. */
1743 len = PTR_DIFF(p, pdata);
1744 len = (len + 3) & ~3;
1745 SIVAL(pdata,0,len);
1746 p = pdata + len;
1747 break;
1749 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1750 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1751 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1752 p += 4;
1753 SIVAL(p,0,reskey); p += 4;
1754 put_long_date_timespec(p,create_date_ts); p += 8;
1755 put_long_date_timespec(p,adate_ts); p += 8;
1756 put_long_date_timespec(p,mdate_ts); p += 8;
1757 put_long_date_timespec(p,mdate_ts); p += 8;
1758 SOFF_T(p,0,file_size); p += 8;
1759 SOFF_T(p,0,allocation_size); p += 8;
1760 SIVAL(p,0,mode); p += 4;
1761 q = p; p += 4; /* q is placeholder for name length */
1763 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1764 SIVAL(p,0,ea_size); /* Extended attributes */
1765 p +=4;
1767 /* Clear the short name buffer. This is
1768 * IMPORTANT as not doing so will trigger
1769 * a Win2k client bug. JRA.
1771 if (!was_8_3 && check_mangled_names) {
1772 if (!name_to_8_3(fname,mangled_name,True,
1773 conn->params)) {
1774 /* Error - mangle failed ! */
1775 memset(mangled_name,'\0',12);
1777 mangled_name[12] = 0;
1778 len = srvstr_push(base_data, flags2,
1779 p+2, mangled_name, 24,
1780 STR_UPPER|STR_UNICODE);
1781 SSVAL(p, 0, len);
1782 if (len < 24) {
1783 memset(p + 2 + len,'\0',24 - len);
1785 SSVAL(p, 0, len);
1786 } else {
1787 memset(p,'\0',26);
1789 p += 26;
1790 SSVAL(p,0,0); p += 2; /* Reserved ? */
1791 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1792 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1793 len = srvstr_push(base_data, flags2, p,
1794 fname, PTR_DIFF(end_data, p),
1795 STR_TERMINATE_ASCII);
1796 SIVAL(q,0,len);
1797 p += len;
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1799 len = PTR_DIFF(p, pdata);
1800 len = (len + 3) & ~3;
1801 SIVAL(pdata,0,len);
1802 p = pdata + len;
1803 break;
1805 /* CIFS UNIX Extension. */
1807 case SMB_FIND_FILE_UNIX:
1808 case SMB_FIND_FILE_UNIX_INFO2:
1809 p+= 4;
1810 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1812 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1814 if (info_level == SMB_FIND_FILE_UNIX) {
1815 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1816 p = store_file_unix_basic(conn, p,
1817 NULL, &sbuf);
1818 len = srvstr_push(base_data, flags2, p,
1819 fname, PTR_DIFF(end_data, p),
1820 STR_TERMINATE);
1821 } else {
1822 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1823 p = store_file_unix_basic_info2(conn, p,
1824 NULL, &sbuf);
1825 nameptr = p;
1826 p += 4;
1827 len = srvstr_push(base_data, flags2, p, fname,
1828 PTR_DIFF(end_data, p), 0);
1829 SIVAL(nameptr, 0, len);
1832 p += len;
1833 SIVAL(p,0,0); /* Ensure any padding is null. */
1835 len = PTR_DIFF(p, pdata);
1836 len = (len + 3) & ~3;
1837 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1838 p = pdata + len;
1839 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1841 break;
1843 default:
1844 return(False);
1848 if (PTR_DIFF(p,pdata) > space_remaining) {
1849 /* Move the dirptr back to prev_dirpos */
1850 dptr_SeekDir(conn->dirptr, prev_dirpos);
1851 *out_of_space = True;
1852 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1853 return False; /* Not finished - just out of space */
1856 /* Setup the last entry pointer, as an offset from base_data */
1857 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1858 /* Advance the data pointer to the next slot */
1859 *ppdata = p;
1861 return(found);
1864 /****************************************************************************
1865 Reply to a TRANS2_FINDFIRST.
1866 ****************************************************************************/
1868 static void call_trans2findfirst(connection_struct *conn,
1869 struct smb_request *req,
1870 char **pparams, int total_params,
1871 char **ppdata, int total_data,
1872 unsigned int max_data_bytes)
1874 /* We must be careful here that we don't return more than the
1875 allowed number of data bytes. If this means returning fewer than
1876 maxentries then so be it. We assume that the redirector has
1877 enough room for the fixed number of parameter bytes it has
1878 requested. */
1879 char *params = *pparams;
1880 char *pdata = *ppdata;
1881 char *data_end;
1882 uint32 dirtype;
1883 int maxentries;
1884 uint16 findfirst_flags;
1885 bool close_after_first;
1886 bool close_if_end;
1887 bool requires_resume_key;
1888 int info_level;
1889 char *directory = NULL;
1890 char *mask = NULL;
1891 char *p;
1892 int last_entry_off=0;
1893 int dptr_num = -1;
1894 int numentries = 0;
1895 int i;
1896 bool finished = False;
1897 bool dont_descend = False;
1898 bool out_of_space = False;
1899 int space_remaining;
1900 bool mask_contains_wcard = False;
1901 SMB_STRUCT_STAT sbuf;
1902 struct ea_list *ea_list = NULL;
1903 NTSTATUS ntstatus = NT_STATUS_OK;
1904 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1905 TALLOC_CTX *ctx = talloc_tos();
1907 if (total_params < 13) {
1908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1909 return;
1912 dirtype = SVAL(params,0);
1913 maxentries = SVAL(params,2);
1914 findfirst_flags = SVAL(params,4);
1915 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1916 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1917 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1918 info_level = SVAL(params,6);
1920 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1921 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1922 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1923 info_level, max_data_bytes));
1925 if (!maxentries) {
1926 /* W2K3 seems to treat zero as 1. */
1927 maxentries = 1;
1930 switch (info_level) {
1931 case SMB_FIND_INFO_STANDARD:
1932 case SMB_FIND_EA_SIZE:
1933 case SMB_FIND_EA_LIST:
1934 case SMB_FIND_FILE_DIRECTORY_INFO:
1935 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1936 case SMB_FIND_FILE_NAMES_INFO:
1937 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1938 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1939 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1940 break;
1941 case SMB_FIND_FILE_UNIX:
1942 case SMB_FIND_FILE_UNIX_INFO2:
1943 /* Always use filesystem for UNIX mtime query. */
1944 ask_sharemode = false;
1945 if (!lp_unix_extensions()) {
1946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1947 return;
1949 break;
1950 default:
1951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1952 return;
1955 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1956 params+12, total_params - 12,
1957 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1958 if (!NT_STATUS_IS_OK(ntstatus)) {
1959 reply_nterror(req, ntstatus);
1960 return;
1963 ntstatus = resolve_dfspath_wcard(ctx, conn,
1964 req->flags2 & FLAGS2_DFS_PATHNAMES,
1965 directory,
1966 &directory,
1967 &mask_contains_wcard);
1968 if (!NT_STATUS_IS_OK(ntstatus)) {
1969 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1970 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1971 ERRSRV, ERRbadpath);
1972 return;
1974 reply_nterror(req, ntstatus);
1975 return;
1978 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1979 if (!NT_STATUS_IS_OK(ntstatus)) {
1980 reply_nterror(req, ntstatus);
1981 return;
1984 ntstatus = check_name(conn, directory);
1985 if (!NT_STATUS_IS_OK(ntstatus)) {
1986 reply_nterror(req, ntstatus);
1987 return;
1990 p = strrchr_m(directory,'/');
1991 if(p == NULL) {
1992 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1993 if((directory[0] == '.') && (directory[1] == '\0')) {
1994 mask = talloc_strdup(ctx,"*");
1995 if (!mask) {
1996 reply_nterror(req, NT_STATUS_NO_MEMORY);
1997 return;
1999 mask_contains_wcard = True;
2001 directory = talloc_strdup(talloc_tos(), "./");
2002 if (!directory) {
2003 reply_nterror(req, NT_STATUS_NO_MEMORY);
2004 return;
2006 } else {
2007 *p = 0;
2010 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2012 if (info_level == SMB_FIND_EA_LIST) {
2013 uint32 ea_size;
2015 if (total_data < 4) {
2016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2017 return;
2020 ea_size = IVAL(pdata,0);
2021 if (ea_size != total_data) {
2022 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2023 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2025 return;
2028 if (!lp_ea_support(SNUM(conn))) {
2029 reply_doserror(req, ERRDOS, ERReasnotsupported);
2030 return;
2033 /* Pull out the list of names. */
2034 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2035 if (!ea_list) {
2036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2037 return;
2041 *ppdata = (char *)SMB_REALLOC(
2042 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2043 if(*ppdata == NULL ) {
2044 reply_nterror(req, NT_STATUS_NO_MEMORY);
2045 return;
2047 pdata = *ppdata;
2048 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2050 /* Realloc the params space */
2051 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2052 if (*pparams == NULL) {
2053 reply_nterror(req, NT_STATUS_NO_MEMORY);
2054 return;
2056 params = *pparams;
2058 /* Save the wildcard match and attribs we are using on this directory -
2059 needed as lanman2 assumes these are being saved between calls */
2061 ntstatus = dptr_create(conn,
2062 directory,
2063 False,
2064 True,
2065 req->smbpid,
2066 mask,
2067 mask_contains_wcard,
2068 dirtype,
2069 &conn->dirptr);
2071 if (!NT_STATUS_IS_OK(ntstatus)) {
2072 reply_nterror(req, ntstatus);
2073 return;
2076 dptr_num = dptr_dnum(conn->dirptr);
2077 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2079 /* We don't need to check for VOL here as this is returned by
2080 a different TRANS2 call. */
2082 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2083 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2084 dont_descend = True;
2086 p = pdata;
2087 space_remaining = max_data_bytes;
2088 out_of_space = False;
2090 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2091 bool got_exact_match = False;
2093 /* this is a heuristic to avoid seeking the dirptr except when
2094 absolutely necessary. It allows for a filename of about 40 chars */
2095 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2096 out_of_space = True;
2097 finished = False;
2098 } else {
2099 finished = !get_lanman2_dir_entry(ctx,
2100 conn,
2101 req->flags2,
2102 mask,dirtype,info_level,
2103 requires_resume_key,dont_descend,
2104 ask_sharemode,
2105 &p,pdata,data_end,
2106 space_remaining, &out_of_space,
2107 &got_exact_match,
2108 &last_entry_off, ea_list);
2111 if (finished && out_of_space)
2112 finished = False;
2114 if (!finished && !out_of_space)
2115 numentries++;
2118 * As an optimisation if we know we aren't looking
2119 * for a wildcard name (ie. the name matches the wildcard exactly)
2120 * then we can finish on any (first) match.
2121 * This speeds up large directory searches. JRA.
2124 if(got_exact_match)
2125 finished = True;
2127 /* Ensure space_remaining never goes -ve. */
2128 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2129 space_remaining = 0;
2130 out_of_space = true;
2131 } else {
2132 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2136 /* Check if we can close the dirptr */
2137 if(close_after_first || (finished && close_if_end)) {
2138 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2139 dptr_close(&dptr_num);
2143 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2144 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2145 * the protocol level is less than NT1. Tested with smbclient. JRA.
2146 * This should fix the OS/2 client bug #2335.
2149 if(numentries == 0) {
2150 dptr_close(&dptr_num);
2151 if (Protocol < PROTOCOL_NT1) {
2152 reply_doserror(req, ERRDOS, ERRnofiles);
2153 return;
2154 } else {
2155 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2156 ERRDOS, ERRbadfile);
2157 return;
2161 /* At this point pdata points to numentries directory entries. */
2163 /* Set up the return parameter block */
2164 SSVAL(params,0,dptr_num);
2165 SSVAL(params,2,numentries);
2166 SSVAL(params,4,finished);
2167 SSVAL(params,6,0); /* Never an EA error */
2168 SSVAL(params,8,last_entry_off);
2170 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2171 max_data_bytes);
2173 if ((! *directory) && dptr_path(dptr_num)) {
2174 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2175 if (!directory) {
2176 reply_nterror(req, NT_STATUS_NO_MEMORY);
2180 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2181 smb_fn_name(CVAL(req->inbuf,smb_com)),
2182 mask, directory, dirtype, numentries ) );
2185 * Force a name mangle here to ensure that the
2186 * mask as an 8.3 name is top of the mangled cache.
2187 * The reasons for this are subtle. Don't remove
2188 * this code unless you know what you are doing
2189 * (see PR#13758). JRA.
2192 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2193 char mangled_name[13];
2194 name_to_8_3(mask, mangled_name, True, conn->params);
2197 return;
2200 /****************************************************************************
2201 Reply to a TRANS2_FINDNEXT.
2202 ****************************************************************************/
2204 static void call_trans2findnext(connection_struct *conn,
2205 struct smb_request *req,
2206 char **pparams, int total_params,
2207 char **ppdata, int total_data,
2208 unsigned int max_data_bytes)
2210 /* We must be careful here that we don't return more than the
2211 allowed number of data bytes. If this means returning fewer than
2212 maxentries then so be it. We assume that the redirector has
2213 enough room for the fixed number of parameter bytes it has
2214 requested. */
2215 char *params = *pparams;
2216 char *pdata = *ppdata;
2217 char *data_end;
2218 int dptr_num;
2219 int maxentries;
2220 uint16 info_level;
2221 uint32 resume_key;
2222 uint16 findnext_flags;
2223 bool close_after_request;
2224 bool close_if_end;
2225 bool requires_resume_key;
2226 bool continue_bit;
2227 bool mask_contains_wcard = False;
2228 char *resume_name = NULL;
2229 const char *mask = NULL;
2230 const char *directory = NULL;
2231 char *p = NULL;
2232 uint16 dirtype;
2233 int numentries = 0;
2234 int i, last_entry_off=0;
2235 bool finished = False;
2236 bool dont_descend = False;
2237 bool out_of_space = False;
2238 int space_remaining;
2239 struct ea_list *ea_list = NULL;
2240 NTSTATUS ntstatus = NT_STATUS_OK;
2241 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2242 TALLOC_CTX *ctx = talloc_tos();
2244 if (total_params < 13) {
2245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2246 return;
2249 dptr_num = SVAL(params,0);
2250 maxentries = SVAL(params,2);
2251 info_level = SVAL(params,4);
2252 resume_key = IVAL(params,6);
2253 findnext_flags = SVAL(params,10);
2254 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2255 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2256 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2257 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2259 if (!continue_bit) {
2260 /* We only need resume_name if continue_bit is zero. */
2261 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2262 params+12,
2263 total_params - 12, STR_TERMINATE, &ntstatus,
2264 &mask_contains_wcard);
2265 if (!NT_STATUS_IS_OK(ntstatus)) {
2266 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2267 complain (it thinks we're asking for the directory above the shared
2268 path or an invalid name). Catch this as the resume name is only compared, never used in
2269 a file access. JRA. */
2270 srvstr_pull_talloc(ctx, params, req->flags2,
2271 &resume_name, params+12,
2272 total_params - 12,
2273 STR_TERMINATE);
2275 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2276 reply_nterror(req, ntstatus);
2277 return;
2282 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2283 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2284 resume_key = %d resume name = %s continue=%d level = %d\n",
2285 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2286 requires_resume_key, resume_key,
2287 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2289 if (!maxentries) {
2290 /* W2K3 seems to treat zero as 1. */
2291 maxentries = 1;
2294 switch (info_level) {
2295 case SMB_FIND_INFO_STANDARD:
2296 case SMB_FIND_EA_SIZE:
2297 case SMB_FIND_EA_LIST:
2298 case SMB_FIND_FILE_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2300 case SMB_FIND_FILE_NAMES_INFO:
2301 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2302 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2304 break;
2305 case SMB_FIND_FILE_UNIX:
2306 case SMB_FIND_FILE_UNIX_INFO2:
2307 /* Always use filesystem for UNIX mtime query. */
2308 ask_sharemode = false;
2309 if (!lp_unix_extensions()) {
2310 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2311 return;
2313 break;
2314 default:
2315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2316 return;
2319 if (info_level == SMB_FIND_EA_LIST) {
2320 uint32 ea_size;
2322 if (total_data < 4) {
2323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2324 return;
2327 ea_size = IVAL(pdata,0);
2328 if (ea_size != total_data) {
2329 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2330 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 return;
2335 if (!lp_ea_support(SNUM(conn))) {
2336 reply_doserror(req, ERRDOS, ERReasnotsupported);
2337 return;
2340 /* Pull out the list of names. */
2341 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2342 if (!ea_list) {
2343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2344 return;
2348 *ppdata = (char *)SMB_REALLOC(
2349 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2350 if(*ppdata == NULL) {
2351 reply_nterror(req, NT_STATUS_NO_MEMORY);
2352 return;
2355 pdata = *ppdata;
2356 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2358 /* Realloc the params space */
2359 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2360 if(*pparams == NULL ) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 return;
2365 params = *pparams;
2367 /* Check that the dptr is valid */
2368 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2369 reply_doserror(req, ERRDOS, ERRnofiles);
2370 return;
2373 string_set(&conn->dirpath,dptr_path(dptr_num));
2375 /* Get the wildcard mask from the dptr */
2376 if((p = dptr_wcard(dptr_num))== NULL) {
2377 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2378 reply_doserror(req, ERRDOS, ERRnofiles);
2379 return;
2382 mask = p;
2383 directory = conn->dirpath;
2385 /* Get the attr mask from the dptr */
2386 dirtype = dptr_attr(dptr_num);
2388 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2389 dptr_num, mask, dirtype,
2390 (long)conn->dirptr,
2391 dptr_TellDir(conn->dirptr)));
2393 /* We don't need to check for VOL here as this is returned by
2394 a different TRANS2 call. */
2396 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2397 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2398 dont_descend = True;
2400 p = pdata;
2401 space_remaining = max_data_bytes;
2402 out_of_space = False;
2405 * Seek to the correct position. We no longer use the resume key but
2406 * depend on the last file name instead.
2409 if(!continue_bit && resume_name && *resume_name) {
2410 SMB_STRUCT_STAT st;
2412 long current_pos = 0;
2414 * Remember, name_to_8_3 is called by
2415 * get_lanman2_dir_entry(), so the resume name
2416 * could be mangled. Ensure we check the unmangled name.
2419 if (mangle_is_mangled(resume_name, conn->params)) {
2420 char *new_resume_name = NULL;
2421 mangle_lookup_name_from_8_3(ctx,
2422 resume_name,
2423 &new_resume_name,
2424 conn->params);
2425 if (new_resume_name) {
2426 resume_name = new_resume_name;
2431 * Fix for NT redirector problem triggered by resume key indexes
2432 * changing between directory scans. We now return a resume key of 0
2433 * and instead look for the filename to continue from (also given
2434 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2435 * findfirst/findnext (as is usual) then the directory pointer
2436 * should already be at the correct place.
2439 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2440 } /* end if resume_name && !continue_bit */
2442 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2443 bool got_exact_match = False;
2445 /* this is a heuristic to avoid seeking the dirptr except when
2446 absolutely necessary. It allows for a filename of about 40 chars */
2447 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2448 out_of_space = True;
2449 finished = False;
2450 } else {
2451 finished = !get_lanman2_dir_entry(ctx,
2452 conn,
2453 req->flags2,
2454 mask,dirtype,info_level,
2455 requires_resume_key,dont_descend,
2456 ask_sharemode,
2457 &p,pdata,data_end,
2458 space_remaining, &out_of_space,
2459 &got_exact_match,
2460 &last_entry_off, ea_list);
2463 if (finished && out_of_space)
2464 finished = False;
2466 if (!finished && !out_of_space)
2467 numentries++;
2470 * As an optimisation if we know we aren't looking
2471 * for a wildcard name (ie. the name matches the wildcard exactly)
2472 * then we can finish on any (first) match.
2473 * This speeds up large directory searches. JRA.
2476 if(got_exact_match)
2477 finished = True;
2479 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2482 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2483 smb_fn_name(CVAL(req->inbuf,smb_com)),
2484 mask, directory, dirtype, numentries ) );
2486 /* Check if we can close the dirptr */
2487 if(close_after_request || (finished && close_if_end)) {
2488 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2489 dptr_close(&dptr_num); /* This frees up the saved mask */
2492 /* Set up the return parameter block */
2493 SSVAL(params,0,numentries);
2494 SSVAL(params,2,finished);
2495 SSVAL(params,4,0); /* Never an EA error */
2496 SSVAL(params,6,last_entry_off);
2498 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2499 max_data_bytes);
2501 return;
2504 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2506 E_md4hash(lp_servicename(SNUM(conn)),objid);
2507 return objid;
2510 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2512 SMB_ASSERT(extended_info != NULL);
2514 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2515 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2516 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2517 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2518 #ifdef SAMBA_VERSION_REVISION
2519 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2520 #endif
2521 extended_info->samba_subversion = 0;
2522 #ifdef SAMBA_VERSION_RC_RELEASE
2523 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2524 #else
2525 #ifdef SAMBA_VERSION_PRE_RELEASE
2526 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2527 #endif
2528 #endif
2529 #ifdef SAMBA_VERSION_VENDOR_PATCH
2530 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2531 #endif
2532 extended_info->samba_gitcommitdate = 0;
2533 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2534 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2535 #endif
2537 memset(extended_info->samba_version_string, 0,
2538 sizeof(extended_info->samba_version_string));
2540 snprintf (extended_info->samba_version_string,
2541 sizeof(extended_info->samba_version_string),
2542 "%s", samba_version_string());
2545 /****************************************************************************
2546 Reply to a TRANS2_QFSINFO (query filesystem info).
2547 ****************************************************************************/
2549 static void call_trans2qfsinfo(connection_struct *conn,
2550 struct smb_request *req,
2551 char **pparams, int total_params,
2552 char **ppdata, int total_data,
2553 unsigned int max_data_bytes)
2555 char *pdata, *end_data;
2556 char *params = *pparams;
2557 uint16 info_level;
2558 int data_len, len;
2559 SMB_STRUCT_STAT st;
2560 const char *vname = volume_label(SNUM(conn));
2561 int snum = SNUM(conn);
2562 char *fstype = lp_fstype(SNUM(conn));
2563 uint32 additional_flags = 0;
2565 if (total_params < 2) {
2566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2567 return;
2570 info_level = SVAL(params,0);
2572 if (IS_IPC(conn)) {
2573 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2574 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2575 "info level (0x%x) on IPC$.\n",
2576 (unsigned int)info_level));
2577 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2578 return;
2582 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2583 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2584 DEBUG(0,("call_trans2qfsinfo: encryption required "
2585 "and info level 0x%x sent.\n",
2586 (unsigned int)info_level));
2587 exit_server_cleanly("encryption required "
2588 "on connection");
2589 return;
2593 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2595 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2596 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2597 reply_doserror(req, ERRSRV, ERRinvdevice);
2598 return;
2601 *ppdata = (char *)SMB_REALLOC(
2602 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2603 if (*ppdata == NULL ) {
2604 reply_nterror(req, NT_STATUS_NO_MEMORY);
2605 return;
2608 pdata = *ppdata;
2609 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2610 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2612 switch (info_level) {
2613 case SMB_INFO_ALLOCATION:
2615 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2616 data_len = 18;
2617 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2618 reply_unixerror(req, ERRHRD, ERRgeneral);
2619 return;
2622 block_size = lp_block_size(snum);
2623 if (bsize < block_size) {
2624 SMB_BIG_UINT factor = block_size/bsize;
2625 bsize = block_size;
2626 dsize /= factor;
2627 dfree /= factor;
2629 if (bsize > block_size) {
2630 SMB_BIG_UINT factor = bsize/block_size;
2631 bsize = block_size;
2632 dsize *= factor;
2633 dfree *= factor;
2635 bytes_per_sector = 512;
2636 sectors_per_unit = bsize/bytes_per_sector;
2638 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2639 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2640 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2642 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2643 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2644 SIVAL(pdata,l1_cUnit,dsize);
2645 SIVAL(pdata,l1_cUnitAvail,dfree);
2646 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2647 break;
2650 case SMB_INFO_VOLUME:
2651 /* Return volume name */
2653 * Add volume serial number - hash of a combination of
2654 * the called hostname and the service name.
2656 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2658 * Win2k3 and previous mess this up by sending a name length
2659 * one byte short. I believe only older clients (OS/2 Win9x) use
2660 * this call so try fixing this by adding a terminating null to
2661 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2663 len = srvstr_push(
2664 pdata, req->flags2,
2665 pdata+l2_vol_szVolLabel, vname,
2666 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2667 STR_NOALIGN|STR_TERMINATE);
2668 SCVAL(pdata,l2_vol_cch,len);
2669 data_len = l2_vol_szVolLabel + len;
2670 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2671 (unsigned)st.st_ctime, len, vname));
2672 break;
2674 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2675 case SMB_FS_ATTRIBUTE_INFORMATION:
2677 additional_flags = 0;
2678 #if defined(HAVE_SYS_QUOTAS)
2679 additional_flags |= FILE_VOLUME_QUOTAS;
2680 #endif
2682 if(lp_nt_acl_support(SNUM(conn))) {
2683 additional_flags |= FILE_PERSISTENT_ACLS;
2686 /* Capabilities are filled in at connection time through STATVFS call */
2687 additional_flags |= conn->fs_capabilities;
2689 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2690 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2691 additional_flags); /* FS ATTRIBUTES */
2693 SIVAL(pdata,4,255); /* Max filename component length */
2694 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2695 and will think we can't do long filenames */
2696 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2697 PTR_DIFF(end_data, pdata+12),
2698 STR_UNICODE);
2699 SIVAL(pdata,8,len);
2700 data_len = 12 + len;
2701 break;
2703 case SMB_QUERY_FS_LABEL_INFO:
2704 case SMB_FS_LABEL_INFORMATION:
2705 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2706 PTR_DIFF(end_data, pdata+4), 0);
2707 data_len = 4 + len;
2708 SIVAL(pdata,0,len);
2709 break;
2711 case SMB_QUERY_FS_VOLUME_INFO:
2712 case SMB_FS_VOLUME_INFORMATION:
2715 * Add volume serial number - hash of a combination of
2716 * the called hostname and the service name.
2718 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2719 (str_checksum(get_local_machine_name())<<16));
2721 /* Max label len is 32 characters. */
2722 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2723 PTR_DIFF(end_data, pdata+18),
2724 STR_UNICODE);
2725 SIVAL(pdata,12,len);
2726 data_len = 18+len;
2728 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2729 (int)strlen(vname),vname, lp_servicename(snum)));
2730 break;
2732 case SMB_QUERY_FS_SIZE_INFO:
2733 case SMB_FS_SIZE_INFORMATION:
2735 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2736 data_len = 24;
2737 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2738 reply_unixerror(req, ERRHRD, ERRgeneral);
2739 return;
2741 block_size = lp_block_size(snum);
2742 if (bsize < block_size) {
2743 SMB_BIG_UINT factor = block_size/bsize;
2744 bsize = block_size;
2745 dsize /= factor;
2746 dfree /= factor;
2748 if (bsize > block_size) {
2749 SMB_BIG_UINT factor = bsize/block_size;
2750 bsize = block_size;
2751 dsize *= factor;
2752 dfree *= factor;
2754 bytes_per_sector = 512;
2755 sectors_per_unit = bsize/bytes_per_sector;
2756 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2757 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2758 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2759 SBIG_UINT(pdata,0,dsize);
2760 SBIG_UINT(pdata,8,dfree);
2761 SIVAL(pdata,16,sectors_per_unit);
2762 SIVAL(pdata,20,bytes_per_sector);
2763 break;
2766 case SMB_FS_FULL_SIZE_INFORMATION:
2768 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2769 data_len = 32;
2770 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2771 reply_unixerror(req, ERRHRD, ERRgeneral);
2772 return;
2774 block_size = lp_block_size(snum);
2775 if (bsize < block_size) {
2776 SMB_BIG_UINT factor = block_size/bsize;
2777 bsize = block_size;
2778 dsize /= factor;
2779 dfree /= factor;
2781 if (bsize > block_size) {
2782 SMB_BIG_UINT factor = bsize/block_size;
2783 bsize = block_size;
2784 dsize *= factor;
2785 dfree *= factor;
2787 bytes_per_sector = 512;
2788 sectors_per_unit = bsize/bytes_per_sector;
2789 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2790 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2791 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2792 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2793 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2794 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2795 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2796 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2797 break;
2800 case SMB_QUERY_FS_DEVICE_INFO:
2801 case SMB_FS_DEVICE_INFORMATION:
2802 data_len = 8;
2803 SIVAL(pdata,0,0); /* dev type */
2804 SIVAL(pdata,4,0); /* characteristics */
2805 break;
2807 #ifdef HAVE_SYS_QUOTAS
2808 case SMB_FS_QUOTA_INFORMATION:
2810 * what we have to send --metze:
2812 * Unknown1: 24 NULL bytes
2813 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2814 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2815 * Quota Flags: 2 byte :
2816 * Unknown3: 6 NULL bytes
2818 * 48 bytes total
2820 * details for Quota Flags:
2822 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2823 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2824 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2825 * 0x0001 Enable Quotas: enable quota for this fs
2829 /* we need to fake up a fsp here,
2830 * because its not send in this call
2832 files_struct fsp;
2833 SMB_NTQUOTA_STRUCT quotas;
2835 ZERO_STRUCT(fsp);
2836 ZERO_STRUCT(quotas);
2838 fsp.conn = conn;
2839 fsp.fnum = -1;
2841 /* access check */
2842 if (conn->server_info->utok.uid != 0) {
2843 DEBUG(0,("set_user_quota: access_denied "
2844 "service [%s] user [%s]\n",
2845 lp_servicename(SNUM(conn)),
2846 conn->server_info->unix_name));
2847 reply_doserror(req, ERRDOS, ERRnoaccess);
2848 return;
2851 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2852 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2853 reply_doserror(req, ERRSRV, ERRerror);
2854 return;
2857 data_len = 48;
2859 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2861 /* Unknown1 24 NULL bytes*/
2862 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2863 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2864 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2866 /* Default Soft Quota 8 bytes */
2867 SBIG_UINT(pdata,24,quotas.softlim);
2869 /* Default Hard Quota 8 bytes */
2870 SBIG_UINT(pdata,32,quotas.hardlim);
2872 /* Quota flag 2 bytes */
2873 SSVAL(pdata,40,quotas.qflags);
2875 /* Unknown3 6 NULL bytes */
2876 SSVAL(pdata,42,0);
2877 SIVAL(pdata,44,0);
2879 break;
2881 #endif /* HAVE_SYS_QUOTAS */
2882 case SMB_FS_OBJECTID_INFORMATION:
2884 unsigned char objid[16];
2885 struct smb_extended_info extended_info;
2886 memcpy(pdata,create_volume_objectid(conn, objid),16);
2887 samba_extended_info_version (&extended_info);
2888 SIVAL(pdata,16,extended_info.samba_magic);
2889 SIVAL(pdata,20,extended_info.samba_version);
2890 SIVAL(pdata,24,extended_info.samba_subversion);
2891 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2892 memcpy(pdata+36,extended_info.samba_version_string,28);
2893 data_len = 64;
2894 break;
2898 * Query the version and capabilities of the CIFS UNIX extensions
2899 * in use.
2902 case SMB_QUERY_CIFS_UNIX_INFO:
2904 bool large_write = lp_min_receive_file_size() &&
2905 !srv_is_signing_active();
2906 bool large_read = !srv_is_signing_active();
2907 int encrypt_caps = 0;
2909 if (!lp_unix_extensions()) {
2910 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2911 return;
2914 switch (conn->encrypt_level) {
2915 case 0:
2916 encrypt_caps = 0;
2917 break;
2918 case 1:
2919 case Auto:
2920 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2921 break;
2922 case Required:
2923 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2924 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2925 large_write = false;
2926 large_read = false;
2927 break;
2930 data_len = 12;
2931 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2932 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2934 /* We have POSIX ACLs, pathname, encryption,
2935 * large read/write, and locking capability. */
2937 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2938 CIFS_UNIX_POSIX_ACLS_CAP|
2939 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2940 CIFS_UNIX_FCNTL_LOCKS_CAP|
2941 CIFS_UNIX_EXTATTR_CAP|
2942 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2943 encrypt_caps|
2944 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2945 (large_write ?
2946 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2947 break;
2950 case SMB_QUERY_POSIX_FS_INFO:
2952 int rc;
2953 vfs_statvfs_struct svfs;
2955 if (!lp_unix_extensions()) {
2956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2957 return;
2960 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2962 if (!rc) {
2963 data_len = 56;
2964 SIVAL(pdata,0,svfs.OptimalTransferSize);
2965 SIVAL(pdata,4,svfs.BlockSize);
2966 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2967 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2968 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2969 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2970 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2971 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2972 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2973 #ifdef EOPNOTSUPP
2974 } else if (rc == EOPNOTSUPP) {
2975 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2976 return;
2977 #endif /* EOPNOTSUPP */
2978 } else {
2979 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2980 reply_doserror(req, ERRSRV, ERRerror);
2981 return;
2983 break;
2986 case SMB_QUERY_POSIX_WHOAMI:
2988 uint32_t flags = 0;
2989 uint32_t sid_bytes;
2990 int i;
2992 if (!lp_unix_extensions()) {
2993 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2994 return;
2997 if (max_data_bytes < 40) {
2998 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2999 return;
3002 /* We ARE guest if global_sid_Builtin_Guests is
3003 * in our list of SIDs.
3005 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3006 conn->server_info->ptok)) {
3007 flags |= SMB_WHOAMI_GUEST;
3010 /* We are NOT guest if global_sid_Authenticated_Users
3011 * is in our list of SIDs.
3013 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3014 conn->server_info->ptok)) {
3015 flags &= ~SMB_WHOAMI_GUEST;
3018 /* NOTE: 8 bytes for UID/GID, irrespective of native
3019 * platform size. This matches
3020 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3022 data_len = 4 /* flags */
3023 + 4 /* flag mask */
3024 + 8 /* uid */
3025 + 8 /* gid */
3026 + 4 /* ngroups */
3027 + 4 /* num_sids */
3028 + 4 /* SID bytes */
3029 + 4 /* pad/reserved */
3030 + (conn->server_info->utok.ngroups * 8)
3031 /* groups list */
3032 + (conn->server_info->ptok->num_sids *
3033 SID_MAX_SIZE)
3034 /* SID list */;
3036 SIVAL(pdata, 0, flags);
3037 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3038 SBIG_UINT(pdata, 8,
3039 (SMB_BIG_UINT)conn->server_info->utok.uid);
3040 SBIG_UINT(pdata, 16,
3041 (SMB_BIG_UINT)conn->server_info->utok.gid);
3044 if (data_len >= max_data_bytes) {
3045 /* Potential overflow, skip the GIDs and SIDs. */
3047 SIVAL(pdata, 24, 0); /* num_groups */
3048 SIVAL(pdata, 28, 0); /* num_sids */
3049 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3050 SIVAL(pdata, 36, 0); /* reserved */
3052 data_len = 40;
3053 break;
3056 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3057 SIVAL(pdata, 28, conn->server_info->num_sids);
3059 /* We walk the SID list twice, but this call is fairly
3060 * infrequent, and I don't expect that it's performance
3061 * sensitive -- jpeach
3063 for (i = 0, sid_bytes = 0;
3064 i < conn->server_info->ptok->num_sids; ++i) {
3065 sid_bytes += ndr_size_dom_sid(
3066 &conn->server_info->ptok->user_sids[i],
3070 /* SID list byte count */
3071 SIVAL(pdata, 32, sid_bytes);
3073 /* 4 bytes pad/reserved - must be zero */
3074 SIVAL(pdata, 36, 0);
3075 data_len = 40;
3077 /* GID list */
3078 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3079 SBIG_UINT(pdata, data_len,
3080 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3081 data_len += 8;
3084 /* SID list */
3085 for (i = 0;
3086 i < conn->server_info->ptok->num_sids; ++i) {
3087 int sid_len = ndr_size_dom_sid(
3088 &conn->server_info->ptok->user_sids[i],
3091 sid_linearize(pdata + data_len, sid_len,
3092 &conn->server_info->ptok->user_sids[i]);
3093 data_len += sid_len;
3096 break;
3099 case SMB_MAC_QUERY_FS_INFO:
3101 * Thursby MAC extension... ONLY on NTFS filesystems
3102 * once we do streams then we don't need this
3104 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3105 data_len = 88;
3106 SIVAL(pdata,84,0x100); /* Don't support mac... */
3107 break;
3109 /* drop through */
3110 default:
3111 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3112 return;
3116 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3117 max_data_bytes);
3119 DEBUG( 4, ( "%s info_level = %d\n",
3120 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3122 return;
3125 /****************************************************************************
3126 Reply to a TRANS2_SETFSINFO (set filesystem info).
3127 ****************************************************************************/
3129 static void call_trans2setfsinfo(connection_struct *conn,
3130 struct smb_request *req,
3131 char **pparams, int total_params,
3132 char **ppdata, int total_data,
3133 unsigned int max_data_bytes)
3135 char *pdata = *ppdata;
3136 char *params = *pparams;
3137 uint16 info_level;
3139 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3141 /* */
3142 if (total_params < 4) {
3143 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3144 total_params));
3145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3146 return;
3149 info_level = SVAL(params,2);
3151 if (IS_IPC(conn)) {
3152 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3153 info_level != SMB_SET_CIFS_UNIX_INFO) {
3154 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3155 "info level (0x%x) on IPC$.\n",
3156 (unsigned int)info_level));
3157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3158 return;
3162 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3163 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3164 DEBUG(0,("call_trans2setfsinfo: encryption required "
3165 "and info level 0x%x sent.\n",
3166 (unsigned int)info_level));
3167 exit_server_cleanly("encryption required "
3168 "on connection");
3169 return;
3173 switch(info_level) {
3174 case SMB_SET_CIFS_UNIX_INFO:
3176 uint16 client_unix_major;
3177 uint16 client_unix_minor;
3178 uint32 client_unix_cap_low;
3179 uint32 client_unix_cap_high;
3181 if (!lp_unix_extensions()) {
3182 reply_nterror(req,
3183 NT_STATUS_INVALID_LEVEL);
3184 return;
3187 /* There should be 12 bytes of capabilities set. */
3188 if (total_data < 8) {
3189 reply_nterror(
3190 req,
3191 NT_STATUS_INVALID_PARAMETER);
3192 return;
3194 client_unix_major = SVAL(pdata,0);
3195 client_unix_minor = SVAL(pdata,2);
3196 client_unix_cap_low = IVAL(pdata,4);
3197 client_unix_cap_high = IVAL(pdata,8);
3198 /* Just print these values for now. */
3199 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3200 cap_low = 0x%x, cap_high = 0x%x\n",
3201 (unsigned int)client_unix_major,
3202 (unsigned int)client_unix_minor,
3203 (unsigned int)client_unix_cap_low,
3204 (unsigned int)client_unix_cap_high ));
3206 /* Here is where we must switch to posix pathname processing... */
3207 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3208 lp_set_posix_pathnames();
3209 mangle_change_to_posix();
3212 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3213 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3214 /* Client that knows how to do posix locks,
3215 * but not posix open/mkdir operations. Set a
3216 * default type for read/write checks. */
3218 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3221 break;
3224 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3226 NTSTATUS status;
3227 size_t param_len = 0;
3228 size_t data_len = total_data;
3230 if (!lp_unix_extensions()) {
3231 reply_nterror(
3232 req,
3233 NT_STATUS_INVALID_LEVEL);
3234 return;
3237 if (lp_smb_encrypt(SNUM(conn)) == false) {
3238 reply_nterror(
3239 req,
3240 NT_STATUS_NOT_SUPPORTED);
3241 return;
3244 DEBUG( 4,("call_trans2setfsinfo: "
3245 "request transport encryption.\n"));
3247 status = srv_request_encryption_setup(conn,
3248 (unsigned char **)ppdata,
3249 &data_len,
3250 (unsigned char **)pparams,
3251 &param_len);
3253 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3254 !NT_STATUS_IS_OK(status)) {
3255 reply_nterror(req, status);
3256 return;
3259 send_trans2_replies(conn, req,
3260 *pparams,
3261 param_len,
3262 *ppdata,
3263 data_len,
3264 max_data_bytes);
3266 if (NT_STATUS_IS_OK(status)) {
3267 /* Server-side transport
3268 * encryption is now *on*. */
3269 status = srv_encryption_start(conn);
3270 if (!NT_STATUS_IS_OK(status)) {
3271 exit_server_cleanly(
3272 "Failure in setting "
3273 "up encrypted transport");
3276 return;
3279 case SMB_FS_QUOTA_INFORMATION:
3281 files_struct *fsp = NULL;
3282 SMB_NTQUOTA_STRUCT quotas;
3284 ZERO_STRUCT(quotas);
3286 /* access check */
3287 if ((conn->server_info->utok.uid != 0)
3288 ||!CAN_WRITE(conn)) {
3289 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3290 lp_servicename(SNUM(conn)),
3291 conn->server_info->unix_name));
3292 reply_doserror(req, ERRSRV, ERRaccess);
3293 return;
3296 /* note: normaly there're 48 bytes,
3297 * but we didn't use the last 6 bytes for now
3298 * --metze
3300 fsp = file_fsp(SVAL(params,0));
3302 if (!check_fsp_ntquota_handle(conn, req,
3303 fsp)) {
3304 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3305 reply_nterror(
3306 req, NT_STATUS_INVALID_HANDLE);
3307 return;
3310 if (total_data < 42) {
3311 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3312 total_data));
3313 reply_nterror(
3314 req,
3315 NT_STATUS_INVALID_PARAMETER);
3316 return;
3319 /* unknown_1 24 NULL bytes in pdata*/
3321 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3322 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3323 #ifdef LARGE_SMB_OFF_T
3324 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3325 #else /* LARGE_SMB_OFF_T */
3326 if ((IVAL(pdata,28) != 0)&&
3327 ((quotas.softlim != 0xFFFFFFFF)||
3328 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3329 /* more than 32 bits? */
3330 reply_nterror(
3331 req,
3332 NT_STATUS_INVALID_PARAMETER);
3333 return;
3335 #endif /* LARGE_SMB_OFF_T */
3337 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3338 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3339 #ifdef LARGE_SMB_OFF_T
3340 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3341 #else /* LARGE_SMB_OFF_T */
3342 if ((IVAL(pdata,36) != 0)&&
3343 ((quotas.hardlim != 0xFFFFFFFF)||
3344 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3345 /* more than 32 bits? */
3346 reply_nterror(
3347 req,
3348 NT_STATUS_INVALID_PARAMETER);
3349 return;
3351 #endif /* LARGE_SMB_OFF_T */
3353 /* quota_flags 2 bytes **/
3354 quotas.qflags = SVAL(pdata,40);
3356 /* unknown_2 6 NULL bytes follow*/
3358 /* now set the quotas */
3359 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3360 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3361 reply_doserror(req, ERRSRV, ERRerror);
3362 return;
3365 break;
3367 default:
3368 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3369 info_level));
3370 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3371 return;
3372 break;
3376 * sending this reply works fine,
3377 * but I'm not sure it's the same
3378 * like windows do...
3379 * --metze
3381 reply_outbuf(req, 10, 0);
3384 #if defined(HAVE_POSIX_ACLS)
3385 /****************************************************************************
3386 Utility function to count the number of entries in a POSIX acl.
3387 ****************************************************************************/
3389 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3391 unsigned int ace_count = 0;
3392 int entry_id = SMB_ACL_FIRST_ENTRY;
3393 SMB_ACL_ENTRY_T entry;
3395 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3396 /* get_next... */
3397 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3398 entry_id = SMB_ACL_NEXT_ENTRY;
3400 ace_count++;
3402 return ace_count;
3405 /****************************************************************************
3406 Utility function to marshall a POSIX acl into wire format.
3407 ****************************************************************************/
3409 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3411 int entry_id = SMB_ACL_FIRST_ENTRY;
3412 SMB_ACL_ENTRY_T entry;
3414 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3415 SMB_ACL_TAG_T tagtype;
3416 SMB_ACL_PERMSET_T permset;
3417 unsigned char perms = 0;
3418 unsigned int own_grp;
3420 /* get_next... */
3421 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3422 entry_id = SMB_ACL_NEXT_ENTRY;
3425 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3426 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3427 return False;
3430 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3432 return False;
3435 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3436 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3437 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3439 SCVAL(pdata,1,perms);
3441 switch (tagtype) {
3442 case SMB_ACL_USER_OBJ:
3443 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3444 own_grp = (unsigned int)pst->st_uid;
3445 SIVAL(pdata,2,own_grp);
3446 SIVAL(pdata,6,0);
3447 break;
3448 case SMB_ACL_USER:
3450 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3451 if (!puid) {
3452 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3453 return False;
3455 own_grp = (unsigned int)*puid;
3456 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3457 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3458 SIVAL(pdata,2,own_grp);
3459 SIVAL(pdata,6,0);
3460 break;
3462 case SMB_ACL_GROUP_OBJ:
3463 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3464 own_grp = (unsigned int)pst->st_gid;
3465 SIVAL(pdata,2,own_grp);
3466 SIVAL(pdata,6,0);
3467 break;
3468 case SMB_ACL_GROUP:
3470 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3471 if (!pgid) {
3472 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3473 return False;
3475 own_grp = (unsigned int)*pgid;
3476 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3477 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3478 SIVAL(pdata,2,own_grp);
3479 SIVAL(pdata,6,0);
3480 break;
3482 case SMB_ACL_MASK:
3483 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3484 SIVAL(pdata,2,0xFFFFFFFF);
3485 SIVAL(pdata,6,0xFFFFFFFF);
3486 break;
3487 case SMB_ACL_OTHER:
3488 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3489 SIVAL(pdata,2,0xFFFFFFFF);
3490 SIVAL(pdata,6,0xFFFFFFFF);
3491 break;
3492 default:
3493 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3494 return False;
3496 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3499 return True;
3501 #endif
3503 /****************************************************************************
3504 Store the FILE_UNIX_BASIC info.
3505 ****************************************************************************/
3507 static char *store_file_unix_basic(connection_struct *conn,
3508 char *pdata,
3509 files_struct *fsp,
3510 const SMB_STRUCT_STAT *psbuf)
3512 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3513 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3515 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3516 pdata += 8;
3518 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3519 pdata += 8;
3521 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3522 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3523 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3524 pdata += 24;
3526 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3527 SIVAL(pdata,4,0);
3528 pdata += 8;
3530 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3531 SIVAL(pdata,4,0);
3532 pdata += 8;
3534 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3535 pdata += 4;
3537 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3538 SIVAL(pdata,4,0);
3539 pdata += 8;
3541 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3542 SIVAL(pdata,4,0);
3543 pdata += 8;
3545 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3546 pdata += 8;
3548 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3549 SIVAL(pdata,4,0);
3550 pdata += 8;
3552 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3553 SIVAL(pdata,4,0);
3554 pdata += 8;
3556 return pdata;
3559 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3560 * the chflags(2) (or equivalent) flags.
3562 * XXX: this really should be behind the VFS interface. To do this, we would
3563 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3564 * Each VFS module could then implement its own mapping as appropriate for the
3565 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3567 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3568 info2_flags_map[] =
3570 #ifdef UF_NODUMP
3571 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3572 #endif
3574 #ifdef UF_IMMUTABLE
3575 { UF_IMMUTABLE, EXT_IMMUTABLE },
3576 #endif
3578 #ifdef UF_APPEND
3579 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3580 #endif
3582 #ifdef UF_HIDDEN
3583 { UF_HIDDEN, EXT_HIDDEN },
3584 #endif
3586 /* Do not remove. We need to guarantee that this array has at least one
3587 * entry to build on HP-UX.
3589 { 0, 0 }
3593 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3594 uint32 *smb_fflags, uint32 *smb_fmask)
3596 #ifdef HAVE_STAT_ST_FLAGS
3597 int i;
3599 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3600 *smb_fmask |= info2_flags_map[i].smb_fflag;
3601 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3602 *smb_fflags |= info2_flags_map[i].smb_fflag;
3605 #endif /* HAVE_STAT_ST_FLAGS */
3608 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3609 const uint32 smb_fflags,
3610 const uint32 smb_fmask,
3611 int *stat_fflags)
3613 #ifdef HAVE_STAT_ST_FLAGS
3614 uint32 max_fmask = 0;
3615 int i;
3617 *stat_fflags = psbuf->st_flags;
3619 /* For each flags requested in smb_fmask, check the state of the
3620 * corresponding flag in smb_fflags and set or clear the matching
3621 * stat flag.
3624 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3625 max_fmask |= info2_flags_map[i].smb_fflag;
3626 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3627 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3628 *stat_fflags |= info2_flags_map[i].stat_fflag;
3629 } else {
3630 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3635 /* If smb_fmask is asking to set any bits that are not supported by
3636 * our flag mappings, we should fail.
3638 if ((smb_fmask & max_fmask) != smb_fmask) {
3639 return False;
3642 return True;
3643 #else
3644 return False;
3645 #endif /* HAVE_STAT_ST_FLAGS */
3649 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3650 * of file flags and birth (create) time.
3652 static char *store_file_unix_basic_info2(connection_struct *conn,
3653 char *pdata,
3654 files_struct *fsp,
3655 const SMB_STRUCT_STAT *psbuf)
3657 uint32 file_flags = 0;
3658 uint32 flags_mask = 0;
3660 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3662 /* Create (birth) time 64 bit */
3663 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3664 pdata += 8;
3666 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3667 SIVAL(pdata, 0, file_flags); /* flags */
3668 SIVAL(pdata, 4, flags_mask); /* mask */
3669 pdata += 8;
3671 return pdata;
3674 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3675 const struct stream_struct *streams,
3676 char *data,
3677 unsigned int max_data_bytes,
3678 unsigned int *data_size)
3680 unsigned int i;
3681 unsigned int ofs = 0;
3683 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3684 unsigned int next_offset;
3685 size_t namelen;
3686 smb_ucs2_t *namebuf;
3688 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3689 streams[i].name, &namelen) ||
3690 namelen <= 2)
3692 return NT_STATUS_INVALID_PARAMETER;
3696 * name_buf is now null-terminated, we need to marshall as not
3697 * terminated
3700 namelen -= 2;
3702 SIVAL(data, ofs+4, namelen);
3703 SOFF_T(data, ofs+8, streams[i].size);
3704 SOFF_T(data, ofs+16, streams[i].alloc_size);
3705 memcpy(data+ofs+24, namebuf, namelen);
3706 TALLOC_FREE(namebuf);
3708 next_offset = ofs + 24 + namelen;
3710 if (i == num_streams-1) {
3711 SIVAL(data, ofs, 0);
3713 else {
3714 unsigned int align = ndr_align_size(next_offset, 8);
3716 memset(data+next_offset, 0, align);
3717 next_offset += align;
3719 SIVAL(data, ofs, next_offset - ofs);
3720 ofs = next_offset;
3723 ofs = next_offset;
3726 *data_size = ofs;
3728 return NT_STATUS_OK;
3731 /****************************************************************************
3732 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3733 ****************************************************************************/
3735 static void call_trans2qpipeinfo(connection_struct *conn,
3736 struct smb_request *req,
3737 unsigned int tran_call,
3738 char **pparams, int total_params,
3739 char **ppdata, int total_data,
3740 unsigned int max_data_bytes)
3742 char *params = *pparams;
3743 char *pdata = *ppdata;
3744 unsigned int data_size = 0;
3745 unsigned int param_size = 2;
3746 uint16 info_level;
3747 smb_np_struct *p_pipe = NULL;
3749 if (!params) {
3750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3751 return;
3754 if (total_params < 4) {
3755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3756 return;
3759 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3760 if (p_pipe == NULL) {
3761 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3762 return;
3765 info_level = SVAL(params,2);
3767 *pparams = (char *)SMB_REALLOC(*pparams,2);
3768 if (*pparams == NULL) {
3769 reply_nterror(req, NT_STATUS_NO_MEMORY);
3770 return;
3772 params = *pparams;
3773 SSVAL(params,0,0);
3774 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3775 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3776 if (*ppdata == NULL ) {
3777 reply_nterror(req, NT_STATUS_NO_MEMORY);
3778 return;
3780 pdata = *ppdata;
3782 switch (info_level) {
3783 case SMB_FILE_STANDARD_INFORMATION:
3784 memset(pdata,0,24);
3785 SOFF_T(pdata,0,4096LL);
3786 SIVAL(pdata,16,1);
3787 SIVAL(pdata,20,1);
3788 data_size = 24;
3789 break;
3791 default:
3792 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3793 return;
3796 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3797 max_data_bytes);
3799 return;
3802 /****************************************************************************
3803 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3804 file name or file id).
3805 ****************************************************************************/
3807 static void call_trans2qfilepathinfo(connection_struct *conn,
3808 struct smb_request *req,
3809 unsigned int tran_call,
3810 char **pparams, int total_params,
3811 char **ppdata, int total_data,
3812 unsigned int max_data_bytes)
3814 char *params = *pparams;
3815 char *pdata = *ppdata;
3816 char *dstart, *dend;
3817 uint16 info_level;
3818 int mode=0;
3819 int nlink;
3820 SMB_OFF_T file_size=0;
3821 SMB_BIG_UINT allocation_size=0;
3822 unsigned int data_size = 0;
3823 unsigned int param_size = 2;
3824 SMB_STRUCT_STAT sbuf;
3825 char *dos_fname = NULL;
3826 char *fname = NULL;
3827 char *fullpathname;
3828 char *base_name;
3829 char *p;
3830 SMB_OFF_T pos = 0;
3831 bool delete_pending = False;
3832 int len;
3833 time_t create_time, mtime, atime;
3834 struct timespec create_time_ts, mtime_ts, atime_ts;
3835 struct timespec write_time_ts;
3836 files_struct *fsp = NULL;
3837 struct file_id fileid;
3838 struct ea_list *ea_list = NULL;
3839 char *lock_data = NULL;
3840 bool ms_dfs_link = false;
3841 TALLOC_CTX *ctx = talloc_tos();
3843 if (!params) {
3844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3845 return;
3848 ZERO_STRUCT(sbuf);
3849 ZERO_STRUCT(write_time_ts);
3851 if (tran_call == TRANSACT2_QFILEINFO) {
3852 if (total_params < 4) {
3853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3854 return;
3857 if (IS_IPC(conn)) {
3858 call_trans2qpipeinfo(conn, req, tran_call,
3859 pparams, total_params,
3860 ppdata, total_data,
3861 max_data_bytes);
3862 return;
3865 fsp = file_fsp(SVAL(params,0));
3866 info_level = SVAL(params,2);
3868 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3870 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3871 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3872 return;
3875 /* Initial check for valid fsp ptr. */
3876 if (!check_fsp_open(conn, req, fsp)) {
3877 return;
3880 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3881 if (!fname) {
3882 reply_nterror(req, NT_STATUS_NO_MEMORY);
3883 return;
3886 if(fsp->fake_file_handle) {
3888 * This is actually for the QUOTA_FAKE_FILE --metze
3891 /* We know this name is ok, it's already passed the checks. */
3893 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3895 * This is actually a QFILEINFO on a directory
3896 * handle (returned from an NT SMB). NT5.0 seems
3897 * to do this call. JRA.
3900 if (INFO_LEVEL_IS_UNIX(info_level)) {
3901 /* Always do lstat for UNIX calls. */
3902 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3903 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3904 reply_unixerror(req,ERRDOS,ERRbadpath);
3905 return;
3907 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3908 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3909 reply_unixerror(req, ERRDOS, ERRbadpath);
3910 return;
3913 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3914 get_file_infos(fileid, &delete_pending, &write_time_ts);
3915 } else {
3917 * Original code - this is an open file.
3919 if (!check_fsp(conn, req, fsp)) {
3920 return;
3923 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3924 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3925 reply_unixerror(req, ERRDOS, ERRbadfid);
3926 return;
3928 pos = fsp->fh->position_information;
3929 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3930 get_file_infos(fileid, &delete_pending, &write_time_ts);
3933 } else {
3934 NTSTATUS status = NT_STATUS_OK;
3936 /* qpathinfo */
3937 if (total_params < 7) {
3938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3939 return;
3942 info_level = SVAL(params,0);
3944 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3946 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3948 return;
3951 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3952 total_params - 6,
3953 STR_TERMINATE, &status);
3954 if (!NT_STATUS_IS_OK(status)) {
3955 reply_nterror(req, status);
3956 return;
3959 status = resolve_dfspath(ctx,
3960 conn,
3961 req->flags2 & FLAGS2_DFS_PATHNAMES,
3962 fname,
3963 &fname);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3966 reply_botherror(req,
3967 NT_STATUS_PATH_NOT_COVERED,
3968 ERRSRV, ERRbadpath);
3970 reply_nterror(req, status);
3971 return;
3974 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 reply_nterror(req, status);
3977 return;
3979 status = check_name(conn, fname);
3980 if (!NT_STATUS_IS_OK(status)) {
3981 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3982 reply_nterror(req, status);
3983 return;
3986 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3987 && is_ntfs_stream_name(fname)) {
3988 char *base;
3989 SMB_STRUCT_STAT bsbuf;
3991 status = split_ntfs_stream_name(talloc_tos(), fname,
3992 &base, NULL);
3993 if (!NT_STATUS_IS_OK(status)) {
3994 DEBUG(10, ("create_file_unixpath: "
3995 "split_ntfs_stream_name failed: %s\n",
3996 nt_errstr(status)));
3997 reply_nterror(req, status);
3998 return;
4001 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4003 if (INFO_LEVEL_IS_UNIX(info_level)) {
4004 /* Always do lstat for UNIX calls. */
4005 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4006 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4007 reply_unixerror(req,ERRDOS,ERRbadpath);
4008 return;
4010 } else {
4011 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4012 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4013 reply_unixerror(req,ERRDOS,ERRbadpath);
4014 return;
4018 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4019 get_file_infos(fileid, &delete_pending, NULL);
4020 if (delete_pending) {
4021 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4022 return;
4026 if (INFO_LEVEL_IS_UNIX(info_level)) {
4027 /* Always do lstat for UNIX calls. */
4028 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4029 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4030 reply_unixerror(req, ERRDOS, ERRbadpath);
4031 return;
4034 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4035 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4037 if (!ms_dfs_link) {
4038 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4039 reply_unixerror(req, ERRDOS, ERRbadpath);
4040 return;
4044 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4045 get_file_infos(fileid, &delete_pending, &write_time_ts);
4046 if (delete_pending) {
4047 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4048 return;
4052 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4053 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4054 return;
4057 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4058 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4060 p = strrchr_m(fname,'/');
4061 if (!p)
4062 base_name = fname;
4063 else
4064 base_name = p+1;
4066 if (ms_dfs_link) {
4067 mode = dos_mode_msdfs(conn,fname,&sbuf);
4068 } else {
4069 mode = dos_mode(conn,fname,&sbuf);
4072 nlink = sbuf.st_nlink;
4074 if (nlink && (mode&aDIR)) {
4075 nlink = 1;
4078 if ((nlink > 0) && delete_pending) {
4079 nlink -= 1;
4082 fullpathname = fname;
4083 if (!(mode & aDIR))
4084 file_size = get_file_size(sbuf);
4086 /* Pull out any data sent here before we realloc. */
4087 switch (info_level) {
4088 case SMB_INFO_QUERY_EAS_FROM_LIST:
4090 /* Pull any EA list from the data portion. */
4091 uint32 ea_size;
4093 if (total_data < 4) {
4094 reply_nterror(
4095 req, NT_STATUS_INVALID_PARAMETER);
4096 return;
4098 ea_size = IVAL(pdata,0);
4100 if (total_data > 0 && ea_size != total_data) {
4101 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4102 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4103 reply_nterror(
4104 req, NT_STATUS_INVALID_PARAMETER);
4105 return;
4108 if (!lp_ea_support(SNUM(conn))) {
4109 reply_doserror(req, ERRDOS,
4110 ERReasnotsupported);
4111 return;
4114 /* Pull out the list of names. */
4115 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4116 if (!ea_list) {
4117 reply_nterror(
4118 req, NT_STATUS_INVALID_PARAMETER);
4119 return;
4121 break;
4124 case SMB_QUERY_POSIX_LOCK:
4126 if (fsp == NULL || fsp->fh->fd == -1) {
4127 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4128 return;
4131 if (total_data != POSIX_LOCK_DATA_SIZE) {
4132 reply_nterror(
4133 req, NT_STATUS_INVALID_PARAMETER);
4134 return;
4137 /* Copy the lock range data. */
4138 lock_data = (char *)TALLOC_MEMDUP(
4139 ctx, pdata, total_data);
4140 if (!lock_data) {
4141 reply_nterror(req, NT_STATUS_NO_MEMORY);
4142 return;
4145 default:
4146 break;
4149 *pparams = (char *)SMB_REALLOC(*pparams,2);
4150 if (*pparams == NULL) {
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4152 return;
4154 params = *pparams;
4155 SSVAL(params,0,0);
4156 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4157 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4158 if (*ppdata == NULL ) {
4159 reply_nterror(req, NT_STATUS_NO_MEMORY);
4160 return;
4162 pdata = *ppdata;
4163 dstart = pdata;
4164 dend = dstart + data_size - 1;
4166 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4167 mtime_ts = get_mtimespec(&sbuf);
4168 atime_ts = get_atimespec(&sbuf);
4170 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4172 if (!fsp) {
4173 /* Do we have this path open ? */
4174 files_struct *fsp1;
4175 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4176 fsp1 = file_find_di_first(fileid);
4177 if (fsp1 && fsp1->initial_allocation_size) {
4178 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4182 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4183 mtime_ts = write_time_ts;
4186 if (lp_dos_filetime_resolution(SNUM(conn))) {
4187 dos_filetime_timespec(&create_time_ts);
4188 dos_filetime_timespec(&mtime_ts);
4189 dos_filetime_timespec(&atime_ts);
4192 create_time = convert_timespec_to_time_t(create_time_ts);
4193 mtime = convert_timespec_to_time_t(mtime_ts);
4194 atime = convert_timespec_to_time_t(atime_ts);
4196 /* NT expects the name to be in an exact form of the *full*
4197 filename. See the trans2 torture test */
4198 if (ISDOT(base_name)) {
4199 dos_fname = talloc_strdup(ctx, "\\");
4200 if (!dos_fname) {
4201 reply_nterror(req, NT_STATUS_NO_MEMORY);
4202 return;
4204 } else {
4205 dos_fname = talloc_asprintf(ctx,
4206 "\\%s",
4207 fname);
4208 if (!dos_fname) {
4209 reply_nterror(req, NT_STATUS_NO_MEMORY);
4210 return;
4212 string_replace(dos_fname, '/', '\\');
4215 switch (info_level) {
4216 case SMB_INFO_STANDARD:
4217 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4218 data_size = 22;
4219 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4220 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4221 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4222 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4223 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4224 SSVAL(pdata,l1_attrFile,mode);
4225 break;
4227 case SMB_INFO_QUERY_EA_SIZE:
4229 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4230 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4231 data_size = 26;
4232 srv_put_dos_date2(pdata,0,create_time);
4233 srv_put_dos_date2(pdata,4,atime);
4234 srv_put_dos_date2(pdata,8,mtime); /* write time */
4235 SIVAL(pdata,12,(uint32)file_size);
4236 SIVAL(pdata,16,(uint32)allocation_size);
4237 SSVAL(pdata,20,mode);
4238 SIVAL(pdata,22,ea_size);
4239 break;
4242 case SMB_INFO_IS_NAME_VALID:
4243 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4244 if (tran_call == TRANSACT2_QFILEINFO) {
4245 /* os/2 needs this ? really ?*/
4246 reply_doserror(req, ERRDOS, ERRbadfunc);
4247 return;
4249 data_size = 0;
4250 param_size = 0;
4251 break;
4253 case SMB_INFO_QUERY_EAS_FROM_LIST:
4255 size_t total_ea_len = 0;
4256 struct ea_list *ea_file_list = NULL;
4258 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4260 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4261 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4263 if (!ea_list || (total_ea_len > data_size)) {
4264 data_size = 4;
4265 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4266 break;
4269 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4270 break;
4273 case SMB_INFO_QUERY_ALL_EAS:
4275 /* We have data_size bytes to put EA's into. */
4276 size_t total_ea_len = 0;
4278 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4280 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4281 if (!ea_list || (total_ea_len > data_size)) {
4282 data_size = 4;
4283 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4284 break;
4287 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4288 break;
4291 case SMB_FILE_BASIC_INFORMATION:
4292 case SMB_QUERY_FILE_BASIC_INFO:
4294 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4295 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4296 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4297 } else {
4298 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4299 data_size = 40;
4300 SIVAL(pdata,36,0);
4302 put_long_date_timespec(pdata,create_time_ts);
4303 put_long_date_timespec(pdata+8,atime_ts);
4304 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4305 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4306 SIVAL(pdata,32,mode);
4308 DEBUG(5,("SMB_QFBI - "));
4309 DEBUG(5,("create: %s ", ctime(&create_time)));
4310 DEBUG(5,("access: %s ", ctime(&atime)));
4311 DEBUG(5,("write: %s ", ctime(&mtime)));
4312 DEBUG(5,("change: %s ", ctime(&mtime)));
4313 DEBUG(5,("mode: %x\n", mode));
4314 break;
4316 case SMB_FILE_STANDARD_INFORMATION:
4317 case SMB_QUERY_FILE_STANDARD_INFO:
4319 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4320 data_size = 24;
4321 SOFF_T(pdata,0,allocation_size);
4322 SOFF_T(pdata,8,file_size);
4323 SIVAL(pdata,16,nlink);
4324 SCVAL(pdata,20,delete_pending?1:0);
4325 SCVAL(pdata,21,(mode&aDIR)?1:0);
4326 SSVAL(pdata,22,0); /* Padding. */
4327 break;
4329 case SMB_FILE_EA_INFORMATION:
4330 case SMB_QUERY_FILE_EA_INFO:
4332 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4333 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4334 data_size = 4;
4335 SIVAL(pdata,0,ea_size);
4336 break;
4339 /* Get the 8.3 name - used if NT SMB was negotiated. */
4340 case SMB_QUERY_FILE_ALT_NAME_INFO:
4341 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4343 char mangled_name[13];
4344 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4345 if (!name_to_8_3(base_name,mangled_name,
4346 True,conn->params)) {
4347 reply_nterror(
4348 req,
4349 NT_STATUS_NO_MEMORY);
4351 len = srvstr_push(dstart, req->flags2,
4352 pdata+4, mangled_name,
4353 PTR_DIFF(dend, pdata+4),
4354 STR_UNICODE);
4355 data_size = 4 + len;
4356 SIVAL(pdata,0,len);
4357 break;
4360 case SMB_QUERY_FILE_NAME_INFO:
4362 this must be *exactly* right for ACLs on mapped drives to work
4364 len = srvstr_push(dstart, req->flags2,
4365 pdata+4, dos_fname,
4366 PTR_DIFF(dend, pdata+4),
4367 STR_UNICODE);
4368 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4369 data_size = 4 + len;
4370 SIVAL(pdata,0,len);
4371 break;
4373 case SMB_FILE_ALLOCATION_INFORMATION:
4374 case SMB_QUERY_FILE_ALLOCATION_INFO:
4375 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4376 data_size = 8;
4377 SOFF_T(pdata,0,allocation_size);
4378 break;
4380 case SMB_FILE_END_OF_FILE_INFORMATION:
4381 case SMB_QUERY_FILE_END_OF_FILEINFO:
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4383 data_size = 8;
4384 SOFF_T(pdata,0,file_size);
4385 break;
4387 case SMB_QUERY_FILE_ALL_INFO:
4388 case SMB_FILE_ALL_INFORMATION:
4390 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4391 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4392 put_long_date_timespec(pdata,create_time_ts);
4393 put_long_date_timespec(pdata+8,atime_ts);
4394 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4395 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4396 SIVAL(pdata,32,mode);
4397 SIVAL(pdata,36,0); /* padding. */
4398 pdata += 40;
4399 SOFF_T(pdata,0,allocation_size);
4400 SOFF_T(pdata,8,file_size);
4401 SIVAL(pdata,16,nlink);
4402 SCVAL(pdata,20,delete_pending);
4403 SCVAL(pdata,21,(mode&aDIR)?1:0);
4404 SSVAL(pdata,22,0);
4405 pdata += 24;
4406 SIVAL(pdata,0,ea_size);
4407 pdata += 4; /* EA info */
4408 len = srvstr_push(dstart, req->flags2,
4409 pdata+4, dos_fname,
4410 PTR_DIFF(dend, pdata+4),
4411 STR_UNICODE);
4412 SIVAL(pdata,0,len);
4413 pdata += 4 + len;
4414 data_size = PTR_DIFF(pdata,(*ppdata));
4415 break;
4417 case SMB_FILE_INTERNAL_INFORMATION:
4418 /* This should be an index number - looks like
4419 dev/ino to me :-)
4421 I think this causes us to fail the IFSKIT
4422 BasicFileInformationTest. -tpot */
4424 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4425 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4426 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4427 data_size = 8;
4428 break;
4430 case SMB_FILE_ACCESS_INFORMATION:
4431 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4432 if (fsp) {
4433 SIVAL(pdata,0,fsp->access_mask);
4434 } else {
4435 /* GENERIC_EXECUTE mapping from Windows */
4436 SIVAL(pdata,0,0x12019F);
4438 data_size = 4;
4439 break;
4441 case SMB_FILE_NAME_INFORMATION:
4442 /* Pathname with leading '\'. */
4444 size_t byte_len;
4445 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4446 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4447 SIVAL(pdata,0,byte_len);
4448 data_size = 4 + byte_len;
4449 break;
4452 case SMB_FILE_DISPOSITION_INFORMATION:
4453 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4454 data_size = 1;
4455 SCVAL(pdata,0,delete_pending);
4456 break;
4458 case SMB_FILE_POSITION_INFORMATION:
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4460 data_size = 8;
4461 SOFF_T(pdata,0,pos);
4462 break;
4464 case SMB_FILE_MODE_INFORMATION:
4465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4466 SIVAL(pdata,0,mode);
4467 data_size = 4;
4468 break;
4470 case SMB_FILE_ALIGNMENT_INFORMATION:
4471 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4472 SIVAL(pdata,0,0); /* No alignment needed. */
4473 data_size = 4;
4474 break;
4477 * NT4 server just returns "invalid query" to this - if we try
4478 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4479 * want this. JRA.
4481 /* The first statement above is false - verified using Thursby
4482 * client against NT4 -- gcolley.
4484 case SMB_QUERY_FILE_STREAM_INFO:
4485 case SMB_FILE_STREAM_INFORMATION: {
4486 unsigned int num_streams;
4487 struct stream_struct *streams;
4488 NTSTATUS status;
4490 DEBUG(10,("call_trans2qfilepathinfo: "
4491 "SMB_FILE_STREAM_INFORMATION\n"));
4493 status = SMB_VFS_STREAMINFO(
4494 conn, fsp, fname, talloc_tos(),
4495 &num_streams, &streams);
4497 if (!NT_STATUS_IS_OK(status)) {
4498 DEBUG(10, ("could not get stream info: %s\n",
4499 nt_errstr(status)));
4500 reply_nterror(req, status);
4501 return;
4504 status = marshall_stream_info(num_streams, streams,
4505 pdata, max_data_bytes,
4506 &data_size);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 DEBUG(10, ("marshall_stream_info failed: %s\n",
4510 nt_errstr(status)));
4511 reply_nterror(req, status);
4512 return;
4515 TALLOC_FREE(streams);
4517 break;
4519 case SMB_QUERY_COMPRESSION_INFO:
4520 case SMB_FILE_COMPRESSION_INFORMATION:
4521 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4522 SOFF_T(pdata,0,file_size);
4523 SIVAL(pdata,8,0); /* ??? */
4524 SIVAL(pdata,12,0); /* ??? */
4525 data_size = 16;
4526 break;
4528 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4529 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4530 put_long_date_timespec(pdata,create_time_ts);
4531 put_long_date_timespec(pdata+8,atime_ts);
4532 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4533 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4534 SOFF_T(pdata,32,allocation_size);
4535 SOFF_T(pdata,40,file_size);
4536 SIVAL(pdata,48,mode);
4537 SIVAL(pdata,52,0); /* ??? */
4538 data_size = 56;
4539 break;
4541 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4542 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4543 SIVAL(pdata,0,mode);
4544 SIVAL(pdata,4,0);
4545 data_size = 8;
4546 break;
4549 * CIFS UNIX Extensions.
4552 case SMB_QUERY_FILE_UNIX_BASIC:
4554 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4555 data_size = PTR_DIFF(pdata,(*ppdata));
4558 int i;
4559 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4561 for (i=0; i<100; i++)
4562 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4563 DEBUG(4,("\n"));
4566 break;
4568 case SMB_QUERY_FILE_UNIX_INFO2:
4570 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4571 data_size = PTR_DIFF(pdata,(*ppdata));
4574 int i;
4575 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4577 for (i=0; i<100; i++)
4578 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4579 DEBUG(4,("\n"));
4582 break;
4584 case SMB_QUERY_FILE_UNIX_LINK:
4586 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4588 if (!buffer) {
4589 reply_nterror(req, NT_STATUS_NO_MEMORY);
4590 return;
4593 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4594 #ifdef S_ISLNK
4595 if(!S_ISLNK(sbuf.st_mode)) {
4596 reply_unixerror(req, ERRSRV,
4597 ERRbadlink);
4598 return;
4600 #else
4601 reply_unixerror(req, ERRDOS, ERRbadlink);
4602 return;
4603 #endif
4604 len = SMB_VFS_READLINK(conn,fullpathname,
4605 buffer, PATH_MAX);
4606 if (len == -1) {
4607 reply_unixerror(req, ERRDOS,
4608 ERRnoaccess);
4609 return;
4611 buffer[len] = 0;
4612 len = srvstr_push(dstart, req->flags2,
4613 pdata, buffer,
4614 PTR_DIFF(dend, pdata),
4615 STR_TERMINATE);
4616 pdata += len;
4617 data_size = PTR_DIFF(pdata,(*ppdata));
4619 break;
4622 #if defined(HAVE_POSIX_ACLS)
4623 case SMB_QUERY_POSIX_ACL:
4625 SMB_ACL_T file_acl = NULL;
4626 SMB_ACL_T def_acl = NULL;
4627 uint16 num_file_acls = 0;
4628 uint16 num_def_acls = 0;
4630 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4631 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4632 } else {
4633 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4636 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4637 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4638 fname ));
4639 reply_nterror(
4640 req,
4641 NT_STATUS_NOT_IMPLEMENTED);
4642 return;
4645 if (S_ISDIR(sbuf.st_mode)) {
4646 if (fsp && fsp->is_directory) {
4647 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4648 } else {
4649 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4651 def_acl = free_empty_sys_acl(conn, def_acl);
4654 num_file_acls = count_acl_entries(conn, file_acl);
4655 num_def_acls = count_acl_entries(conn, def_acl);
4657 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4658 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4659 data_size,
4660 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4661 SMB_POSIX_ACL_HEADER_SIZE) ));
4662 if (file_acl) {
4663 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4665 if (def_acl) {
4666 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4668 reply_nterror(
4669 req,
4670 NT_STATUS_BUFFER_TOO_SMALL);
4671 return;
4674 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4675 SSVAL(pdata,2,num_file_acls);
4676 SSVAL(pdata,4,num_def_acls);
4677 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4678 if (file_acl) {
4679 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4681 if (def_acl) {
4682 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4684 reply_nterror(
4685 req, NT_STATUS_INTERNAL_ERROR);
4686 return;
4688 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4689 if (file_acl) {
4690 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692 if (def_acl) {
4693 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4695 reply_nterror(
4696 req,
4697 NT_STATUS_INTERNAL_ERROR);
4698 return;
4701 if (file_acl) {
4702 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4704 if (def_acl) {
4705 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4707 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4708 break;
4710 #endif
4713 case SMB_QUERY_POSIX_LOCK:
4715 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4716 SMB_BIG_UINT count;
4717 SMB_BIG_UINT offset;
4718 uint32 lock_pid;
4719 enum brl_type lock_type;
4721 if (total_data != POSIX_LOCK_DATA_SIZE) {
4722 reply_nterror(
4723 req, NT_STATUS_INVALID_PARAMETER);
4724 return;
4727 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4728 case POSIX_LOCK_TYPE_READ:
4729 lock_type = READ_LOCK;
4730 break;
4731 case POSIX_LOCK_TYPE_WRITE:
4732 lock_type = WRITE_LOCK;
4733 break;
4734 case POSIX_LOCK_TYPE_UNLOCK:
4735 default:
4736 /* There's no point in asking for an unlock... */
4737 reply_nterror(
4738 req,
4739 NT_STATUS_INVALID_PARAMETER);
4740 return;
4743 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4744 #if defined(HAVE_LONGLONG)
4745 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4746 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4747 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4748 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4749 #else /* HAVE_LONGLONG */
4750 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4751 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4752 #endif /* HAVE_LONGLONG */
4754 status = query_lock(fsp,
4755 &lock_pid,
4756 &count,
4757 &offset,
4758 &lock_type,
4759 POSIX_LOCK);
4761 if (ERROR_WAS_LOCK_DENIED(status)) {
4762 /* Here we need to report who has it locked... */
4763 data_size = POSIX_LOCK_DATA_SIZE;
4765 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4766 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4767 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4768 #if defined(HAVE_LONGLONG)
4769 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4770 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4771 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4772 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4773 #else /* HAVE_LONGLONG */
4774 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4775 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4776 #endif /* HAVE_LONGLONG */
4778 } else if (NT_STATUS_IS_OK(status)) {
4779 /* For success we just return a copy of what we sent
4780 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4781 data_size = POSIX_LOCK_DATA_SIZE;
4782 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4783 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4784 } else {
4785 reply_nterror(req, status);
4786 return;
4788 break;
4791 default:
4792 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4793 return;
4796 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4797 max_data_bytes);
4799 return;
4802 /****************************************************************************
4803 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4804 code.
4805 ****************************************************************************/
4807 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4808 connection_struct *conn,
4809 const char *oldname_in,
4810 const char *newname_in)
4812 SMB_STRUCT_STAT sbuf1, sbuf2;
4813 char *last_component_oldname = NULL;
4814 char *last_component_newname = NULL;
4815 char *oldname = NULL;
4816 char *newname = NULL;
4817 NTSTATUS status = NT_STATUS_OK;
4819 ZERO_STRUCT(sbuf1);
4820 ZERO_STRUCT(sbuf2);
4822 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4823 &last_component_oldname, &sbuf1);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 return status;
4828 status = check_name(conn, oldname);
4829 if (!NT_STATUS_IS_OK(status)) {
4830 return status;
4833 /* source must already exist. */
4834 if (!VALID_STAT(sbuf1)) {
4835 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4838 status = unix_convert(ctx, conn, newname_in, False, &newname,
4839 &last_component_newname, &sbuf2);
4840 if (!NT_STATUS_IS_OK(status)) {
4841 return status;
4844 status = check_name(conn, newname);
4845 if (!NT_STATUS_IS_OK(status)) {
4846 return status;
4849 /* Disallow if newname already exists. */
4850 if (VALID_STAT(sbuf2)) {
4851 return NT_STATUS_OBJECT_NAME_COLLISION;
4854 /* No links from a directory. */
4855 if (S_ISDIR(sbuf1.st_mode)) {
4856 return NT_STATUS_FILE_IS_A_DIRECTORY;
4859 /* Ensure this is within the share. */
4860 status = check_reduced_name(conn, oldname);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 return status;
4865 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4867 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4868 status = map_nt_error_from_unix(errno);
4869 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4870 nt_errstr(status), newname, oldname));
4873 return status;
4876 /****************************************************************************
4877 Deal with setting the time from any of the setfilepathinfo functions.
4878 ****************************************************************************/
4880 NTSTATUS smb_set_file_time(connection_struct *conn,
4881 files_struct *fsp,
4882 const char *fname,
4883 const SMB_STRUCT_STAT *psbuf,
4884 struct timespec ts[2],
4885 bool setting_write_time)
4887 uint32 action =
4888 FILE_NOTIFY_CHANGE_LAST_ACCESS
4889 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4891 if (!VALID_STAT(*psbuf)) {
4892 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4895 /* get some defaults (no modifications) if any info is zero or -1. */
4896 if (null_timespec(ts[0])) {
4897 ts[0] = get_atimespec(psbuf);
4898 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4901 if (null_timespec(ts[1])) {
4902 ts[1] = get_mtimespec(psbuf);
4903 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4906 if (!setting_write_time) {
4907 /* ts[1] comes from change time, not write time. */
4908 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4911 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4912 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4915 * Try and set the times of this file if
4916 * they are different from the current values.
4920 struct timespec mts = get_mtimespec(psbuf);
4921 struct timespec ats = get_atimespec(psbuf);
4922 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4923 return NT_STATUS_OK;
4927 if (setting_write_time) {
4929 * This was a Windows setfileinfo on an open file.
4930 * NT does this a lot. We also need to
4931 * set the time here, as it can be read by
4932 * FindFirst/FindNext and with the patch for bug #2045
4933 * in smbd/fileio.c it ensures that this timestamp is
4934 * kept sticky even after a write. We save the request
4935 * away and will set it on file close and after a write. JRA.
4938 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4939 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4941 if (fsp != NULL) {
4942 if (fsp->base_fsp) {
4943 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4944 } else {
4945 set_sticky_write_time_fsp(fsp, ts[1]);
4947 } else {
4948 set_sticky_write_time_path(conn, fname,
4949 vfs_file_id_from_sbuf(conn, psbuf),
4950 ts[1]);
4954 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4956 if (fsp && fsp->base_fsp) {
4957 fname = fsp->base_fsp->fsp_name;
4960 if(file_ntimes(conn, fname, ts)!=0) {
4961 return map_nt_error_from_unix(errno);
4963 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4965 return NT_STATUS_OK;
4968 /****************************************************************************
4969 Deal with setting the dosmode from any of the setfilepathinfo functions.
4970 ****************************************************************************/
4972 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4973 files_struct *fsp,
4974 const char *fname,
4975 SMB_STRUCT_STAT *psbuf,
4976 uint32 dosmode)
4978 if (!VALID_STAT(*psbuf)) {
4979 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4982 if (fsp) {
4983 if (fsp->base_fsp) {
4984 fname = fsp->base_fsp->fsp_name;
4985 } else {
4986 fname = fsp->fsp_name;
4990 if (dosmode) {
4991 if (S_ISDIR(psbuf->st_mode)) {
4992 dosmode |= aDIR;
4993 } else {
4994 dosmode &= ~aDIR;
4998 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5000 /* check the mode isn't different, before changing it */
5001 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5003 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5004 fname, (unsigned int)dosmode ));
5006 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5007 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5008 fname, strerror(errno)));
5009 return map_nt_error_from_unix(errno);
5012 return NT_STATUS_OK;
5015 /****************************************************************************
5016 Deal with setting the size from any of the setfilepathinfo functions.
5017 ****************************************************************************/
5019 static NTSTATUS smb_set_file_size(connection_struct *conn,
5020 struct smb_request *req,
5021 files_struct *fsp,
5022 const char *fname,
5023 SMB_STRUCT_STAT *psbuf,
5024 SMB_OFF_T size)
5026 NTSTATUS status = NT_STATUS_OK;
5027 files_struct *new_fsp = NULL;
5029 if (!VALID_STAT(*psbuf)) {
5030 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5033 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5035 if (size == get_file_size(*psbuf)) {
5036 return NT_STATUS_OK;
5039 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5040 fname, (double)size ));
5042 if (fsp && fsp->fh->fd != -1) {
5043 /* Handle based call. */
5044 if (vfs_set_filelen(fsp, size) == -1) {
5045 return map_nt_error_from_unix(errno);
5047 trigger_write_time_update_immediate(fsp);
5048 return NT_STATUS_OK;
5051 status = open_file_ntcreate(conn, req, fname, psbuf,
5052 FILE_WRITE_ATTRIBUTES,
5053 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5054 FILE_OPEN,
5056 FILE_ATTRIBUTE_NORMAL,
5057 FORCE_OPLOCK_BREAK_TO_NONE,
5058 NULL, &new_fsp);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 /* NB. We check for open_was_deferred in the caller. */
5062 return status;
5065 if (vfs_set_filelen(new_fsp, size) == -1) {
5066 status = map_nt_error_from_unix(errno);
5067 close_file(new_fsp,NORMAL_CLOSE);
5068 return status;
5071 trigger_write_time_update_immediate(new_fsp);
5072 close_file(new_fsp,NORMAL_CLOSE);
5073 return NT_STATUS_OK;
5076 /****************************************************************************
5077 Deal with SMB_INFO_SET_EA.
5078 ****************************************************************************/
5080 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5081 const char *pdata,
5082 int total_data,
5083 files_struct *fsp,
5084 const char *fname)
5086 struct ea_list *ea_list = NULL;
5087 TALLOC_CTX *ctx = NULL;
5088 NTSTATUS status = NT_STATUS_OK;
5090 if (total_data < 10) {
5092 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5093 length. They seem to have no effect. Bug #3212. JRA */
5095 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5096 /* We're done. We only get EA info in this call. */
5097 return NT_STATUS_OK;
5100 return NT_STATUS_INVALID_PARAMETER;
5103 if (IVAL(pdata,0) > total_data) {
5104 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5105 IVAL(pdata,0), (unsigned int)total_data));
5106 return NT_STATUS_INVALID_PARAMETER;
5109 ctx = talloc_tos();
5110 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5111 if (!ea_list) {
5112 return NT_STATUS_INVALID_PARAMETER;
5114 status = set_ea(conn, fsp, fname, ea_list);
5116 return status;
5119 /****************************************************************************
5120 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5121 ****************************************************************************/
5123 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5124 const char *pdata,
5125 int total_data,
5126 files_struct *fsp,
5127 const char *fname,
5128 SMB_STRUCT_STAT *psbuf)
5130 NTSTATUS status = NT_STATUS_OK;
5131 bool delete_on_close;
5132 uint32 dosmode = 0;
5134 if (total_data < 1) {
5135 return NT_STATUS_INVALID_PARAMETER;
5138 if (fsp == NULL) {
5139 return NT_STATUS_INVALID_HANDLE;
5142 delete_on_close = (CVAL(pdata,0) ? True : False);
5143 dosmode = dos_mode(conn, fname, psbuf);
5145 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5146 "delete_on_close = %u\n",
5147 fsp->fsp_name,
5148 (unsigned int)dosmode,
5149 (unsigned int)delete_on_close ));
5151 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5153 if (!NT_STATUS_IS_OK(status)) {
5154 return status;
5157 /* The set is across all open files on this dev/inode pair. */
5158 if (!set_delete_on_close(fsp, delete_on_close,
5159 &conn->server_info->utok)) {
5160 return NT_STATUS_ACCESS_DENIED;
5162 return NT_STATUS_OK;
5165 /****************************************************************************
5166 Deal with SMB_FILE_POSITION_INFORMATION.
5167 ****************************************************************************/
5169 static NTSTATUS smb_file_position_information(connection_struct *conn,
5170 const char *pdata,
5171 int total_data,
5172 files_struct *fsp)
5174 SMB_BIG_UINT position_information;
5176 if (total_data < 8) {
5177 return NT_STATUS_INVALID_PARAMETER;
5180 if (fsp == NULL) {
5181 /* Ignore on pathname based set. */
5182 return NT_STATUS_OK;
5185 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5186 #ifdef LARGE_SMB_OFF_T
5187 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5188 #else /* LARGE_SMB_OFF_T */
5189 if (IVAL(pdata,4) != 0) {
5190 /* more than 32 bits? */
5191 return NT_STATUS_INVALID_PARAMETER;
5193 #endif /* LARGE_SMB_OFF_T */
5195 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5196 fsp->fsp_name, (double)position_information ));
5197 fsp->fh->position_information = position_information;
5198 return NT_STATUS_OK;
5201 /****************************************************************************
5202 Deal with SMB_FILE_MODE_INFORMATION.
5203 ****************************************************************************/
5205 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5206 const char *pdata,
5207 int total_data)
5209 uint32 mode;
5211 if (total_data < 4) {
5212 return NT_STATUS_INVALID_PARAMETER;
5214 mode = IVAL(pdata,0);
5215 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5216 return NT_STATUS_INVALID_PARAMETER;
5218 return NT_STATUS_OK;
5221 /****************************************************************************
5222 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5223 ****************************************************************************/
5225 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5226 struct smb_request *req,
5227 const char *pdata,
5228 int total_data,
5229 const char *fname)
5231 char *link_target = NULL;
5232 const char *newname = fname;
5233 TALLOC_CTX *ctx = talloc_tos();
5235 /* Set a symbolic link. */
5236 /* Don't allow this if follow links is false. */
5238 if (total_data == 0) {
5239 return NT_STATUS_INVALID_PARAMETER;
5242 if (!lp_symlinks(SNUM(conn))) {
5243 return NT_STATUS_ACCESS_DENIED;
5246 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5247 total_data, STR_TERMINATE);
5249 if (!link_target) {
5250 return NT_STATUS_INVALID_PARAMETER;
5253 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5254 newname, link_target ));
5256 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5257 return map_nt_error_from_unix(errno);
5260 return NT_STATUS_OK;
5263 /****************************************************************************
5264 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5265 ****************************************************************************/
5267 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5268 struct smb_request *req,
5269 const char *pdata, int total_data,
5270 const char *fname)
5272 char *oldname = NULL;
5273 TALLOC_CTX *ctx = talloc_tos();
5274 NTSTATUS status = NT_STATUS_OK;
5276 /* Set a hard link. */
5277 if (total_data == 0) {
5278 return NT_STATUS_INVALID_PARAMETER;
5281 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5282 total_data, STR_TERMINATE, &status);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 return status;
5287 status = resolve_dfspath(ctx, conn,
5288 req->flags2 & FLAGS2_DFS_PATHNAMES,
5289 oldname,
5290 &oldname);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 return status;
5295 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5296 fname, oldname));
5298 return hardlink_internals(ctx, conn, oldname, fname);
5301 /****************************************************************************
5302 Deal with SMB_FILE_RENAME_INFORMATION.
5303 ****************************************************************************/
5305 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5306 struct smb_request *req,
5307 const char *pdata,
5308 int total_data,
5309 files_struct *fsp,
5310 const char *fname)
5312 bool overwrite;
5313 uint32 root_fid;
5314 uint32 len;
5315 char *newname = NULL;
5316 char *base_name = NULL;
5317 bool dest_has_wcard = False;
5318 SMB_STRUCT_STAT sbuf;
5319 char *newname_last_component = NULL;
5320 NTSTATUS status = NT_STATUS_OK;
5321 char *p;
5322 TALLOC_CTX *ctx = talloc_tos();
5324 if (total_data < 13) {
5325 return NT_STATUS_INVALID_PARAMETER;
5328 ZERO_STRUCT(sbuf);
5330 overwrite = (CVAL(pdata,0) ? True : False);
5331 root_fid = IVAL(pdata,4);
5332 len = IVAL(pdata,8);
5334 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5335 return NT_STATUS_INVALID_PARAMETER;
5338 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5339 len, 0, &status,
5340 &dest_has_wcard);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 return status;
5345 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5346 newname));
5348 status = resolve_dfspath_wcard(ctx, conn,
5349 req->flags2 & FLAGS2_DFS_PATHNAMES,
5350 newname,
5351 &newname,
5352 &dest_has_wcard);
5353 if (!NT_STATUS_IS_OK(status)) {
5354 return status;
5357 /* Check the new name has no '/' characters. */
5358 if (strchr_m(newname, '/')) {
5359 return NT_STATUS_NOT_SUPPORTED;
5362 if (fsp && fsp->base_fsp) {
5363 /* newname must be a stream name. */
5364 if (newname[0] != ':') {
5365 return NT_STATUS_NOT_SUPPORTED;
5367 base_name = talloc_asprintf(ctx, "%s%s",
5368 fsp->base_fsp->fsp_name,
5369 newname);
5370 if (!base_name) {
5371 return NT_STATUS_NO_MEMORY;
5373 } else {
5374 /* newname must *not* be a stream name. */
5375 if (is_ntfs_stream_name(newname)) {
5376 return NT_STATUS_NOT_SUPPORTED;
5379 /* Create the base directory. */
5380 base_name = talloc_strdup(ctx, fname);
5381 if (!base_name) {
5382 return NT_STATUS_NO_MEMORY;
5384 p = strrchr_m(base_name, '/');
5385 if (p) {
5386 p[1] = '\0';
5387 } else {
5388 base_name = talloc_strdup(ctx, "./");
5389 if (!base_name) {
5390 return NT_STATUS_NO_MEMORY;
5393 /* Append the new name. */
5394 base_name = talloc_asprintf_append(base_name,
5395 "%s",
5396 newname);
5397 if (!base_name) {
5398 return NT_STATUS_NO_MEMORY;
5401 status = unix_convert(ctx, conn, newname, False,
5402 &newname,
5403 &newname_last_component,
5404 &sbuf);
5406 /* If an error we expect this to be
5407 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5409 if (!NT_STATUS_IS_OK(status)
5410 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5411 status)) {
5412 return status;
5416 if (fsp) {
5417 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5418 fsp->fnum, fsp->fsp_name, base_name ));
5419 status = rename_internals_fsp(conn, fsp, base_name,
5420 newname_last_component, 0,
5421 overwrite);
5422 } else {
5423 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5424 fname, base_name ));
5425 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5426 overwrite, False, dest_has_wcard,
5427 FILE_WRITE_ATTRIBUTES);
5430 return status;
5433 /****************************************************************************
5434 Deal with SMB_SET_POSIX_ACL.
5435 ****************************************************************************/
5437 #if defined(HAVE_POSIX_ACLS)
5438 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5439 const char *pdata,
5440 int total_data,
5441 files_struct *fsp,
5442 const char *fname,
5443 SMB_STRUCT_STAT *psbuf)
5445 uint16 posix_acl_version;
5446 uint16 num_file_acls;
5447 uint16 num_def_acls;
5448 bool valid_file_acls = True;
5449 bool valid_def_acls = True;
5451 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5452 return NT_STATUS_INVALID_PARAMETER;
5454 posix_acl_version = SVAL(pdata,0);
5455 num_file_acls = SVAL(pdata,2);
5456 num_def_acls = SVAL(pdata,4);
5458 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5459 valid_file_acls = False;
5460 num_file_acls = 0;
5463 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5464 valid_def_acls = False;
5465 num_def_acls = 0;
5468 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5469 return NT_STATUS_INVALID_PARAMETER;
5472 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5473 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5474 return NT_STATUS_INVALID_PARAMETER;
5477 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5478 fname ? fname : fsp->fsp_name,
5479 (unsigned int)num_file_acls,
5480 (unsigned int)num_def_acls));
5482 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5483 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5484 return map_nt_error_from_unix(errno);
5487 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5488 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5489 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5490 return map_nt_error_from_unix(errno);
5492 return NT_STATUS_OK;
5494 #endif
5496 /****************************************************************************
5497 Deal with SMB_SET_POSIX_LOCK.
5498 ****************************************************************************/
5500 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5501 const struct smb_request *req,
5502 const char *pdata,
5503 int total_data,
5504 files_struct *fsp)
5506 SMB_BIG_UINT count;
5507 SMB_BIG_UINT offset;
5508 uint32 lock_pid;
5509 bool blocking_lock = False;
5510 enum brl_type lock_type;
5512 NTSTATUS status = NT_STATUS_OK;
5514 if (fsp == NULL || fsp->fh->fd == -1) {
5515 return NT_STATUS_INVALID_HANDLE;
5518 if (total_data != POSIX_LOCK_DATA_SIZE) {
5519 return NT_STATUS_INVALID_PARAMETER;
5522 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5523 case POSIX_LOCK_TYPE_READ:
5524 lock_type = READ_LOCK;
5525 break;
5526 case POSIX_LOCK_TYPE_WRITE:
5527 /* Return the right POSIX-mappable error code for files opened read-only. */
5528 if (!fsp->can_write) {
5529 return NT_STATUS_INVALID_HANDLE;
5531 lock_type = WRITE_LOCK;
5532 break;
5533 case POSIX_LOCK_TYPE_UNLOCK:
5534 lock_type = UNLOCK_LOCK;
5535 break;
5536 default:
5537 return NT_STATUS_INVALID_PARAMETER;
5540 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5541 blocking_lock = False;
5542 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5543 blocking_lock = True;
5544 } else {
5545 return NT_STATUS_INVALID_PARAMETER;
5548 if (!lp_blocking_locks(SNUM(conn))) {
5549 blocking_lock = False;
5552 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5553 #if defined(HAVE_LONGLONG)
5554 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5555 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5556 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5557 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5558 #else /* HAVE_LONGLONG */
5559 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5560 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5561 #endif /* HAVE_LONGLONG */
5563 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5564 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5565 fsp->fsp_name,
5566 (unsigned int)lock_type,
5567 (unsigned int)lock_pid,
5568 (double)count,
5569 (double)offset ));
5571 if (lock_type == UNLOCK_LOCK) {
5572 status = do_unlock(smbd_messaging_context(),
5573 fsp,
5574 lock_pid,
5575 count,
5576 offset,
5577 POSIX_LOCK);
5578 } else {
5579 uint32 block_smbpid;
5581 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5582 fsp,
5583 lock_pid,
5584 count,
5585 offset,
5586 lock_type,
5587 POSIX_LOCK,
5588 blocking_lock,
5589 &status,
5590 &block_smbpid);
5592 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5594 * A blocking lock was requested. Package up
5595 * this smb into a queued request and push it
5596 * onto the blocking lock queue.
5598 if(push_blocking_lock_request(br_lck,
5599 req,
5600 fsp,
5601 -1, /* infinite timeout. */
5603 lock_pid,
5604 lock_type,
5605 POSIX_LOCK,
5606 offset,
5607 count,
5608 block_smbpid)) {
5609 TALLOC_FREE(br_lck);
5610 return status;
5613 TALLOC_FREE(br_lck);
5616 return status;
5619 /****************************************************************************
5620 Deal with SMB_INFO_STANDARD.
5621 ****************************************************************************/
5623 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5624 const char *pdata,
5625 int total_data,
5626 files_struct *fsp,
5627 const char *fname,
5628 const SMB_STRUCT_STAT *psbuf)
5630 struct timespec ts[2];
5632 if (total_data < 12) {
5633 return NT_STATUS_INVALID_PARAMETER;
5636 /* access time */
5637 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5638 /* write time */
5639 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5641 DEBUG(10,("smb_set_info_standard: file %s\n",
5642 fname ? fname : fsp->fsp_name ));
5644 return smb_set_file_time(conn,
5645 fsp,
5646 fname,
5647 psbuf,
5649 true);
5652 /****************************************************************************
5653 Deal with SMB_SET_FILE_BASIC_INFO.
5654 ****************************************************************************/
5656 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5657 const char *pdata,
5658 int total_data,
5659 files_struct *fsp,
5660 const char *fname,
5661 SMB_STRUCT_STAT *psbuf)
5663 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5664 struct timespec write_time;
5665 struct timespec changed_time;
5666 uint32 dosmode = 0;
5667 struct timespec ts[2];
5668 NTSTATUS status = NT_STATUS_OK;
5669 bool setting_write_time = true;
5671 if (total_data < 36) {
5672 return NT_STATUS_INVALID_PARAMETER;
5675 /* Set the attributes */
5676 dosmode = IVAL(pdata,32);
5677 status = smb_set_file_dosmode(conn,
5678 fsp,
5679 fname,
5680 psbuf,
5681 dosmode);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 return status;
5687 /* Ignore create time at offset pdata. */
5689 /* access time */
5690 ts[0] = interpret_long_date(pdata+8);
5692 write_time = interpret_long_date(pdata+16);
5693 changed_time = interpret_long_date(pdata+24);
5695 /* mtime */
5696 ts[1] = timespec_min(&write_time, &changed_time);
5698 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5699 ts[1] = write_time;
5702 /* Prefer a defined time to an undefined one. */
5703 if (null_timespec(ts[1])) {
5704 if (null_timespec(write_time)) {
5705 ts[1] = changed_time;
5706 setting_write_time = false;
5707 } else {
5708 ts[1] = write_time;
5712 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5713 fname ? fname : fsp->fsp_name ));
5715 return smb_set_file_time(conn,
5716 fsp,
5717 fname,
5718 psbuf,
5720 setting_write_time);
5723 /****************************************************************************
5724 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5725 ****************************************************************************/
5727 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5728 struct smb_request *req,
5729 const char *pdata,
5730 int total_data,
5731 files_struct *fsp,
5732 const char *fname,
5733 SMB_STRUCT_STAT *psbuf)
5735 SMB_BIG_UINT allocation_size = 0;
5736 NTSTATUS status = NT_STATUS_OK;
5737 files_struct *new_fsp = NULL;
5739 if (!VALID_STAT(*psbuf)) {
5740 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5743 if (total_data < 8) {
5744 return NT_STATUS_INVALID_PARAMETER;
5747 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5748 #ifdef LARGE_SMB_OFF_T
5749 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5750 #else /* LARGE_SMB_OFF_T */
5751 if (IVAL(pdata,4) != 0) {
5752 /* more than 32 bits? */
5753 return NT_STATUS_INVALID_PARAMETER;
5755 #endif /* LARGE_SMB_OFF_T */
5757 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5758 fname, (double)allocation_size ));
5760 if (allocation_size) {
5761 allocation_size = smb_roundup(conn, allocation_size);
5764 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5765 fname, (double)allocation_size ));
5767 if (fsp && fsp->fh->fd != -1) {
5768 /* Open file handle. */
5769 /* Only change if needed. */
5770 if (allocation_size != get_file_size(*psbuf)) {
5771 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5772 return map_nt_error_from_unix(errno);
5775 /* But always update the time. */
5777 * This is equivalent to a write. Ensure it's seen immediately
5778 * if there are no pending writes.
5780 trigger_write_time_update_immediate(fsp);
5781 return NT_STATUS_OK;
5784 /* Pathname or stat or directory file. */
5786 status = open_file_ntcreate(conn, req, fname, psbuf,
5787 FILE_WRITE_DATA,
5788 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5789 FILE_OPEN,
5791 FILE_ATTRIBUTE_NORMAL,
5792 FORCE_OPLOCK_BREAK_TO_NONE,
5793 NULL, &new_fsp);
5795 if (!NT_STATUS_IS_OK(status)) {
5796 /* NB. We check for open_was_deferred in the caller. */
5797 return status;
5800 /* Only change if needed. */
5801 if (allocation_size != get_file_size(*psbuf)) {
5802 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5803 status = map_nt_error_from_unix(errno);
5804 close_file(new_fsp,NORMAL_CLOSE);
5805 return status;
5809 /* Changing the allocation size should set the last mod time. */
5811 * This is equivalent to a write. Ensure it's seen immediately
5812 * if there are no pending writes.
5814 trigger_write_time_update_immediate(new_fsp);
5816 close_file(new_fsp,NORMAL_CLOSE);
5817 return NT_STATUS_OK;
5820 /****************************************************************************
5821 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5822 ****************************************************************************/
5824 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5825 struct smb_request *req,
5826 const char *pdata,
5827 int total_data,
5828 files_struct *fsp,
5829 const char *fname,
5830 SMB_STRUCT_STAT *psbuf)
5832 SMB_OFF_T size;
5834 if (total_data < 8) {
5835 return NT_STATUS_INVALID_PARAMETER;
5838 size = IVAL(pdata,0);
5839 #ifdef LARGE_SMB_OFF_T
5840 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5841 #else /* LARGE_SMB_OFF_T */
5842 if (IVAL(pdata,4) != 0) {
5843 /* more than 32 bits? */
5844 return NT_STATUS_INVALID_PARAMETER;
5846 #endif /* LARGE_SMB_OFF_T */
5847 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5848 "file %s to %.0f\n", fname, (double)size ));
5850 return smb_set_file_size(conn, req,
5851 fsp,
5852 fname,
5853 psbuf,
5854 size);
5857 /****************************************************************************
5858 Allow a UNIX info mknod.
5859 ****************************************************************************/
5861 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5862 const char *pdata,
5863 int total_data,
5864 const char *fname,
5865 SMB_STRUCT_STAT *psbuf)
5867 uint32 file_type = IVAL(pdata,56);
5868 #if defined(HAVE_MAKEDEV)
5869 uint32 dev_major = IVAL(pdata,60);
5870 uint32 dev_minor = IVAL(pdata,68);
5871 #endif
5872 SMB_DEV_T dev = (SMB_DEV_T)0;
5873 uint32 raw_unixmode = IVAL(pdata,84);
5874 NTSTATUS status;
5875 mode_t unixmode;
5877 if (total_data < 100) {
5878 return NT_STATUS_INVALID_PARAMETER;
5881 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5882 if (!NT_STATUS_IS_OK(status)) {
5883 return status;
5886 #if defined(HAVE_MAKEDEV)
5887 dev = makedev(dev_major, dev_minor);
5888 #endif
5890 switch (file_type) {
5891 #if defined(S_IFIFO)
5892 case UNIX_TYPE_FIFO:
5893 unixmode |= S_IFIFO;
5894 break;
5895 #endif
5896 #if defined(S_IFSOCK)
5897 case UNIX_TYPE_SOCKET:
5898 unixmode |= S_IFSOCK;
5899 break;
5900 #endif
5901 #if defined(S_IFCHR)
5902 case UNIX_TYPE_CHARDEV:
5903 unixmode |= S_IFCHR;
5904 break;
5905 #endif
5906 #if defined(S_IFBLK)
5907 case UNIX_TYPE_BLKDEV:
5908 unixmode |= S_IFBLK;
5909 break;
5910 #endif
5911 default:
5912 return NT_STATUS_INVALID_PARAMETER;
5915 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5916 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5918 /* Ok - do the mknod. */
5919 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5920 return map_nt_error_from_unix(errno);
5923 /* If any of the other "set" calls fail we
5924 * don't want to end up with a half-constructed mknod.
5927 if (lp_inherit_perms(SNUM(conn))) {
5928 inherit_access_posix_acl(
5929 conn, parent_dirname(fname),
5930 fname, unixmode);
5933 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5934 status = map_nt_error_from_unix(errno);
5935 SMB_VFS_UNLINK(conn,fname);
5936 return status;
5938 return NT_STATUS_OK;
5941 /****************************************************************************
5942 Deal with SMB_SET_FILE_UNIX_BASIC.
5943 ****************************************************************************/
5945 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5946 struct smb_request *req,
5947 const char *pdata,
5948 int total_data,
5949 files_struct *fsp,
5950 const char *fname,
5951 SMB_STRUCT_STAT *psbuf)
5953 struct timespec ts[2];
5954 uint32 raw_unixmode;
5955 mode_t unixmode;
5956 SMB_OFF_T size = 0;
5957 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5958 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5959 NTSTATUS status = NT_STATUS_OK;
5960 bool delete_on_fail = False;
5961 enum perm_type ptype;
5962 files_struct *all_fsps = NULL;
5963 bool modify_mtime = true;
5964 struct file_id id;
5966 if (total_data < 100) {
5967 return NT_STATUS_INVALID_PARAMETER;
5970 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5971 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5972 size=IVAL(pdata,0); /* first 8 Bytes are size */
5973 #ifdef LARGE_SMB_OFF_T
5974 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5975 #else /* LARGE_SMB_OFF_T */
5976 if (IVAL(pdata,4) != 0) {
5977 /* more than 32 bits? */
5978 return NT_STATUS_INVALID_PARAMETER;
5980 #endif /* LARGE_SMB_OFF_T */
5983 ts[0] = interpret_long_date(pdata+24); /* access_time */
5984 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5985 set_owner = (uid_t)IVAL(pdata,40);
5986 set_grp = (gid_t)IVAL(pdata,48);
5987 raw_unixmode = IVAL(pdata,84);
5989 if (VALID_STAT(*psbuf)) {
5990 if (S_ISDIR(psbuf->st_mode)) {
5991 ptype = PERM_EXISTING_DIR;
5992 } else {
5993 ptype = PERM_EXISTING_FILE;
5995 } else {
5996 ptype = PERM_NEW_FILE;
5999 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6000 if (!NT_STATUS_IS_OK(status)) {
6001 return status;
6004 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6005 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6006 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6008 if (!VALID_STAT(*psbuf)) {
6010 * The only valid use of this is to create character and block
6011 * devices, and named pipes. This is deprecated (IMHO) and
6012 * a new info level should be used for mknod. JRA.
6015 status = smb_unix_mknod(conn,
6016 pdata,
6017 total_data,
6018 fname,
6019 psbuf);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 return status;
6024 /* Ensure we don't try and change anything else. */
6025 raw_unixmode = SMB_MODE_NO_CHANGE;
6026 size = get_file_size(*psbuf);
6027 ts[0] = get_atimespec(psbuf);
6028 ts[1] = get_mtimespec(psbuf);
6030 * We continue here as we might want to change the
6031 * owner uid/gid.
6033 delete_on_fail = True;
6036 #if 1
6037 /* Horrible backwards compatibility hack as an old server bug
6038 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6039 * */
6041 if (!size) {
6042 size = get_file_size(*psbuf);
6044 #endif
6047 * Deal with the UNIX specific mode set.
6050 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6051 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6052 (unsigned int)unixmode, fname ));
6053 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6054 return map_nt_error_from_unix(errno);
6059 * Deal with the UNIX specific uid set.
6062 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6063 int ret;
6065 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6066 (unsigned int)set_owner, fname ));
6068 if (S_ISLNK(psbuf->st_mode)) {
6069 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6070 } else {
6071 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6074 if (ret != 0) {
6075 status = map_nt_error_from_unix(errno);
6076 if (delete_on_fail) {
6077 SMB_VFS_UNLINK(conn,fname);
6079 return status;
6084 * Deal with the UNIX specific gid set.
6087 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6089 (unsigned int)set_owner, fname ));
6090 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6091 status = map_nt_error_from_unix(errno);
6092 if (delete_on_fail) {
6093 SMB_VFS_UNLINK(conn,fname);
6095 return status;
6099 /* Deal with any size changes. */
6101 status = smb_set_file_size(conn, req,
6102 fsp,
6103 fname,
6104 psbuf,
6105 size);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 return status;
6110 /* Deal with any time changes. */
6111 id = vfs_file_id_from_sbuf(conn, psbuf);
6112 for(all_fsps = file_find_di_first(id); all_fsps;
6113 all_fsps = file_find_di_next(all_fsps)) {
6115 * We're setting the time explicitly for UNIX.
6116 * Cancel any pending changes over all handles.
6118 all_fsps->update_write_time_on_close = false;
6119 TALLOC_FREE(all_fsps->update_write_time_event);
6123 * Override the "setting_write_time"
6124 * parameter here as it almost does what
6125 * we need. Just remember if we modified
6126 * mtime and send the notify ourselves.
6128 if (null_timespec(ts[1])) {
6129 modify_mtime = false;
6132 status = smb_set_file_time(conn,
6133 fsp,
6134 fname,
6135 psbuf,
6137 false);
6139 if (modify_mtime) {
6140 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6141 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6143 return status;
6146 /****************************************************************************
6147 Deal with SMB_SET_FILE_UNIX_INFO2.
6148 ****************************************************************************/
6150 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6151 struct smb_request *req,
6152 const char *pdata,
6153 int total_data,
6154 files_struct *fsp,
6155 const char *fname,
6156 SMB_STRUCT_STAT *psbuf)
6158 NTSTATUS status;
6159 uint32 smb_fflags;
6160 uint32 smb_fmask;
6162 if (total_data < 116) {
6163 return NT_STATUS_INVALID_PARAMETER;
6166 /* Start by setting all the fields that are common between UNIX_BASIC
6167 * and UNIX_INFO2.
6169 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6170 fsp, fname, psbuf);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 return status;
6175 smb_fflags = IVAL(pdata, 108);
6176 smb_fmask = IVAL(pdata, 112);
6178 /* NB: We should only attempt to alter the file flags if the client
6179 * sends a non-zero mask.
6181 if (smb_fmask != 0) {
6182 int stat_fflags = 0;
6184 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6185 &stat_fflags)) {
6186 /* Client asked to alter a flag we don't understand. */
6187 return NT_STATUS_INVALID_PARAMETER;
6190 if (fsp && fsp->fh->fd != -1) {
6191 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6192 return NT_STATUS_NOT_SUPPORTED;
6193 } else {
6194 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6195 return map_nt_error_from_unix(errno);
6200 /* XXX: need to add support for changing the create_time here. You
6201 * can do this for paths on Darwin with setattrlist(2). The right way
6202 * to hook this up is probably by extending the VFS utimes interface.
6205 return NT_STATUS_OK;
6208 /****************************************************************************
6209 Create a directory with POSIX semantics.
6210 ****************************************************************************/
6212 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6213 struct smb_request *req,
6214 char **ppdata,
6215 int total_data,
6216 const char *fname,
6217 SMB_STRUCT_STAT *psbuf,
6218 int *pdata_return_size)
6220 NTSTATUS status = NT_STATUS_OK;
6221 uint32 raw_unixmode = 0;
6222 uint32 mod_unixmode = 0;
6223 mode_t unixmode = (mode_t)0;
6224 files_struct *fsp = NULL;
6225 uint16 info_level_return = 0;
6226 int info;
6227 char *pdata = *ppdata;
6229 if (total_data < 18) {
6230 return NT_STATUS_INVALID_PARAMETER;
6233 raw_unixmode = IVAL(pdata,8);
6234 /* Next 4 bytes are not yet defined. */
6236 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 return status;
6241 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6243 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6244 fname, (unsigned int)unixmode ));
6246 status = open_directory(conn, req,
6247 fname,
6248 psbuf,
6249 FILE_READ_ATTRIBUTES, /* Just a stat open */
6250 FILE_SHARE_NONE, /* Ignored for stat opens */
6251 FILE_CREATE,
6253 mod_unixmode,
6254 &info,
6255 &fsp);
6257 if (NT_STATUS_IS_OK(status)) {
6258 close_file(fsp, NORMAL_CLOSE);
6261 info_level_return = SVAL(pdata,16);
6263 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6264 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6265 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6266 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6267 } else {
6268 *pdata_return_size = 12;
6271 /* Realloc the data size */
6272 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6273 if (*ppdata == NULL) {
6274 *pdata_return_size = 0;
6275 return NT_STATUS_NO_MEMORY;
6277 pdata = *ppdata;
6279 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6280 SSVAL(pdata,2,0); /* No fnum. */
6281 SIVAL(pdata,4,info); /* Was directory created. */
6283 switch (info_level_return) {
6284 case SMB_QUERY_FILE_UNIX_BASIC:
6285 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6286 SSVAL(pdata,10,0); /* Padding. */
6287 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6288 break;
6289 case SMB_QUERY_FILE_UNIX_INFO2:
6290 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6291 SSVAL(pdata,10,0); /* Padding. */
6292 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6293 break;
6294 default:
6295 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6296 SSVAL(pdata,10,0); /* Padding. */
6297 break;
6300 return status;
6303 /****************************************************************************
6304 Open/Create a file with POSIX semantics.
6305 ****************************************************************************/
6307 static NTSTATUS smb_posix_open(connection_struct *conn,
6308 struct smb_request *req,
6309 char **ppdata,
6310 int total_data,
6311 const char *fname,
6312 SMB_STRUCT_STAT *psbuf,
6313 int *pdata_return_size)
6315 bool extended_oplock_granted = False;
6316 char *pdata = *ppdata;
6317 uint32 flags = 0;
6318 uint32 wire_open_mode = 0;
6319 uint32 raw_unixmode = 0;
6320 uint32 mod_unixmode = 0;
6321 uint32 create_disp = 0;
6322 uint32 access_mask = 0;
6323 uint32 create_options = 0;
6324 NTSTATUS status = NT_STATUS_OK;
6325 mode_t unixmode = (mode_t)0;
6326 files_struct *fsp = NULL;
6327 int oplock_request = 0;
6328 int info = 0;
6329 uint16 info_level_return = 0;
6331 if (total_data < 18) {
6332 return NT_STATUS_INVALID_PARAMETER;
6335 flags = IVAL(pdata,0);
6336 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6337 if (oplock_request) {
6338 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6341 wire_open_mode = IVAL(pdata,4);
6343 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6344 return smb_posix_mkdir(conn, req,
6345 ppdata,
6346 total_data,
6347 fname,
6348 psbuf,
6349 pdata_return_size);
6352 switch (wire_open_mode & SMB_ACCMODE) {
6353 case SMB_O_RDONLY:
6354 access_mask = FILE_READ_DATA;
6355 break;
6356 case SMB_O_WRONLY:
6357 access_mask = FILE_WRITE_DATA;
6358 break;
6359 case SMB_O_RDWR:
6360 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6361 break;
6362 default:
6363 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6364 (unsigned int)wire_open_mode ));
6365 return NT_STATUS_INVALID_PARAMETER;
6368 wire_open_mode &= ~SMB_ACCMODE;
6370 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6371 create_disp = FILE_CREATE;
6372 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6373 create_disp = FILE_OVERWRITE_IF;
6374 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6375 create_disp = FILE_OPEN_IF;
6376 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6377 create_disp = FILE_OPEN;
6378 } else {
6379 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6380 (unsigned int)wire_open_mode ));
6381 return NT_STATUS_INVALID_PARAMETER;
6384 raw_unixmode = IVAL(pdata,8);
6385 /* Next 4 bytes are not yet defined. */
6387 status = unix_perms_from_wire(conn,
6388 psbuf,
6389 raw_unixmode,
6390 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6391 &unixmode);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 return status;
6397 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6399 if (wire_open_mode & SMB_O_SYNC) {
6400 create_options |= FILE_WRITE_THROUGH;
6402 if (wire_open_mode & SMB_O_APPEND) {
6403 access_mask |= FILE_APPEND_DATA;
6405 if (wire_open_mode & SMB_O_DIRECT) {
6406 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6409 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6410 fname,
6411 (unsigned int)wire_open_mode,
6412 (unsigned int)unixmode ));
6414 status = open_file_ntcreate(conn, req,
6415 fname,
6416 psbuf,
6417 access_mask,
6418 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6419 create_disp,
6420 0, /* no create options yet. */
6421 mod_unixmode,
6422 oplock_request,
6423 &info,
6424 &fsp);
6426 if (!NT_STATUS_IS_OK(status)) {
6427 return status;
6430 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6431 extended_oplock_granted = True;
6434 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6435 extended_oplock_granted = True;
6438 info_level_return = SVAL(pdata,16);
6440 /* Allocate the correct return size. */
6442 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6443 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6444 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6445 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6446 } else {
6447 *pdata_return_size = 12;
6450 /* Realloc the data size */
6451 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6452 if (*ppdata == NULL) {
6453 close_file(fsp,ERROR_CLOSE);
6454 *pdata_return_size = 0;
6455 return NT_STATUS_NO_MEMORY;
6457 pdata = *ppdata;
6459 if (extended_oplock_granted) {
6460 if (flags & REQUEST_BATCH_OPLOCK) {
6461 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6462 } else {
6463 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6465 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6466 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6467 } else {
6468 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6471 SSVAL(pdata,2,fsp->fnum);
6472 SIVAL(pdata,4,info); /* Was file created etc. */
6474 switch (info_level_return) {
6475 case SMB_QUERY_FILE_UNIX_BASIC:
6476 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6477 SSVAL(pdata,10,0); /* padding. */
6478 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6479 break;
6480 case SMB_QUERY_FILE_UNIX_INFO2:
6481 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6482 SSVAL(pdata,10,0); /* padding. */
6483 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6484 break;
6485 default:
6486 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6487 SSVAL(pdata,10,0); /* padding. */
6488 break;
6490 return NT_STATUS_OK;
6493 /****************************************************************************
6494 Delete a file with POSIX semantics.
6495 ****************************************************************************/
6497 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6498 struct smb_request *req,
6499 const char *pdata,
6500 int total_data,
6501 const char *fname,
6502 SMB_STRUCT_STAT *psbuf)
6504 NTSTATUS status = NT_STATUS_OK;
6505 files_struct *fsp = NULL;
6506 uint16 flags = 0;
6507 char del = 1;
6508 int info = 0;
6509 int i;
6510 struct share_mode_lock *lck = NULL;
6512 if (total_data < 2) {
6513 return NT_STATUS_INVALID_PARAMETER;
6516 flags = SVAL(pdata,0);
6518 if (!VALID_STAT(*psbuf)) {
6519 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6522 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6523 !VALID_STAT_OF_DIR(*psbuf)) {
6524 return NT_STATUS_NOT_A_DIRECTORY;
6527 DEBUG(10,("smb_posix_unlink: %s %s\n",
6528 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6529 fname));
6531 if (VALID_STAT_OF_DIR(*psbuf)) {
6532 status = open_directory(conn, req,
6533 fname,
6534 psbuf,
6535 DELETE_ACCESS,
6536 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6537 FILE_OPEN,
6539 FILE_FLAG_POSIX_SEMANTICS|0777,
6540 &info,
6541 &fsp);
6542 } else {
6544 status = open_file_ntcreate(conn, req,
6545 fname,
6546 psbuf,
6547 DELETE_ACCESS,
6548 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6549 FILE_OPEN,
6551 FILE_FLAG_POSIX_SEMANTICS|0777,
6552 0, /* No oplock, but break existing ones. */
6553 &info,
6554 &fsp);
6557 if (!NT_STATUS_IS_OK(status)) {
6558 return status;
6562 * Don't lie to client. If we can't really delete due to
6563 * non-POSIX opens return SHARING_VIOLATION.
6566 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6567 NULL);
6568 if (lck == NULL) {
6569 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6570 "lock for file %s\n", fsp->fsp_name));
6571 close_file(fsp, NORMAL_CLOSE);
6572 return NT_STATUS_INVALID_PARAMETER;
6576 * See if others still have the file open. If this is the case, then
6577 * don't delete. If all opens are POSIX delete we can set the delete
6578 * on close disposition.
6580 for (i=0; i<lck->num_share_modes; i++) {
6581 struct share_mode_entry *e = &lck->share_modes[i];
6582 if (is_valid_share_mode_entry(e)) {
6583 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6584 continue;
6586 /* Fail with sharing violation. */
6587 close_file(fsp, NORMAL_CLOSE);
6588 TALLOC_FREE(lck);
6589 return NT_STATUS_SHARING_VIOLATION;
6594 * Set the delete on close.
6596 status = smb_set_file_disposition_info(conn,
6597 &del,
6599 fsp,
6600 fname,
6601 psbuf);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 close_file(fsp, NORMAL_CLOSE);
6605 TALLOC_FREE(lck);
6606 return status;
6608 TALLOC_FREE(lck);
6609 return close_file(fsp, NORMAL_CLOSE);
6612 /****************************************************************************
6613 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6614 ****************************************************************************/
6616 static void call_trans2setfilepathinfo(connection_struct *conn,
6617 struct smb_request *req,
6618 unsigned int tran_call,
6619 char **pparams, int total_params,
6620 char **ppdata, int total_data,
6621 unsigned int max_data_bytes)
6623 char *params = *pparams;
6624 char *pdata = *ppdata;
6625 uint16 info_level;
6626 SMB_STRUCT_STAT sbuf;
6627 char *fname = NULL;
6628 files_struct *fsp = NULL;
6629 NTSTATUS status = NT_STATUS_OK;
6630 int data_return_size = 0;
6631 TALLOC_CTX *ctx = talloc_tos();
6633 if (!params) {
6634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6635 return;
6638 ZERO_STRUCT(sbuf);
6640 if (tran_call == TRANSACT2_SETFILEINFO) {
6641 if (total_params < 4) {
6642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6643 return;
6646 fsp = file_fsp(SVAL(params,0));
6647 /* Basic check for non-null fsp. */
6648 if (!check_fsp_open(conn, req, fsp)) {
6649 return;
6651 info_level = SVAL(params,2);
6653 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6654 if (!fname) {
6655 reply_nterror(req, NT_STATUS_NO_MEMORY);
6656 return;
6659 if(fsp->is_directory || fsp->fh->fd == -1) {
6661 * This is actually a SETFILEINFO on a directory
6662 * handle (returned from an NT SMB). NT5.0 seems
6663 * to do this call. JRA.
6665 if (INFO_LEVEL_IS_UNIX(info_level)) {
6666 /* Always do lstat for UNIX calls. */
6667 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6668 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6669 reply_unixerror(req,ERRDOS,ERRbadpath);
6670 return;
6672 } else {
6673 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6674 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6675 reply_unixerror(req,ERRDOS,ERRbadpath);
6676 return;
6679 } else if (fsp->print_file) {
6681 * Doing a DELETE_ON_CLOSE should cancel a print job.
6683 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6684 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6686 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6688 SSVAL(params,0,0);
6689 send_trans2_replies(conn, req, params, 2,
6690 *ppdata, 0,
6691 max_data_bytes);
6692 return;
6693 } else {
6694 reply_unixerror(req, ERRDOS, ERRbadpath);
6695 return;
6697 } else {
6699 * Original code - this is an open file.
6701 if (!check_fsp(conn, req, fsp)) {
6702 return;
6705 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6706 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6707 reply_unixerror(req, ERRDOS, ERRbadfid);
6708 return;
6711 } else {
6712 /* set path info */
6713 if (total_params < 7) {
6714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6715 return;
6718 info_level = SVAL(params,0);
6719 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6720 total_params - 6, STR_TERMINATE,
6721 &status);
6722 if (!NT_STATUS_IS_OK(status)) {
6723 reply_nterror(req, status);
6724 return;
6727 status = resolve_dfspath(ctx, conn,
6728 req->flags2 & FLAGS2_DFS_PATHNAMES,
6729 fname,
6730 &fname);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6733 reply_botherror(req,
6734 NT_STATUS_PATH_NOT_COVERED,
6735 ERRSRV, ERRbadpath);
6736 return;
6738 reply_nterror(req, status);
6739 return;
6742 status = unix_convert(ctx, conn, fname, False,
6743 &fname, NULL, &sbuf);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 reply_nterror(req, status);
6746 return;
6749 status = check_name(conn, fname);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 reply_nterror(req, status);
6752 return;
6755 if (INFO_LEVEL_IS_UNIX(info_level)) {
6757 * For CIFS UNIX extensions the target name may not exist.
6760 /* Always do lstat for UNIX calls. */
6761 SMB_VFS_LSTAT(conn,fname,&sbuf);
6763 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6764 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6765 reply_unixerror(req, ERRDOS, ERRbadpath);
6766 return;
6770 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6771 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6772 return;
6775 if (!CAN_WRITE(conn)) {
6776 /* Allow POSIX opens. The open path will deny
6777 * any non-readonly opens. */
6778 if (info_level != SMB_POSIX_PATH_OPEN) {
6779 reply_doserror(req, ERRSRV, ERRaccess);
6780 return;
6784 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6785 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6787 /* Realloc the parameter size */
6788 *pparams = (char *)SMB_REALLOC(*pparams,2);
6789 if (*pparams == NULL) {
6790 reply_nterror(req, NT_STATUS_NO_MEMORY);
6791 return;
6793 params = *pparams;
6795 SSVAL(params,0,0);
6797 switch (info_level) {
6799 case SMB_INFO_STANDARD:
6801 status = smb_set_info_standard(conn,
6802 pdata,
6803 total_data,
6804 fsp,
6805 fname,
6806 &sbuf);
6807 break;
6810 case SMB_INFO_SET_EA:
6812 status = smb_info_set_ea(conn,
6813 pdata,
6814 total_data,
6815 fsp,
6816 fname);
6817 break;
6820 case SMB_SET_FILE_BASIC_INFO:
6821 case SMB_FILE_BASIC_INFORMATION:
6823 status = smb_set_file_basic_info(conn,
6824 pdata,
6825 total_data,
6826 fsp,
6827 fname,
6828 &sbuf);
6829 break;
6832 case SMB_FILE_ALLOCATION_INFORMATION:
6833 case SMB_SET_FILE_ALLOCATION_INFO:
6835 status = smb_set_file_allocation_info(conn, req,
6836 pdata,
6837 total_data,
6838 fsp,
6839 fname,
6840 &sbuf);
6841 break;
6844 case SMB_FILE_END_OF_FILE_INFORMATION:
6845 case SMB_SET_FILE_END_OF_FILE_INFO:
6847 status = smb_set_file_end_of_file_info(conn, req,
6848 pdata,
6849 total_data,
6850 fsp,
6851 fname,
6852 &sbuf);
6853 break;
6856 case SMB_FILE_DISPOSITION_INFORMATION:
6857 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6859 #if 0
6860 /* JRA - We used to just ignore this on a path ?
6861 * Shouldn't this be invalid level on a pathname
6862 * based call ?
6864 if (tran_call != TRANSACT2_SETFILEINFO) {
6865 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6867 #endif
6868 status = smb_set_file_disposition_info(conn,
6869 pdata,
6870 total_data,
6871 fsp,
6872 fname,
6873 &sbuf);
6874 break;
6877 case SMB_FILE_POSITION_INFORMATION:
6879 status = smb_file_position_information(conn,
6880 pdata,
6881 total_data,
6882 fsp);
6883 break;
6886 /* From tridge Samba4 :
6887 * MODE_INFORMATION in setfileinfo (I have no
6888 * idea what "mode information" on a file is - it takes a value of 0,
6889 * 2, 4 or 6. What could it be?).
6892 case SMB_FILE_MODE_INFORMATION:
6894 status = smb_file_mode_information(conn,
6895 pdata,
6896 total_data);
6897 break;
6901 * CIFS UNIX extensions.
6904 case SMB_SET_FILE_UNIX_BASIC:
6906 status = smb_set_file_unix_basic(conn, req,
6907 pdata,
6908 total_data,
6909 fsp,
6910 fname,
6911 &sbuf);
6912 break;
6915 case SMB_SET_FILE_UNIX_INFO2:
6917 status = smb_set_file_unix_info2(conn, req,
6918 pdata,
6919 total_data,
6920 fsp,
6921 fname,
6922 &sbuf);
6923 break;
6926 case SMB_SET_FILE_UNIX_LINK:
6928 if (tran_call != TRANSACT2_SETPATHINFO) {
6929 /* We must have a pathname for this. */
6930 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6931 return;
6933 status = smb_set_file_unix_link(conn, req, pdata,
6934 total_data, fname);
6935 break;
6938 case SMB_SET_FILE_UNIX_HLINK:
6940 if (tran_call != TRANSACT2_SETPATHINFO) {
6941 /* We must have a pathname for this. */
6942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6943 return;
6945 status = smb_set_file_unix_hlink(conn, req,
6946 pdata, total_data,
6947 fname);
6948 break;
6951 case SMB_FILE_RENAME_INFORMATION:
6953 status = smb_file_rename_information(conn, req,
6954 pdata, total_data,
6955 fsp, fname);
6956 break;
6959 #if defined(HAVE_POSIX_ACLS)
6960 case SMB_SET_POSIX_ACL:
6962 status = smb_set_posix_acl(conn,
6963 pdata,
6964 total_data,
6965 fsp,
6966 fname,
6967 &sbuf);
6968 break;
6970 #endif
6972 case SMB_SET_POSIX_LOCK:
6974 if (tran_call != TRANSACT2_SETFILEINFO) {
6975 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6976 return;
6978 status = smb_set_posix_lock(conn, req,
6979 pdata, total_data, fsp);
6980 break;
6983 case SMB_POSIX_PATH_OPEN:
6985 if (tran_call != TRANSACT2_SETPATHINFO) {
6986 /* We must have a pathname for this. */
6987 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6988 return;
6991 status = smb_posix_open(conn, req,
6992 ppdata,
6993 total_data,
6994 fname,
6995 &sbuf,
6996 &data_return_size);
6997 break;
7000 case SMB_POSIX_PATH_UNLINK:
7002 if (tran_call != TRANSACT2_SETPATHINFO) {
7003 /* We must have a pathname for this. */
7004 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7005 return;
7008 status = smb_posix_unlink(conn, req,
7009 pdata,
7010 total_data,
7011 fname,
7012 &sbuf);
7013 break;
7016 default:
7017 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7018 return;
7022 if (!NT_STATUS_IS_OK(status)) {
7023 if (open_was_deferred(req->mid)) {
7024 /* We have re-scheduled this call. */
7025 return;
7027 if (blocking_lock_was_deferred(req->mid)) {
7028 /* We have re-scheduled this call. */
7029 return;
7031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7032 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7033 ERRSRV, ERRbadpath);
7034 return;
7036 if (info_level == SMB_POSIX_PATH_OPEN) {
7037 reply_openerror(req, status);
7038 return;
7041 reply_nterror(req, status);
7042 return;
7045 SSVAL(params,0,0);
7046 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7047 max_data_bytes);
7049 return;
7052 /****************************************************************************
7053 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7054 ****************************************************************************/
7056 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7057 char **pparams, int total_params,
7058 char **ppdata, int total_data,
7059 unsigned int max_data_bytes)
7061 char *params = *pparams;
7062 char *pdata = *ppdata;
7063 char *directory = NULL;
7064 SMB_STRUCT_STAT sbuf;
7065 NTSTATUS status = NT_STATUS_OK;
7066 struct ea_list *ea_list = NULL;
7067 TALLOC_CTX *ctx = talloc_tos();
7069 if (!CAN_WRITE(conn)) {
7070 reply_doserror(req, ERRSRV, ERRaccess);
7071 return;
7074 if (total_params < 5) {
7075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7076 return;
7079 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7080 total_params - 4, STR_TERMINATE,
7081 &status);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 reply_nterror(req, status);
7084 return;
7087 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7089 status = resolve_dfspath(ctx,
7090 conn,
7091 req->flags2 & FLAGS2_DFS_PATHNAMES,
7092 directory,
7093 &directory);
7094 if (!NT_STATUS_IS_OK(status)) {
7095 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7096 reply_botherror(req,
7097 NT_STATUS_PATH_NOT_COVERED,
7098 ERRSRV, ERRbadpath);
7100 reply_nterror(req, status);
7101 return;
7104 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7105 if (!NT_STATUS_IS_OK(status)) {
7106 reply_nterror(req, status);
7107 return;
7110 status = check_name(conn, directory);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7113 reply_nterror(req, status);
7114 return;
7117 /* Any data in this call is an EA list. */
7118 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7119 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7120 return;
7124 * OS/2 workplace shell seems to send SET_EA requests of "null"
7125 * length (4 bytes containing IVAL 4).
7126 * They seem to have no effect. Bug #3212. JRA.
7129 if (total_data != 4) {
7130 if (total_data < 10) {
7131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7132 return;
7135 if (IVAL(pdata,0) > total_data) {
7136 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7137 IVAL(pdata,0), (unsigned int)total_data));
7138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7139 return;
7142 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7143 total_data - 4);
7144 if (!ea_list) {
7145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7146 return;
7149 /* If total_data == 4 Windows doesn't care what values
7150 * are placed in that field, it just ignores them.
7151 * The System i QNTC IBM SMB client puts bad values here,
7152 * so ignore them. */
7154 status = create_directory(conn, req, directory);
7156 if (!NT_STATUS_IS_OK(status)) {
7157 reply_nterror(req, status);
7158 return;
7161 /* Try and set any given EA. */
7162 if (ea_list) {
7163 status = set_ea(conn, NULL, directory, ea_list);
7164 if (!NT_STATUS_IS_OK(status)) {
7165 reply_nterror(req, status);
7166 return;
7170 /* Realloc the parameter and data sizes */
7171 *pparams = (char *)SMB_REALLOC(*pparams,2);
7172 if(*pparams == NULL) {
7173 reply_nterror(req, NT_STATUS_NO_MEMORY);
7174 return;
7176 params = *pparams;
7178 SSVAL(params,0,0);
7180 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7182 return;
7185 /****************************************************************************
7186 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7187 We don't actually do this - we just send a null response.
7188 ****************************************************************************/
7190 static void call_trans2findnotifyfirst(connection_struct *conn,
7191 struct smb_request *req,
7192 char **pparams, int total_params,
7193 char **ppdata, int total_data,
7194 unsigned int max_data_bytes)
7196 static uint16 fnf_handle = 257;
7197 char *params = *pparams;
7198 uint16 info_level;
7200 if (total_params < 6) {
7201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7202 return;
7205 info_level = SVAL(params,4);
7206 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7208 switch (info_level) {
7209 case 1:
7210 case 2:
7211 break;
7212 default:
7213 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7214 return;
7217 /* Realloc the parameter and data sizes */
7218 *pparams = (char *)SMB_REALLOC(*pparams,6);
7219 if (*pparams == NULL) {
7220 reply_nterror(req, NT_STATUS_NO_MEMORY);
7221 return;
7223 params = *pparams;
7225 SSVAL(params,0,fnf_handle);
7226 SSVAL(params,2,0); /* No changes */
7227 SSVAL(params,4,0); /* No EA errors */
7229 fnf_handle++;
7231 if(fnf_handle == 0)
7232 fnf_handle = 257;
7234 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7236 return;
7239 /****************************************************************************
7240 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7241 changes). Currently this does nothing.
7242 ****************************************************************************/
7244 static void call_trans2findnotifynext(connection_struct *conn,
7245 struct smb_request *req,
7246 char **pparams, int total_params,
7247 char **ppdata, int total_data,
7248 unsigned int max_data_bytes)
7250 char *params = *pparams;
7252 DEBUG(3,("call_trans2findnotifynext\n"));
7254 /* Realloc the parameter and data sizes */
7255 *pparams = (char *)SMB_REALLOC(*pparams,4);
7256 if (*pparams == NULL) {
7257 reply_nterror(req, NT_STATUS_NO_MEMORY);
7258 return;
7260 params = *pparams;
7262 SSVAL(params,0,0); /* No changes */
7263 SSVAL(params,2,0); /* No EA errors */
7265 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7267 return;
7270 /****************************************************************************
7271 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7272 ****************************************************************************/
7274 static void call_trans2getdfsreferral(connection_struct *conn,
7275 struct smb_request *req,
7276 char **pparams, int total_params,
7277 char **ppdata, int total_data,
7278 unsigned int max_data_bytes)
7280 char *params = *pparams;
7281 char *pathname = NULL;
7282 int reply_size = 0;
7283 int max_referral_level;
7284 NTSTATUS status = NT_STATUS_OK;
7285 TALLOC_CTX *ctx = talloc_tos();
7287 DEBUG(10,("call_trans2getdfsreferral\n"));
7289 if (total_params < 3) {
7290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7291 return;
7294 max_referral_level = SVAL(params,0);
7296 if(!lp_host_msdfs()) {
7297 reply_doserror(req, ERRDOS, ERRbadfunc);
7298 return;
7301 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7302 total_params - 2, STR_TERMINATE);
7303 if (!pathname) {
7304 reply_nterror(req, NT_STATUS_NOT_FOUND);
7305 return;
7307 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7308 ppdata,&status)) < 0) {
7309 reply_nterror(req, status);
7310 return;
7313 SSVAL(req->inbuf, smb_flg2,
7314 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7315 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7317 return;
7320 #define LMCAT_SPL 0x53
7321 #define LMFUNC_GETJOBID 0x60
7323 /****************************************************************************
7324 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7325 ****************************************************************************/
7327 static void call_trans2ioctl(connection_struct *conn,
7328 struct smb_request *req,
7329 char **pparams, int total_params,
7330 char **ppdata, int total_data,
7331 unsigned int max_data_bytes)
7333 char *pdata = *ppdata;
7334 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7336 /* check for an invalid fid before proceeding */
7338 if (!fsp) {
7339 reply_doserror(req, ERRDOS, ERRbadfid);
7340 return;
7343 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7344 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7345 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7346 if (*ppdata == NULL) {
7347 reply_nterror(req, NT_STATUS_NO_MEMORY);
7348 return;
7350 pdata = *ppdata;
7352 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7353 CAN ACCEPT THIS IN UNICODE. JRA. */
7355 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7356 srvstr_push(pdata, req->flags2, pdata + 2,
7357 global_myname(), 15,
7358 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7359 srvstr_push(pdata, req->flags2, pdata+18,
7360 lp_servicename(SNUM(conn)), 13,
7361 STR_ASCII|STR_TERMINATE); /* Service name */
7362 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7363 max_data_bytes);
7364 return;
7367 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7368 reply_doserror(req, ERRSRV, ERRerror);
7371 /****************************************************************************
7372 Reply to a SMBfindclose (stop trans2 directory search).
7373 ****************************************************************************/
7375 void reply_findclose(struct smb_request *req)
7377 int dptr_num;
7379 START_PROFILE(SMBfindclose);
7381 if (req->wct < 1) {
7382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7383 END_PROFILE(SMBfindclose);
7384 return;
7387 dptr_num = SVALS(req->inbuf,smb_vwv0);
7389 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7391 dptr_close(&dptr_num);
7393 reply_outbuf(req, 0, 0);
7395 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7397 END_PROFILE(SMBfindclose);
7398 return;
7401 /****************************************************************************
7402 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7403 ****************************************************************************/
7405 void reply_findnclose(struct smb_request *req)
7407 int dptr_num;
7409 START_PROFILE(SMBfindnclose);
7411 if (req->wct < 1) {
7412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7413 END_PROFILE(SMBfindnclose);
7414 return;
7417 dptr_num = SVAL(req->inbuf,smb_vwv0);
7419 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7421 /* We never give out valid handles for a
7422 findnotifyfirst - so any dptr_num is ok here.
7423 Just ignore it. */
7425 reply_outbuf(req, 0, 0);
7427 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7429 END_PROFILE(SMBfindnclose);
7430 return;
7433 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7434 struct trans_state *state)
7436 if (Protocol >= PROTOCOL_NT1) {
7437 req->flags2 |= 0x40; /* IS_LONG_NAME */
7438 SSVAL(req->inbuf,smb_flg2,req->flags2);
7441 if (conn->encrypt_level == Required && !req->encrypted) {
7442 if (state->call != TRANSACT2_QFSINFO &&
7443 state->call != TRANSACT2_SETFSINFO) {
7444 DEBUG(0,("handle_trans2: encryption required "
7445 "with call 0x%x\n",
7446 (unsigned int)state->call));
7447 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7448 return;
7452 /* Now we must call the relevant TRANS2 function */
7453 switch(state->call) {
7454 case TRANSACT2_OPEN:
7456 START_PROFILE(Trans2_open);
7457 call_trans2open(conn, req,
7458 &state->param, state->total_param,
7459 &state->data, state->total_data,
7460 state->max_data_return);
7461 END_PROFILE(Trans2_open);
7462 break;
7465 case TRANSACT2_FINDFIRST:
7467 START_PROFILE(Trans2_findfirst);
7468 call_trans2findfirst(conn, req,
7469 &state->param, state->total_param,
7470 &state->data, state->total_data,
7471 state->max_data_return);
7472 END_PROFILE(Trans2_findfirst);
7473 break;
7476 case TRANSACT2_FINDNEXT:
7478 START_PROFILE(Trans2_findnext);
7479 call_trans2findnext(conn, req,
7480 &state->param, state->total_param,
7481 &state->data, state->total_data,
7482 state->max_data_return);
7483 END_PROFILE(Trans2_findnext);
7484 break;
7487 case TRANSACT2_QFSINFO:
7489 START_PROFILE(Trans2_qfsinfo);
7490 call_trans2qfsinfo(conn, req,
7491 &state->param, state->total_param,
7492 &state->data, state->total_data,
7493 state->max_data_return);
7494 END_PROFILE(Trans2_qfsinfo);
7495 break;
7498 case TRANSACT2_SETFSINFO:
7500 START_PROFILE(Trans2_setfsinfo);
7501 call_trans2setfsinfo(conn, req,
7502 &state->param, state->total_param,
7503 &state->data, state->total_data,
7504 state->max_data_return);
7505 END_PROFILE(Trans2_setfsinfo);
7506 break;
7509 case TRANSACT2_QPATHINFO:
7510 case TRANSACT2_QFILEINFO:
7512 START_PROFILE(Trans2_qpathinfo);
7513 call_trans2qfilepathinfo(conn, req, state->call,
7514 &state->param, state->total_param,
7515 &state->data, state->total_data,
7516 state->max_data_return);
7517 END_PROFILE(Trans2_qpathinfo);
7518 break;
7521 case TRANSACT2_SETPATHINFO:
7522 case TRANSACT2_SETFILEINFO:
7524 START_PROFILE(Trans2_setpathinfo);
7525 call_trans2setfilepathinfo(conn, req, state->call,
7526 &state->param, state->total_param,
7527 &state->data, state->total_data,
7528 state->max_data_return);
7529 END_PROFILE(Trans2_setpathinfo);
7530 break;
7533 case TRANSACT2_FINDNOTIFYFIRST:
7535 START_PROFILE(Trans2_findnotifyfirst);
7536 call_trans2findnotifyfirst(conn, req,
7537 &state->param, state->total_param,
7538 &state->data, state->total_data,
7539 state->max_data_return);
7540 END_PROFILE(Trans2_findnotifyfirst);
7541 break;
7544 case TRANSACT2_FINDNOTIFYNEXT:
7546 START_PROFILE(Trans2_findnotifynext);
7547 call_trans2findnotifynext(conn, req,
7548 &state->param, state->total_param,
7549 &state->data, state->total_data,
7550 state->max_data_return);
7551 END_PROFILE(Trans2_findnotifynext);
7552 break;
7555 case TRANSACT2_MKDIR:
7557 START_PROFILE(Trans2_mkdir);
7558 call_trans2mkdir(conn, req,
7559 &state->param, state->total_param,
7560 &state->data, state->total_data,
7561 state->max_data_return);
7562 END_PROFILE(Trans2_mkdir);
7563 break;
7566 case TRANSACT2_GET_DFS_REFERRAL:
7568 START_PROFILE(Trans2_get_dfs_referral);
7569 call_trans2getdfsreferral(conn, req,
7570 &state->param, state->total_param,
7571 &state->data, state->total_data,
7572 state->max_data_return);
7573 END_PROFILE(Trans2_get_dfs_referral);
7574 break;
7577 case TRANSACT2_IOCTL:
7579 START_PROFILE(Trans2_ioctl);
7580 call_trans2ioctl(conn, req,
7581 &state->param, state->total_param,
7582 &state->data, state->total_data,
7583 state->max_data_return);
7584 END_PROFILE(Trans2_ioctl);
7585 break;
7588 default:
7589 /* Error in request */
7590 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7591 reply_doserror(req, ERRSRV,ERRerror);
7595 /****************************************************************************
7596 Reply to a SMBtrans2.
7597 ****************************************************************************/
7599 void reply_trans2(struct smb_request *req)
7601 connection_struct *conn = req->conn;
7602 unsigned int dsoff;
7603 unsigned int dscnt;
7604 unsigned int psoff;
7605 unsigned int pscnt;
7606 unsigned int tran_call;
7607 unsigned int size;
7608 unsigned int av_size;
7609 struct trans_state *state;
7610 NTSTATUS result;
7612 START_PROFILE(SMBtrans2);
7614 if (req->wct < 14) {
7615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7616 END_PROFILE(SMBtrans2);
7617 return;
7620 dsoff = SVAL(req->inbuf, smb_dsoff);
7621 dscnt = SVAL(req->inbuf, smb_dscnt);
7622 psoff = SVAL(req->inbuf, smb_psoff);
7623 pscnt = SVAL(req->inbuf, smb_pscnt);
7624 tran_call = SVAL(req->inbuf, smb_setup0);
7625 size = smb_len(req->inbuf) + 4;
7626 av_size = smb_len(req->inbuf);
7628 result = allow_new_trans(conn->pending_trans, req->mid);
7629 if (!NT_STATUS_IS_OK(result)) {
7630 DEBUG(2, ("Got invalid trans2 request: %s\n",
7631 nt_errstr(result)));
7632 reply_nterror(req, result);
7633 END_PROFILE(SMBtrans2);
7634 return;
7637 if (IS_IPC(conn)) {
7638 switch (tran_call) {
7639 /* List the allowed trans2 calls on IPC$ */
7640 case TRANSACT2_OPEN:
7641 case TRANSACT2_GET_DFS_REFERRAL:
7642 case TRANSACT2_QFILEINFO:
7643 case TRANSACT2_QFSINFO:
7644 case TRANSACT2_SETFSINFO:
7645 break;
7646 default:
7647 reply_doserror(req, ERRSRV, ERRaccess);
7648 END_PROFILE(SMBtrans2);
7649 return;
7653 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7654 DEBUG(0, ("talloc failed\n"));
7655 reply_nterror(req, NT_STATUS_NO_MEMORY);
7656 END_PROFILE(SMBtrans2);
7657 return;
7660 state->cmd = SMBtrans2;
7662 state->mid = req->mid;
7663 state->vuid = req->vuid;
7664 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7665 state->setup = NULL;
7666 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7667 state->param = NULL;
7668 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7669 state->data = NULL;
7670 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7671 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7672 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7673 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7674 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7676 state->call = tran_call;
7678 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7679 is so as a sanity check */
7680 if (state->setup_count != 1) {
7682 * Need to have rc=0 for ioctl to get job id for OS/2.
7683 * Network printing will fail if function is not successful.
7684 * Similar function in reply.c will be used if protocol
7685 * is LANMAN1.0 instead of LM1.2X002.
7686 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7687 * outbuf doesn't have to be set(only job id is used).
7689 if ( (state->setup_count == 4)
7690 && (tran_call == TRANSACT2_IOCTL)
7691 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7692 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7693 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7694 } else {
7695 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7696 DEBUG(2,("Transaction is %d\n",tran_call));
7697 TALLOC_FREE(state);
7698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7699 END_PROFILE(SMBtrans2);
7700 return;
7704 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7705 goto bad_param;
7707 if (state->total_data) {
7708 /* Can't use talloc here, the core routines do realloc on the
7709 * params and data. */
7710 state->data = (char *)SMB_MALLOC(state->total_data);
7711 if (state->data == NULL) {
7712 DEBUG(0,("reply_trans2: data malloc fail for %u "
7713 "bytes !\n", (unsigned int)state->total_data));
7714 TALLOC_FREE(state);
7715 reply_nterror(req, NT_STATUS_NO_MEMORY);
7716 END_PROFILE(SMBtrans2);
7717 return;
7720 if (dscnt > state->total_data ||
7721 dsoff+dscnt < dsoff) {
7722 goto bad_param;
7725 if (dsoff > av_size ||
7726 dscnt > av_size ||
7727 dsoff+dscnt > av_size) {
7728 goto bad_param;
7731 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7734 if (state->total_param) {
7735 /* Can't use talloc here, the core routines do realloc on the
7736 * params and data. */
7737 state->param = (char *)SMB_MALLOC(state->total_param);
7738 if (state->param == NULL) {
7739 DEBUG(0,("reply_trans: param malloc fail for %u "
7740 "bytes !\n", (unsigned int)state->total_param));
7741 SAFE_FREE(state->data);
7742 TALLOC_FREE(state);
7743 reply_nterror(req, NT_STATUS_NO_MEMORY);
7744 END_PROFILE(SMBtrans2);
7745 return;
7748 if (pscnt > state->total_param ||
7749 psoff+pscnt < psoff) {
7750 goto bad_param;
7753 if (psoff > av_size ||
7754 pscnt > av_size ||
7755 psoff+pscnt > av_size) {
7756 goto bad_param;
7759 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7762 state->received_data = dscnt;
7763 state->received_param = pscnt;
7765 if ((state->received_param == state->total_param) &&
7766 (state->received_data == state->total_data)) {
7768 handle_trans2(conn, req, state);
7770 SAFE_FREE(state->data);
7771 SAFE_FREE(state->param);
7772 TALLOC_FREE(state);
7773 END_PROFILE(SMBtrans2);
7774 return;
7777 DLIST_ADD(conn->pending_trans, state);
7779 /* We need to send an interim response then receive the rest
7780 of the parameter/data bytes */
7781 reply_outbuf(req, 0, 0);
7782 show_msg((char *)req->outbuf);
7783 END_PROFILE(SMBtrans2);
7784 return;
7786 bad_param:
7788 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7789 SAFE_FREE(state->data);
7790 SAFE_FREE(state->param);
7791 TALLOC_FREE(state);
7792 END_PROFILE(SMBtrans2);
7793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7797 /****************************************************************************
7798 Reply to a SMBtranss2
7799 ****************************************************************************/
7801 void reply_transs2(struct smb_request *req)
7803 connection_struct *conn = req->conn;
7804 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7805 struct trans_state *state;
7806 unsigned int size;
7807 unsigned int av_size;
7809 START_PROFILE(SMBtranss2);
7811 show_msg((char *)req->inbuf);
7813 if (req->wct < 8) {
7814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7815 END_PROFILE(SMBtranss2);
7816 return;
7819 size = smb_len(req->inbuf)+4;
7820 av_size = smb_len(req->inbuf);
7822 for (state = conn->pending_trans; state != NULL;
7823 state = state->next) {
7824 if (state->mid == req->mid) {
7825 break;
7829 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7831 END_PROFILE(SMBtranss2);
7832 return;
7835 /* Revise state->total_param and state->total_data in case they have
7836 changed downwards */
7838 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7839 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7840 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7841 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7843 pcnt = SVAL(req->inbuf, smb_spscnt);
7844 poff = SVAL(req->inbuf, smb_spsoff);
7845 pdisp = SVAL(req->inbuf, smb_spsdisp);
7847 dcnt = SVAL(req->inbuf, smb_sdscnt);
7848 doff = SVAL(req->inbuf, smb_sdsoff);
7849 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7851 state->received_param += pcnt;
7852 state->received_data += dcnt;
7854 if ((state->received_data > state->total_data) ||
7855 (state->received_param > state->total_param))
7856 goto bad_param;
7858 if (pcnt) {
7859 if (pdisp > state->total_param ||
7860 pcnt > state->total_param ||
7861 pdisp+pcnt > state->total_param ||
7862 pdisp+pcnt < pdisp) {
7863 goto bad_param;
7866 if (poff > av_size ||
7867 pcnt > av_size ||
7868 poff+pcnt > av_size ||
7869 poff+pcnt < poff) {
7870 goto bad_param;
7873 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7874 pcnt);
7877 if (dcnt) {
7878 if (ddisp > state->total_data ||
7879 dcnt > state->total_data ||
7880 ddisp+dcnt > state->total_data ||
7881 ddisp+dcnt < ddisp) {
7882 goto bad_param;
7885 if (doff > av_size ||
7886 dcnt > av_size ||
7887 doff+dcnt > av_size ||
7888 doff+dcnt < doff) {
7889 goto bad_param;
7892 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7893 dcnt);
7896 if ((state->received_param < state->total_param) ||
7897 (state->received_data < state->total_data)) {
7898 END_PROFILE(SMBtranss2);
7899 return;
7903 * construct_reply_common will copy smb_com from inbuf to
7904 * outbuf. SMBtranss2 is wrong here.
7906 SCVAL(req->inbuf,smb_com,SMBtrans2);
7908 handle_trans2(conn, req, state);
7910 DLIST_REMOVE(conn->pending_trans, state);
7911 SAFE_FREE(state->data);
7912 SAFE_FREE(state->param);
7913 TALLOC_FREE(state);
7915 END_PROFILE(SMBtranss2);
7916 return;
7918 bad_param:
7920 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7921 DLIST_REMOVE(conn->pending_trans, state);
7922 SAFE_FREE(state->data);
7923 SAFE_FREE(state->param);
7924 TALLOC_FREE(state);
7925 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7926 END_PROFILE(SMBtranss2);
7927 return;