s3:smbd: construct the correct newname for stream renames
[Samba.git] / source / smbd / trans2.c
blobdf0b4470569fb9f182f79ebad32ecb2fba70aec5
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 (conn->case_sensitive)
1091 return strcmp(str,mask)==0;
1092 if (StrCaseCmp(str,mask) != 0) {
1093 return False;
1095 if (dptr_has_wild(conn->dirptr)) {
1096 return False;
1098 return True;
1101 /****************************************************************************
1102 Return the filetype for UNIX extensions.
1103 ****************************************************************************/
1105 static uint32 unix_filetype(mode_t mode)
1107 if(S_ISREG(mode))
1108 return UNIX_TYPE_FILE;
1109 else if(S_ISDIR(mode))
1110 return UNIX_TYPE_DIR;
1111 #ifdef S_ISLNK
1112 else if(S_ISLNK(mode))
1113 return UNIX_TYPE_SYMLINK;
1114 #endif
1115 #ifdef S_ISCHR
1116 else if(S_ISCHR(mode))
1117 return UNIX_TYPE_CHARDEV;
1118 #endif
1119 #ifdef S_ISBLK
1120 else if(S_ISBLK(mode))
1121 return UNIX_TYPE_BLKDEV;
1122 #endif
1123 #ifdef S_ISFIFO
1124 else if(S_ISFIFO(mode))
1125 return UNIX_TYPE_FIFO;
1126 #endif
1127 #ifdef S_ISSOCK
1128 else if(S_ISSOCK(mode))
1129 return UNIX_TYPE_SOCKET;
1130 #endif
1132 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1133 return UNIX_TYPE_UNKNOWN;
1136 /****************************************************************************
1137 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1138 ****************************************************************************/
1140 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1142 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1143 SMB_STRUCT_STAT *psbuf,
1144 uint32 perms,
1145 enum perm_type ptype,
1146 mode_t *ret_perms)
1148 mode_t ret = 0;
1150 if (perms == SMB_MODE_NO_CHANGE) {
1151 if (!VALID_STAT(*psbuf)) {
1152 return NT_STATUS_INVALID_PARAMETER;
1153 } else {
1154 *ret_perms = psbuf->st_mode;
1155 return NT_STATUS_OK;
1159 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1160 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1161 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1162 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1163 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1164 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1165 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1166 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1167 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1168 #ifdef S_ISVTX
1169 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1170 #endif
1171 #ifdef S_ISGID
1172 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1173 #endif
1174 #ifdef S_ISUID
1175 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1176 #endif
1178 switch (ptype) {
1179 case PERM_NEW_FILE:
1180 /* Apply mode mask */
1181 ret &= lp_create_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_create_mode(SNUM(conn));
1184 break;
1185 case PERM_NEW_DIR:
1186 ret &= lp_dir_mask(SNUM(conn));
1187 /* Add in force bits */
1188 ret |= lp_force_dir_mode(SNUM(conn));
1189 break;
1190 case PERM_EXISTING_FILE:
1191 /* Apply mode mask */
1192 ret &= lp_security_mask(SNUM(conn));
1193 /* Add in force bits */
1194 ret |= lp_force_security_mode(SNUM(conn));
1195 break;
1196 case PERM_EXISTING_DIR:
1197 /* Apply mode mask */
1198 ret &= lp_dir_security_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_dir_security_mode(SNUM(conn));
1201 break;
1204 *ret_perms = ret;
1205 return NT_STATUS_OK;
1208 /****************************************************************************
1209 Needed to show the msdfs symlinks as directories. Modifies psbuf
1210 to be a directory if it's a msdfs link.
1211 ****************************************************************************/
1213 static bool check_msdfs_link(connection_struct *conn,
1214 const char *pathname,
1215 SMB_STRUCT_STAT *psbuf)
1217 int saved_errno = errno;
1218 if(lp_host_msdfs() &&
1219 lp_msdfs_root(SNUM(conn)) &&
1220 is_msdfs_link(conn, pathname, psbuf)) {
1222 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1223 "as a directory\n",
1224 pathname));
1225 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1226 errno = saved_errno;
1227 return true;
1229 errno = saved_errno;
1230 return false;
1234 /****************************************************************************
1235 Get a level dependent lanman2 dir entry.
1236 ****************************************************************************/
1238 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1239 connection_struct *conn,
1240 uint16 flags2,
1241 const char *path_mask,
1242 uint32 dirtype,
1243 int info_level,
1244 int requires_resume_key,
1245 bool dont_descend,
1246 bool ask_sharemode,
1247 char **ppdata,
1248 char *base_data,
1249 char *end_data,
1250 int space_remaining,
1251 bool *out_of_space,
1252 bool *got_exact_match,
1253 int *last_entry_off,
1254 struct ea_list *name_list)
1256 const char *dname;
1257 bool found = False;
1258 SMB_STRUCT_STAT sbuf;
1259 const char *mask = NULL;
1260 char *pathreal = NULL;
1261 const char *fname = NULL;
1262 char *p, *q, *pdata = *ppdata;
1263 uint32 reskey=0;
1264 long prev_dirpos=0;
1265 uint32 mode=0;
1266 SMB_OFF_T file_size = 0;
1267 SMB_BIG_UINT allocation_size = 0;
1268 uint32 len;
1269 struct timespec mdate_ts, adate_ts, create_date_ts;
1270 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1271 char *nameptr;
1272 char *last_entry_ptr;
1273 bool was_8_3;
1274 uint32 nt_extmode; /* Used for NT connections instead of mode */
1275 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1276 bool check_mangled_names = lp_manglednames(conn->params);
1277 char mangled_name[13]; /* mangled 8.3 name. */
1279 *out_of_space = False;
1280 *got_exact_match = False;
1282 ZERO_STRUCT(mdate_ts);
1283 ZERO_STRUCT(adate_ts);
1284 ZERO_STRUCT(create_date_ts);
1286 if (!conn->dirptr) {
1287 return(False);
1290 p = strrchr_m(path_mask,'/');
1291 if(p != NULL) {
1292 if(p[1] == '\0') {
1293 mask = talloc_strdup(ctx,"*.*");
1294 } else {
1295 mask = p+1;
1297 } else {
1298 mask = path_mask;
1301 while (!found) {
1302 bool got_match;
1303 bool ms_dfs_link = False;
1305 /* Needed if we run out of space */
1306 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1307 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1310 * Due to bugs in NT client redirectors we are not using
1311 * resume keys any more - set them to zero.
1312 * Check out the related comments in findfirst/findnext.
1313 * JRA.
1316 reskey = 0;
1318 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1319 (long)conn->dirptr,curr_dirpos));
1321 if (!dname) {
1322 return(False);
1326 * fname may get mangled, dname is never mangled.
1327 * Whenever we're accessing the filesystem we use
1328 * pathreal which is composed from dname.
1331 pathreal = NULL;
1332 fname = dname;
1334 /* Mangle fname if it's an illegal name. */
1335 if (mangle_must_mangle(dname,conn->params)) {
1336 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1337 continue; /* Error - couldn't mangle. */
1339 fname = mangled_name;
1342 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1343 got_match = mask_match(fname, mask, conn->case_sensitive);
1346 if(!got_match && check_mangled_names &&
1347 !mangle_is_8_3(fname, False, conn->params)) {
1349 * It turns out that NT matches wildcards against
1350 * both long *and* short names. This may explain some
1351 * of the wildcard wierdness from old DOS clients
1352 * that some people have been seeing.... JRA.
1354 /* Force the mangling into 8.3. */
1355 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1356 continue; /* Error - couldn't mangle. */
1359 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1360 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1364 if (got_match) {
1365 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1367 if (dont_descend && !isdots) {
1368 continue;
1371 if (needslash) {
1372 pathreal = NULL;
1373 pathreal = talloc_asprintf(ctx,
1374 "%s/%s",
1375 conn->dirpath,
1376 dname);
1377 } else {
1378 pathreal = talloc_asprintf(ctx,
1379 "%s%s",
1380 conn->dirpath,
1381 dname);
1384 if (!pathreal) {
1385 return False;
1388 if (INFO_LEVEL_IS_UNIX(info_level)) {
1389 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1390 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1391 pathreal,strerror(errno)));
1392 TALLOC_FREE(pathreal);
1393 continue;
1395 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1396 /* Needed to show the msdfs symlinks as
1397 * directories */
1399 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1400 if (!ms_dfs_link) {
1401 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1402 pathreal,strerror(errno)));
1403 TALLOC_FREE(pathreal);
1404 continue;
1408 if (ms_dfs_link) {
1409 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1410 } else {
1411 mode = dos_mode(conn,pathreal,&sbuf);
1414 if (!dir_check_ftype(conn,mode,dirtype)) {
1415 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1416 TALLOC_FREE(pathreal);
1417 continue;
1420 if (!(mode & aDIR)) {
1421 file_size = get_file_size(sbuf);
1423 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1425 mdate_ts = get_mtimespec(&sbuf);
1426 adate_ts = get_atimespec(&sbuf);
1427 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1429 if (ask_sharemode) {
1430 struct timespec write_time_ts;
1431 struct file_id fileid;
1433 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1434 get_file_infos(fileid, NULL, &write_time_ts);
1435 if (!null_timespec(write_time_ts)) {
1436 mdate_ts = write_time_ts;
1440 if (lp_dos_filetime_resolution(SNUM(conn))) {
1441 dos_filetime_timespec(&create_date_ts);
1442 dos_filetime_timespec(&mdate_ts);
1443 dos_filetime_timespec(&adate_ts);
1446 create_date = convert_timespec_to_time_t(create_date_ts);
1447 mdate = convert_timespec_to_time_t(mdate_ts);
1448 adate = convert_timespec_to_time_t(adate_ts);
1450 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1452 found = True;
1454 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1458 p = pdata;
1459 last_entry_ptr = p;
1461 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1463 switch (info_level) {
1464 case SMB_FIND_INFO_STANDARD:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466 if(requires_resume_key) {
1467 SIVAL(p,0,reskey);
1468 p += 4;
1470 srv_put_dos_date2(p,0,create_date);
1471 srv_put_dos_date2(p,4,adate);
1472 srv_put_dos_date2(p,8,mdate);
1473 SIVAL(p,12,(uint32)file_size);
1474 SIVAL(p,16,(uint32)allocation_size);
1475 SSVAL(p,20,mode);
1476 p += 23;
1477 nameptr = p;
1478 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1479 p += ucs2_align(base_data, p, 0);
1481 len = srvstr_push(base_data, flags2, p,
1482 fname, PTR_DIFF(end_data, p),
1483 STR_TERMINATE);
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1485 if (len > 2) {
1486 SCVAL(nameptr, -1, len - 2);
1487 } else {
1488 SCVAL(nameptr, -1, 0);
1490 } else {
1491 if (len > 1) {
1492 SCVAL(nameptr, -1, len - 1);
1493 } else {
1494 SCVAL(nameptr, -1, 0);
1497 p += len;
1498 break;
1500 case SMB_FIND_EA_SIZE:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502 if(requires_resume_key) {
1503 SIVAL(p,0,reskey);
1504 p += 4;
1506 srv_put_dos_date2(p,0,create_date);
1507 srv_put_dos_date2(p,4,adate);
1508 srv_put_dos_date2(p,8,mdate);
1509 SIVAL(p,12,(uint32)file_size);
1510 SIVAL(p,16,(uint32)allocation_size);
1511 SSVAL(p,20,mode);
1513 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514 SIVAL(p,22,ea_size); /* Extended attributes */
1516 p += 27;
1517 nameptr = p - 1;
1518 len = srvstr_push(base_data, flags2,
1519 p, fname, PTR_DIFF(end_data, p),
1520 STR_TERMINATE | STR_NOALIGN);
1521 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1522 if (len > 2) {
1523 len -= 2;
1524 } else {
1525 len = 0;
1527 } else {
1528 if (len > 1) {
1529 len -= 1;
1530 } else {
1531 len = 0;
1534 SCVAL(nameptr,0,len);
1535 p += len;
1536 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1537 break;
1539 case SMB_FIND_EA_LIST:
1541 struct ea_list *file_list = NULL;
1542 size_t ea_len = 0;
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1545 if (!name_list) {
1546 return False;
1548 if(requires_resume_key) {
1549 SIVAL(p,0,reskey);
1550 p += 4;
1552 srv_put_dos_date2(p,0,create_date);
1553 srv_put_dos_date2(p,4,adate);
1554 srv_put_dos_date2(p,8,mdate);
1555 SIVAL(p,12,(uint32)file_size);
1556 SIVAL(p,16,(uint32)allocation_size);
1557 SSVAL(p,20,mode);
1558 p += 22; /* p now points to the EA area. */
1560 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1561 name_list = ea_list_union(name_list, file_list, &ea_len);
1563 /* We need to determine if this entry will fit in the space available. */
1564 /* Max string size is 255 bytes. */
1565 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568 *out_of_space = True;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False; /* Not finished - just out of space */
1573 /* Push the ea_data followed by the name. */
1574 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1575 nameptr = p;
1576 len = srvstr_push(base_data, flags2,
1577 p + 1, fname, PTR_DIFF(end_data, p+1),
1578 STR_TERMINATE | STR_NOALIGN);
1579 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1580 if (len > 2) {
1581 len -= 2;
1582 } else {
1583 len = 0;
1585 } else {
1586 if (len > 1) {
1587 len -= 1;
1588 } else {
1589 len = 0;
1592 SCVAL(nameptr,0,len);
1593 p += len + 1;
1594 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1595 break;
1598 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1601 p += 4;
1602 SIVAL(p,0,reskey); p += 4;
1603 put_long_date_timespec(p,create_date_ts); p += 8;
1604 put_long_date_timespec(p,adate_ts); p += 8;
1605 put_long_date_timespec(p,mdate_ts); p += 8;
1606 put_long_date_timespec(p,mdate_ts); p += 8;
1607 SOFF_T(p,0,file_size); p += 8;
1608 SOFF_T(p,0,allocation_size); p += 8;
1609 SIVAL(p,0,nt_extmode); p += 4;
1610 q = p; p += 4; /* q is placeholder for name length. */
1612 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1613 SIVAL(p,0,ea_size); /* Extended attributes */
1614 p += 4;
1616 /* Clear the short name buffer. This is
1617 * IMPORTANT as not doing so will trigger
1618 * a Win2k client bug. JRA.
1620 if (!was_8_3 && check_mangled_names) {
1621 if (!name_to_8_3(fname,mangled_name,True,
1622 conn->params)) {
1623 /* Error - mangle failed ! */
1624 memset(mangled_name,'\0',12);
1626 mangled_name[12] = 0;
1627 len = srvstr_push(base_data, flags2,
1628 p+2, mangled_name, 24,
1629 STR_UPPER|STR_UNICODE);
1630 if (len < 24) {
1631 memset(p + 2 + len,'\0',24 - len);
1633 SSVAL(p, 0, len);
1634 } else {
1635 memset(p,'\0',26);
1637 p += 2 + 24;
1638 len = srvstr_push(base_data, flags2, p,
1639 fname, PTR_DIFF(end_data, p),
1640 STR_TERMINATE_ASCII);
1641 SIVAL(q,0,len);
1642 p += len;
1643 SIVAL(p,0,0); /* Ensure any padding is null. */
1644 len = PTR_DIFF(p, pdata);
1645 len = (len + 3) & ~3;
1646 SIVAL(pdata,0,len);
1647 p = pdata + len;
1648 break;
1650 case SMB_FIND_FILE_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1652 p += 4;
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 len = srvstr_push(base_data, flags2,
1662 p + 4, fname, PTR_DIFF(end_data, p+4),
1663 STR_TERMINATE_ASCII);
1664 SIVAL(p,0,len);
1665 p += 4 + len;
1666 SIVAL(p,0,0); /* Ensure any padding is null. */
1667 len = PTR_DIFF(p, pdata);
1668 len = (len + 3) & ~3;
1669 SIVAL(pdata,0,len);
1670 p = pdata + len;
1671 break;
1673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1675 p += 4;
1676 SIVAL(p,0,reskey); p += 4;
1677 put_long_date_timespec(p,create_date_ts); p += 8;
1678 put_long_date_timespec(p,adate_ts); p += 8;
1679 put_long_date_timespec(p,mdate_ts); p += 8;
1680 put_long_date_timespec(p,mdate_ts); p += 8;
1681 SOFF_T(p,0,file_size); p += 8;
1682 SOFF_T(p,0,allocation_size); p += 8;
1683 SIVAL(p,0,nt_extmode); p += 4;
1684 q = p; p += 4; /* q is placeholder for name length. */
1686 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1687 SIVAL(p,0,ea_size); /* Extended attributes */
1688 p +=4;
1690 len = srvstr_push(base_data, flags2, p,
1691 fname, PTR_DIFF(end_data, p),
1692 STR_TERMINATE_ASCII);
1693 SIVAL(q, 0, len);
1694 p += len;
1696 SIVAL(p,0,0); /* Ensure any padding is null. */
1697 len = PTR_DIFF(p, pdata);
1698 len = (len + 3) & ~3;
1699 SIVAL(pdata,0,len);
1700 p = pdata + len;
1701 break;
1703 case SMB_FIND_FILE_NAMES_INFO:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1705 p += 4;
1706 SIVAL(p,0,reskey); p += 4;
1707 p += 4;
1708 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709 acl on a dir (tridge) */
1710 len = srvstr_push(base_data, flags2, p,
1711 fname, PTR_DIFF(end_data, p),
1712 STR_TERMINATE_ASCII);
1713 SIVAL(p, -4, len);
1714 p += len;
1715 SIVAL(p,0,0); /* Ensure any padding is null. */
1716 len = PTR_DIFF(p, pdata);
1717 len = (len + 3) & ~3;
1718 SIVAL(pdata,0,len);
1719 p = pdata + len;
1720 break;
1722 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1724 p += 4;
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_timespec(p,create_date_ts); p += 8;
1727 put_long_date_timespec(p,adate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,nt_extmode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length. */
1735 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1737 p +=4;
1739 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1740 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1741 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE_ASCII);
1745 SIVAL(q, 0, len);
1746 p += len;
1747 SIVAL(p,0,0); /* Ensure any padding is null. */
1748 len = PTR_DIFF(p, pdata);
1749 len = (len + 3) & ~3;
1750 SIVAL(pdata,0,len);
1751 p = pdata + len;
1752 break;
1754 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1757 p += 4;
1758 SIVAL(p,0,reskey); p += 4;
1759 put_long_date_timespec(p,create_date_ts); p += 8;
1760 put_long_date_timespec(p,adate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 put_long_date_timespec(p,mdate_ts); p += 8;
1763 SOFF_T(p,0,file_size); p += 8;
1764 SOFF_T(p,0,allocation_size); p += 8;
1765 SIVAL(p,0,nt_extmode); p += 4;
1766 q = p; p += 4; /* q is placeholder for name length */
1768 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1769 SIVAL(p,0,ea_size); /* Extended attributes */
1770 p +=4;
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3 && check_mangled_names) {
1777 if (!name_to_8_3(fname,mangled_name,True,
1778 conn->params)) {
1779 /* Error - mangle failed ! */
1780 memset(mangled_name,'\0',12);
1782 mangled_name[12] = 0;
1783 len = srvstr_push(base_data, flags2,
1784 p+2, mangled_name, 24,
1785 STR_UPPER|STR_UNICODE);
1786 SSVAL(p, 0, len);
1787 if (len < 24) {
1788 memset(p + 2 + len,'\0',24 - len);
1790 SSVAL(p, 0, len);
1791 } else {
1792 memset(p,'\0',26);
1794 p += 26;
1795 SSVAL(p,0,0); p += 2; /* Reserved ? */
1796 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1797 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1801 SIVAL(q,0,len);
1802 p += len;
1803 SIVAL(p,0,0); /* Ensure any padding is null. */
1804 len = PTR_DIFF(p, pdata);
1805 len = (len + 3) & ~3;
1806 SIVAL(pdata,0,len);
1807 p = pdata + len;
1808 break;
1810 /* CIFS UNIX Extension. */
1812 case SMB_FIND_FILE_UNIX:
1813 case SMB_FIND_FILE_UNIX_INFO2:
1814 p+= 4;
1815 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1817 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1819 if (info_level == SMB_FIND_FILE_UNIX) {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821 p = store_file_unix_basic(conn, p,
1822 NULL, &sbuf);
1823 len = srvstr_push(base_data, flags2, p,
1824 fname, PTR_DIFF(end_data, p),
1825 STR_TERMINATE);
1826 } else {
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828 p = store_file_unix_basic_info2(conn, p,
1829 NULL, &sbuf);
1830 nameptr = p;
1831 p += 4;
1832 len = srvstr_push(base_data, flags2, p, fname,
1833 PTR_DIFF(end_data, p), 0);
1834 SIVAL(nameptr, 0, len);
1837 p += len;
1838 SIVAL(p,0,0); /* Ensure any padding is null. */
1840 len = PTR_DIFF(p, pdata);
1841 len = (len + 3) & ~3;
1842 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1843 p = pdata + len;
1844 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1846 break;
1848 default:
1849 return(False);
1853 if (PTR_DIFF(p,pdata) > space_remaining) {
1854 /* Move the dirptr back to prev_dirpos */
1855 dptr_SeekDir(conn->dirptr, prev_dirpos);
1856 *out_of_space = True;
1857 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1858 return False; /* Not finished - just out of space */
1861 /* Setup the last entry pointer, as an offset from base_data */
1862 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1863 /* Advance the data pointer to the next slot */
1864 *ppdata = p;
1866 return(found);
1869 /****************************************************************************
1870 Reply to a TRANS2_FINDFIRST.
1871 ****************************************************************************/
1873 static void call_trans2findfirst(connection_struct *conn,
1874 struct smb_request *req,
1875 char **pparams, int total_params,
1876 char **ppdata, int total_data,
1877 unsigned int max_data_bytes)
1879 /* We must be careful here that we don't return more than the
1880 allowed number of data bytes. If this means returning fewer than
1881 maxentries then so be it. We assume that the redirector has
1882 enough room for the fixed number of parameter bytes it has
1883 requested. */
1884 char *params = *pparams;
1885 char *pdata = *ppdata;
1886 char *data_end;
1887 uint32 dirtype;
1888 int maxentries;
1889 uint16 findfirst_flags;
1890 bool close_after_first;
1891 bool close_if_end;
1892 bool requires_resume_key;
1893 int info_level;
1894 char *directory = NULL;
1895 char *mask = NULL;
1896 char *p;
1897 int last_entry_off=0;
1898 int dptr_num = -1;
1899 int numentries = 0;
1900 int i;
1901 bool finished = False;
1902 bool dont_descend = False;
1903 bool out_of_space = False;
1904 int space_remaining;
1905 bool mask_contains_wcard = False;
1906 SMB_STRUCT_STAT sbuf;
1907 struct ea_list *ea_list = NULL;
1908 NTSTATUS ntstatus = NT_STATUS_OK;
1909 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1910 TALLOC_CTX *ctx = talloc_tos();
1912 if (total_params < 13) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1914 return;
1917 dirtype = SVAL(params,0);
1918 maxentries = SVAL(params,2);
1919 findfirst_flags = SVAL(params,4);
1920 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1921 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1922 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1923 info_level = SVAL(params,6);
1925 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1926 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1927 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1928 info_level, max_data_bytes));
1930 if (!maxentries) {
1931 /* W2K3 seems to treat zero as 1. */
1932 maxentries = 1;
1935 switch (info_level) {
1936 case SMB_FIND_INFO_STANDARD:
1937 case SMB_FIND_EA_SIZE:
1938 case SMB_FIND_EA_LIST:
1939 case SMB_FIND_FILE_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1941 case SMB_FIND_FILE_NAMES_INFO:
1942 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1943 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1944 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1945 break;
1946 case SMB_FIND_FILE_UNIX:
1947 case SMB_FIND_FILE_UNIX_INFO2:
1948 /* Always use filesystem for UNIX mtime query. */
1949 ask_sharemode = false;
1950 if (!lp_unix_extensions()) {
1951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1952 return;
1954 break;
1955 default:
1956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1957 return;
1960 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1961 params+12, total_params - 12,
1962 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1963 if (!NT_STATUS_IS_OK(ntstatus)) {
1964 reply_nterror(req, ntstatus);
1965 return;
1968 ntstatus = resolve_dfspath_wcard(ctx, conn,
1969 req->flags2 & FLAGS2_DFS_PATHNAMES,
1970 directory,
1971 &directory,
1972 &mask_contains_wcard);
1973 if (!NT_STATUS_IS_OK(ntstatus)) {
1974 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1975 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1976 ERRSRV, ERRbadpath);
1977 return;
1979 reply_nterror(req, ntstatus);
1980 return;
1983 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1984 if (!NT_STATUS_IS_OK(ntstatus)) {
1985 reply_nterror(req, ntstatus);
1986 return;
1989 ntstatus = check_name(conn, directory);
1990 if (!NT_STATUS_IS_OK(ntstatus)) {
1991 reply_nterror(req, ntstatus);
1992 return;
1995 p = strrchr_m(directory,'/');
1996 if(p == NULL) {
1997 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1998 if((directory[0] == '.') && (directory[1] == '\0')) {
1999 mask = talloc_strdup(ctx,"*");
2000 if (!mask) {
2001 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 return;
2004 mask_contains_wcard = True;
2006 directory = talloc_strdup(talloc_tos(), "./");
2007 if (!directory) {
2008 reply_nterror(req, NT_STATUS_NO_MEMORY);
2009 return;
2011 } else {
2012 *p = 0;
2015 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2017 if (info_level == SMB_FIND_EA_LIST) {
2018 uint32 ea_size;
2020 if (total_data < 4) {
2021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2022 return;
2025 ea_size = IVAL(pdata,0);
2026 if (ea_size != total_data) {
2027 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2028 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2030 return;
2033 if (!lp_ea_support(SNUM(conn))) {
2034 reply_doserror(req, ERRDOS, ERReasnotsupported);
2035 return;
2038 /* Pull out the list of names. */
2039 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2040 if (!ea_list) {
2041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2042 return;
2046 *ppdata = (char *)SMB_REALLOC(
2047 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2048 if(*ppdata == NULL ) {
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2050 return;
2052 pdata = *ppdata;
2053 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2055 /* Realloc the params space */
2056 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2057 if (*pparams == NULL) {
2058 reply_nterror(req, NT_STATUS_NO_MEMORY);
2059 return;
2061 params = *pparams;
2063 /* Save the wildcard match and attribs we are using on this directory -
2064 needed as lanman2 assumes these are being saved between calls */
2066 ntstatus = dptr_create(conn,
2067 directory,
2068 False,
2069 True,
2070 req->smbpid,
2071 mask,
2072 mask_contains_wcard,
2073 dirtype,
2074 &conn->dirptr);
2076 if (!NT_STATUS_IS_OK(ntstatus)) {
2077 reply_nterror(req, ntstatus);
2078 return;
2081 dptr_num = dptr_dnum(conn->dirptr);
2082 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2084 /* We don't need to check for VOL here as this is returned by
2085 a different TRANS2 call. */
2087 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2088 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2089 dont_descend = True;
2091 p = pdata;
2092 space_remaining = max_data_bytes;
2093 out_of_space = False;
2095 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2096 bool got_exact_match = False;
2098 /* this is a heuristic to avoid seeking the dirptr except when
2099 absolutely necessary. It allows for a filename of about 40 chars */
2100 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2101 out_of_space = True;
2102 finished = False;
2103 } else {
2104 finished = !get_lanman2_dir_entry(ctx,
2105 conn,
2106 req->flags2,
2107 mask,dirtype,info_level,
2108 requires_resume_key,dont_descend,
2109 ask_sharemode,
2110 &p,pdata,data_end,
2111 space_remaining, &out_of_space,
2112 &got_exact_match,
2113 &last_entry_off, ea_list);
2116 if (finished && out_of_space)
2117 finished = False;
2119 if (!finished && !out_of_space)
2120 numentries++;
2123 * As an optimisation if we know we aren't looking
2124 * for a wildcard name (ie. the name matches the wildcard exactly)
2125 * then we can finish on any (first) match.
2126 * This speeds up large directory searches. JRA.
2129 if(got_exact_match)
2130 finished = True;
2132 /* Ensure space_remaining never goes -ve. */
2133 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2134 space_remaining = 0;
2135 out_of_space = true;
2136 } else {
2137 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2141 /* Check if we can close the dirptr */
2142 if(close_after_first || (finished && close_if_end)) {
2143 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2144 dptr_close(&dptr_num);
2148 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2149 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2150 * the protocol level is less than NT1. Tested with smbclient. JRA.
2151 * This should fix the OS/2 client bug #2335.
2154 if(numentries == 0) {
2155 dptr_close(&dptr_num);
2156 if (Protocol < PROTOCOL_NT1) {
2157 reply_doserror(req, ERRDOS, ERRnofiles);
2158 return;
2159 } else {
2160 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2161 ERRDOS, ERRbadfile);
2162 return;
2166 /* At this point pdata points to numentries directory entries. */
2168 /* Set up the return parameter block */
2169 SSVAL(params,0,dptr_num);
2170 SSVAL(params,2,numentries);
2171 SSVAL(params,4,finished);
2172 SSVAL(params,6,0); /* Never an EA error */
2173 SSVAL(params,8,last_entry_off);
2175 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2176 max_data_bytes);
2178 if ((! *directory) && dptr_path(dptr_num)) {
2179 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2180 if (!directory) {
2181 reply_nterror(req, NT_STATUS_NO_MEMORY);
2185 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2186 smb_fn_name(CVAL(req->inbuf,smb_com)),
2187 mask, directory, dirtype, numentries ) );
2190 * Force a name mangle here to ensure that the
2191 * mask as an 8.3 name is top of the mangled cache.
2192 * The reasons for this are subtle. Don't remove
2193 * this code unless you know what you are doing
2194 * (see PR#13758). JRA.
2197 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2198 char mangled_name[13];
2199 name_to_8_3(mask, mangled_name, True, conn->params);
2202 return;
2205 /****************************************************************************
2206 Reply to a TRANS2_FINDNEXT.
2207 ****************************************************************************/
2209 static void call_trans2findnext(connection_struct *conn,
2210 struct smb_request *req,
2211 char **pparams, int total_params,
2212 char **ppdata, int total_data,
2213 unsigned int max_data_bytes)
2215 /* We must be careful here that we don't return more than the
2216 allowed number of data bytes. If this means returning fewer than
2217 maxentries then so be it. We assume that the redirector has
2218 enough room for the fixed number of parameter bytes it has
2219 requested. */
2220 char *params = *pparams;
2221 char *pdata = *ppdata;
2222 char *data_end;
2223 int dptr_num;
2224 int maxentries;
2225 uint16 info_level;
2226 uint32 resume_key;
2227 uint16 findnext_flags;
2228 bool close_after_request;
2229 bool close_if_end;
2230 bool requires_resume_key;
2231 bool continue_bit;
2232 bool mask_contains_wcard = False;
2233 char *resume_name = NULL;
2234 const char *mask = NULL;
2235 const char *directory = NULL;
2236 char *p = NULL;
2237 uint16 dirtype;
2238 int numentries = 0;
2239 int i, last_entry_off=0;
2240 bool finished = False;
2241 bool dont_descend = False;
2242 bool out_of_space = False;
2243 int space_remaining;
2244 struct ea_list *ea_list = NULL;
2245 NTSTATUS ntstatus = NT_STATUS_OK;
2246 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2247 TALLOC_CTX *ctx = talloc_tos();
2249 if (total_params < 13) {
2250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2251 return;
2254 dptr_num = SVAL(params,0);
2255 maxentries = SVAL(params,2);
2256 info_level = SVAL(params,4);
2257 resume_key = IVAL(params,6);
2258 findnext_flags = SVAL(params,10);
2259 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2260 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2261 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2262 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2264 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2265 params+12,
2266 total_params - 12, STR_TERMINATE, &ntstatus,
2267 &mask_contains_wcard);
2268 if (!NT_STATUS_IS_OK(ntstatus)) {
2269 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2270 complain (it thinks we're asking for the directory above the shared
2271 path or an invalid name). Catch this as the resume name is only compared, never used in
2272 a file access. JRA. */
2273 srvstr_pull_talloc(ctx, params, req->flags2,
2274 &resume_name, params+12,
2275 total_params - 12,
2276 STR_TERMINATE);
2278 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2279 reply_nterror(req, ntstatus);
2280 return;
2284 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2285 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2286 resume_key = %d resume name = %s continue=%d level = %d\n",
2287 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2288 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2290 if (!maxentries) {
2291 /* W2K3 seems to treat zero as 1. */
2292 maxentries = 1;
2295 switch (info_level) {
2296 case SMB_FIND_INFO_STANDARD:
2297 case SMB_FIND_EA_SIZE:
2298 case SMB_FIND_EA_LIST:
2299 case SMB_FIND_FILE_DIRECTORY_INFO:
2300 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2301 case SMB_FIND_FILE_NAMES_INFO:
2302 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2303 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2304 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2305 break;
2306 case SMB_FIND_FILE_UNIX:
2307 case SMB_FIND_FILE_UNIX_INFO2:
2308 /* Always use filesystem for UNIX mtime query. */
2309 ask_sharemode = false;
2310 if (!lp_unix_extensions()) {
2311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2312 return;
2314 break;
2315 default:
2316 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2317 return;
2320 if (info_level == SMB_FIND_EA_LIST) {
2321 uint32 ea_size;
2323 if (total_data < 4) {
2324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 return;
2328 ea_size = IVAL(pdata,0);
2329 if (ea_size != total_data) {
2330 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 return;
2336 if (!lp_ea_support(SNUM(conn))) {
2337 reply_doserror(req, ERRDOS, ERReasnotsupported);
2338 return;
2341 /* Pull out the list of names. */
2342 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2343 if (!ea_list) {
2344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2345 return;
2349 *ppdata = (char *)SMB_REALLOC(
2350 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2351 if(*ppdata == NULL) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 return;
2356 pdata = *ppdata;
2357 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2359 /* Realloc the params space */
2360 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2361 if(*pparams == NULL ) {
2362 reply_nterror(req, NT_STATUS_NO_MEMORY);
2363 return;
2366 params = *pparams;
2368 /* Check that the dptr is valid */
2369 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2370 reply_doserror(req, ERRDOS, ERRnofiles);
2371 return;
2374 string_set(&conn->dirpath,dptr_path(dptr_num));
2376 /* Get the wildcard mask from the dptr */
2377 if((p = dptr_wcard(dptr_num))== NULL) {
2378 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2379 reply_doserror(req, ERRDOS, ERRnofiles);
2380 return;
2383 mask = p;
2384 directory = conn->dirpath;
2386 /* Get the attr mask from the dptr */
2387 dirtype = dptr_attr(dptr_num);
2389 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2390 dptr_num, mask, dirtype,
2391 (long)conn->dirptr,
2392 dptr_TellDir(conn->dirptr)));
2394 /* We don't need to check for VOL here as this is returned by
2395 a different TRANS2 call. */
2397 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2398 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2399 dont_descend = True;
2401 p = pdata;
2402 space_remaining = max_data_bytes;
2403 out_of_space = False;
2406 * Seek to the correct position. We no longer use the resume key but
2407 * depend on the last file name instead.
2410 if(*resume_name && !continue_bit) {
2411 SMB_STRUCT_STAT st;
2413 long current_pos = 0;
2415 * Remember, name_to_8_3 is called by
2416 * get_lanman2_dir_entry(), so the resume name
2417 * could be mangled. Ensure we check the unmangled name.
2420 if (mangle_is_mangled(resume_name, conn->params)) {
2421 char *new_resume_name = NULL;
2422 mangle_lookup_name_from_8_3(ctx,
2423 resume_name,
2424 &new_resume_name,
2425 conn->params);
2426 if (new_resume_name) {
2427 resume_name = new_resume_name;
2432 * Fix for NT redirector problem triggered by resume key indexes
2433 * changing between directory scans. We now return a resume key of 0
2434 * and instead look for the filename to continue from (also given
2435 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2436 * findfirst/findnext (as is usual) then the directory pointer
2437 * should already be at the correct place.
2440 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2441 } /* end if resume_name && !continue_bit */
2443 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2444 bool got_exact_match = False;
2446 /* this is a heuristic to avoid seeking the dirptr except when
2447 absolutely necessary. It allows for a filename of about 40 chars */
2448 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2449 out_of_space = True;
2450 finished = False;
2451 } else {
2452 finished = !get_lanman2_dir_entry(ctx,
2453 conn,
2454 req->flags2,
2455 mask,dirtype,info_level,
2456 requires_resume_key,dont_descend,
2457 ask_sharemode,
2458 &p,pdata,data_end,
2459 space_remaining, &out_of_space,
2460 &got_exact_match,
2461 &last_entry_off, ea_list);
2464 if (finished && out_of_space)
2465 finished = False;
2467 if (!finished && !out_of_space)
2468 numentries++;
2471 * As an optimisation if we know we aren't looking
2472 * for a wildcard name (ie. the name matches the wildcard exactly)
2473 * then we can finish on any (first) match.
2474 * This speeds up large directory searches. JRA.
2477 if(got_exact_match)
2478 finished = True;
2480 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2483 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2484 smb_fn_name(CVAL(req->inbuf,smb_com)),
2485 mask, directory, dirtype, numentries ) );
2487 /* Check if we can close the dirptr */
2488 if(close_after_request || (finished && close_if_end)) {
2489 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2490 dptr_close(&dptr_num); /* This frees up the saved mask */
2493 /* Set up the return parameter block */
2494 SSVAL(params,0,numentries);
2495 SSVAL(params,2,finished);
2496 SSVAL(params,4,0); /* Never an EA error */
2497 SSVAL(params,6,last_entry_off);
2499 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2500 max_data_bytes);
2502 return;
2505 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2507 E_md4hash(lp_servicename(SNUM(conn)),objid);
2508 return objid;
2511 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2513 SMB_ASSERT(extended_info != NULL);
2515 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2516 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2517 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2518 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2519 #ifdef SAMBA_VERSION_REVISION
2520 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2521 #endif
2522 extended_info->samba_subversion = 0;
2523 #ifdef SAMBA_VERSION_RC_RELEASE
2524 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2525 #else
2526 #ifdef SAMBA_VERSION_PRE_RELEASE
2527 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2528 #endif
2529 #endif
2530 #ifdef SAMBA_VERSION_VENDOR_PATCH
2531 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2532 #endif
2533 extended_info->samba_gitcommitdate = 0;
2534 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2535 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2536 #endif
2538 memset(extended_info->samba_version_string, 0,
2539 sizeof(extended_info->samba_version_string));
2541 snprintf (extended_info->samba_version_string,
2542 sizeof(extended_info->samba_version_string),
2543 "%s", samba_version_string());
2546 /****************************************************************************
2547 Reply to a TRANS2_QFSINFO (query filesystem info).
2548 ****************************************************************************/
2550 static void call_trans2qfsinfo(connection_struct *conn,
2551 struct smb_request *req,
2552 char **pparams, int total_params,
2553 char **ppdata, int total_data,
2554 unsigned int max_data_bytes)
2556 char *pdata, *end_data;
2557 char *params = *pparams;
2558 uint16 info_level;
2559 int data_len, len;
2560 SMB_STRUCT_STAT st;
2561 const char *vname = volume_label(SNUM(conn));
2562 int snum = SNUM(conn);
2563 char *fstype = lp_fstype(SNUM(conn));
2564 uint32 additional_flags = 0;
2566 if (total_params < 2) {
2567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2568 return;
2571 info_level = SVAL(params,0);
2573 if (IS_IPC(conn)) {
2574 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2575 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2576 "info level (0x%x) on IPC$.\n",
2577 (unsigned int)info_level));
2578 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2579 return;
2583 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2584 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2585 DEBUG(0,("call_trans2qfsinfo: encryption required "
2586 "and info level 0x%x sent.\n",
2587 (unsigned int)info_level));
2588 exit_server_cleanly("encryption required "
2589 "on connection");
2590 return;
2594 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2596 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2597 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2598 reply_doserror(req, ERRSRV, ERRinvdevice);
2599 return;
2602 *ppdata = (char *)SMB_REALLOC(
2603 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2604 if (*ppdata == NULL ) {
2605 reply_nterror(req, NT_STATUS_NO_MEMORY);
2606 return;
2609 pdata = *ppdata;
2610 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2611 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2613 switch (info_level) {
2614 case SMB_INFO_ALLOCATION:
2616 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2617 data_len = 18;
2618 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2619 reply_unixerror(req, ERRHRD, ERRgeneral);
2620 return;
2623 block_size = lp_block_size(snum);
2624 if (bsize < block_size) {
2625 SMB_BIG_UINT factor = block_size/bsize;
2626 bsize = block_size;
2627 dsize /= factor;
2628 dfree /= factor;
2630 if (bsize > block_size) {
2631 SMB_BIG_UINT factor = bsize/block_size;
2632 bsize = block_size;
2633 dsize *= factor;
2634 dfree *= factor;
2636 bytes_per_sector = 512;
2637 sectors_per_unit = bsize/bytes_per_sector;
2639 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2640 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2641 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2643 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2644 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2645 SIVAL(pdata,l1_cUnit,dsize);
2646 SIVAL(pdata,l1_cUnitAvail,dfree);
2647 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2648 break;
2651 case SMB_INFO_VOLUME:
2652 /* Return volume name */
2654 * Add volume serial number - hash of a combination of
2655 * the called hostname and the service name.
2657 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2659 * Win2k3 and previous mess this up by sending a name length
2660 * one byte short. I believe only older clients (OS/2 Win9x) use
2661 * this call so try fixing this by adding a terminating null to
2662 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2664 len = srvstr_push(
2665 pdata, req->flags2,
2666 pdata+l2_vol_szVolLabel, vname,
2667 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2668 STR_NOALIGN|STR_TERMINATE);
2669 SCVAL(pdata,l2_vol_cch,len);
2670 data_len = l2_vol_szVolLabel + len;
2671 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2672 (unsigned)st.st_ctime, len, vname));
2673 break;
2675 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2676 case SMB_FS_ATTRIBUTE_INFORMATION:
2678 additional_flags = 0;
2679 #if defined(HAVE_SYS_QUOTAS)
2680 additional_flags |= FILE_VOLUME_QUOTAS;
2681 #endif
2683 if(lp_nt_acl_support(SNUM(conn))) {
2684 additional_flags |= FILE_PERSISTENT_ACLS;
2687 /* Capabilities are filled in at connection time through STATVFS call */
2688 additional_flags |= conn->fs_capabilities;
2690 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2691 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2692 additional_flags); /* FS ATTRIBUTES */
2694 SIVAL(pdata,4,255); /* Max filename component length */
2695 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2696 and will think we can't do long filenames */
2697 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2698 PTR_DIFF(end_data, pdata+12),
2699 STR_UNICODE);
2700 SIVAL(pdata,8,len);
2701 data_len = 12 + len;
2702 break;
2704 case SMB_QUERY_FS_LABEL_INFO:
2705 case SMB_FS_LABEL_INFORMATION:
2706 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2707 PTR_DIFF(end_data, pdata+4), 0);
2708 data_len = 4 + len;
2709 SIVAL(pdata,0,len);
2710 break;
2712 case SMB_QUERY_FS_VOLUME_INFO:
2713 case SMB_FS_VOLUME_INFORMATION:
2716 * Add volume serial number - hash of a combination of
2717 * the called hostname and the service name.
2719 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2720 (str_checksum(get_local_machine_name())<<16));
2722 /* Max label len is 32 characters. */
2723 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2724 PTR_DIFF(end_data, pdata+18),
2725 STR_UNICODE);
2726 SIVAL(pdata,12,len);
2727 data_len = 18+len;
2729 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2730 (int)strlen(vname),vname, lp_servicename(snum)));
2731 break;
2733 case SMB_QUERY_FS_SIZE_INFO:
2734 case SMB_FS_SIZE_INFORMATION:
2736 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2737 data_len = 24;
2738 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2739 reply_unixerror(req, ERRHRD, ERRgeneral);
2740 return;
2742 block_size = lp_block_size(snum);
2743 if (bsize < block_size) {
2744 SMB_BIG_UINT factor = block_size/bsize;
2745 bsize = block_size;
2746 dsize /= factor;
2747 dfree /= factor;
2749 if (bsize > block_size) {
2750 SMB_BIG_UINT factor = bsize/block_size;
2751 bsize = block_size;
2752 dsize *= factor;
2753 dfree *= factor;
2755 bytes_per_sector = 512;
2756 sectors_per_unit = bsize/bytes_per_sector;
2757 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2758 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2759 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2760 SBIG_UINT(pdata,0,dsize);
2761 SBIG_UINT(pdata,8,dfree);
2762 SIVAL(pdata,16,sectors_per_unit);
2763 SIVAL(pdata,20,bytes_per_sector);
2764 break;
2767 case SMB_FS_FULL_SIZE_INFORMATION:
2769 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2770 data_len = 32;
2771 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2772 reply_unixerror(req, ERRHRD, ERRgeneral);
2773 return;
2775 block_size = lp_block_size(snum);
2776 if (bsize < block_size) {
2777 SMB_BIG_UINT factor = block_size/bsize;
2778 bsize = block_size;
2779 dsize /= factor;
2780 dfree /= factor;
2782 if (bsize > block_size) {
2783 SMB_BIG_UINT factor = bsize/block_size;
2784 bsize = block_size;
2785 dsize *= factor;
2786 dfree *= factor;
2788 bytes_per_sector = 512;
2789 sectors_per_unit = bsize/bytes_per_sector;
2790 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2791 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2792 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2793 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2794 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2795 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2796 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2797 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2798 break;
2801 case SMB_QUERY_FS_DEVICE_INFO:
2802 case SMB_FS_DEVICE_INFORMATION:
2803 data_len = 8;
2804 SIVAL(pdata,0,0); /* dev type */
2805 SIVAL(pdata,4,0); /* characteristics */
2806 break;
2808 #ifdef HAVE_SYS_QUOTAS
2809 case SMB_FS_QUOTA_INFORMATION:
2811 * what we have to send --metze:
2813 * Unknown1: 24 NULL bytes
2814 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2815 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2816 * Quota Flags: 2 byte :
2817 * Unknown3: 6 NULL bytes
2819 * 48 bytes total
2821 * details for Quota Flags:
2823 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2824 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2825 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2826 * 0x0001 Enable Quotas: enable quota for this fs
2830 /* we need to fake up a fsp here,
2831 * because its not send in this call
2833 files_struct fsp;
2834 SMB_NTQUOTA_STRUCT quotas;
2836 ZERO_STRUCT(fsp);
2837 ZERO_STRUCT(quotas);
2839 fsp.conn = conn;
2840 fsp.fnum = -1;
2842 /* access check */
2843 if (conn->server_info->utok.uid != 0) {
2844 DEBUG(0,("set_user_quota: access_denied "
2845 "service [%s] user [%s]\n",
2846 lp_servicename(SNUM(conn)),
2847 conn->server_info->unix_name));
2848 reply_doserror(req, ERRDOS, ERRnoaccess);
2849 return;
2852 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2853 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2854 reply_doserror(req, ERRSRV, ERRerror);
2855 return;
2858 data_len = 48;
2860 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2862 /* Unknown1 24 NULL bytes*/
2863 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2864 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2865 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2867 /* Default Soft Quota 8 bytes */
2868 SBIG_UINT(pdata,24,quotas.softlim);
2870 /* Default Hard Quota 8 bytes */
2871 SBIG_UINT(pdata,32,quotas.hardlim);
2873 /* Quota flag 2 bytes */
2874 SSVAL(pdata,40,quotas.qflags);
2876 /* Unknown3 6 NULL bytes */
2877 SSVAL(pdata,42,0);
2878 SIVAL(pdata,44,0);
2880 break;
2882 #endif /* HAVE_SYS_QUOTAS */
2883 case SMB_FS_OBJECTID_INFORMATION:
2885 unsigned char objid[16];
2886 struct smb_extended_info extended_info;
2887 memcpy(pdata,create_volume_objectid(conn, objid),16);
2888 samba_extended_info_version (&extended_info);
2889 SIVAL(pdata,16,extended_info.samba_magic);
2890 SIVAL(pdata,20,extended_info.samba_version);
2891 SIVAL(pdata,24,extended_info.samba_subversion);
2892 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2893 memcpy(pdata+36,extended_info.samba_version_string,28);
2894 data_len = 64;
2895 break;
2899 * Query the version and capabilities of the CIFS UNIX extensions
2900 * in use.
2903 case SMB_QUERY_CIFS_UNIX_INFO:
2905 bool large_write = lp_min_receive_file_size() &&
2906 !srv_is_signing_active();
2907 bool large_read = !srv_is_signing_active();
2908 int encrypt_caps = 0;
2910 if (!lp_unix_extensions()) {
2911 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2912 return;
2915 switch (conn->encrypt_level) {
2916 case 0:
2917 encrypt_caps = 0;
2918 break;
2919 case 1:
2920 case Auto:
2921 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2922 break;
2923 case Required:
2924 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2925 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2926 large_write = false;
2927 large_read = false;
2928 break;
2931 data_len = 12;
2932 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2933 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2935 /* We have POSIX ACLs, pathname, encryption,
2936 * large read/write, and locking capability. */
2938 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2939 CIFS_UNIX_POSIX_ACLS_CAP|
2940 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2941 CIFS_UNIX_FCNTL_LOCKS_CAP|
2942 CIFS_UNIX_EXTATTR_CAP|
2943 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2944 encrypt_caps|
2945 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2946 (large_write ?
2947 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2948 break;
2951 case SMB_QUERY_POSIX_FS_INFO:
2953 int rc;
2954 vfs_statvfs_struct svfs;
2956 if (!lp_unix_extensions()) {
2957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2958 return;
2961 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2963 if (!rc) {
2964 data_len = 56;
2965 SIVAL(pdata,0,svfs.OptimalTransferSize);
2966 SIVAL(pdata,4,svfs.BlockSize);
2967 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2968 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2969 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2970 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2971 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2972 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2973 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2974 #ifdef EOPNOTSUPP
2975 } else if (rc == EOPNOTSUPP) {
2976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2977 return;
2978 #endif /* EOPNOTSUPP */
2979 } else {
2980 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2981 reply_doserror(req, ERRSRV, ERRerror);
2982 return;
2984 break;
2987 case SMB_QUERY_POSIX_WHOAMI:
2989 uint32_t flags = 0;
2990 uint32_t sid_bytes;
2991 int i;
2993 if (!lp_unix_extensions()) {
2994 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2995 return;
2998 if (max_data_bytes < 40) {
2999 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3000 return;
3003 /* We ARE guest if global_sid_Builtin_Guests is
3004 * in our list of SIDs.
3006 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3007 conn->server_info->ptok)) {
3008 flags |= SMB_WHOAMI_GUEST;
3011 /* We are NOT guest if global_sid_Authenticated_Users
3012 * is in our list of SIDs.
3014 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3015 conn->server_info->ptok)) {
3016 flags &= ~SMB_WHOAMI_GUEST;
3019 /* NOTE: 8 bytes for UID/GID, irrespective of native
3020 * platform size. This matches
3021 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3023 data_len = 4 /* flags */
3024 + 4 /* flag mask */
3025 + 8 /* uid */
3026 + 8 /* gid */
3027 + 4 /* ngroups */
3028 + 4 /* num_sids */
3029 + 4 /* SID bytes */
3030 + 4 /* pad/reserved */
3031 + (conn->server_info->utok.ngroups * 8)
3032 /* groups list */
3033 + (conn->server_info->ptok->num_sids *
3034 SID_MAX_SIZE)
3035 /* SID list */;
3037 SIVAL(pdata, 0, flags);
3038 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3039 SBIG_UINT(pdata, 8,
3040 (SMB_BIG_UINT)conn->server_info->utok.uid);
3041 SBIG_UINT(pdata, 16,
3042 (SMB_BIG_UINT)conn->server_info->utok.gid);
3045 if (data_len >= max_data_bytes) {
3046 /* Potential overflow, skip the GIDs and SIDs. */
3048 SIVAL(pdata, 24, 0); /* num_groups */
3049 SIVAL(pdata, 28, 0); /* num_sids */
3050 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3051 SIVAL(pdata, 36, 0); /* reserved */
3053 data_len = 40;
3054 break;
3057 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3058 SIVAL(pdata, 28, conn->server_info->num_sids);
3060 /* We walk the SID list twice, but this call is fairly
3061 * infrequent, and I don't expect that it's performance
3062 * sensitive -- jpeach
3064 for (i = 0, sid_bytes = 0;
3065 i < conn->server_info->ptok->num_sids; ++i) {
3066 sid_bytes += ndr_size_dom_sid(
3067 &conn->server_info->ptok->user_sids[i],
3071 /* SID list byte count */
3072 SIVAL(pdata, 32, sid_bytes);
3074 /* 4 bytes pad/reserved - must be zero */
3075 SIVAL(pdata, 36, 0);
3076 data_len = 40;
3078 /* GID list */
3079 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3080 SBIG_UINT(pdata, data_len,
3081 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3082 data_len += 8;
3085 /* SID list */
3086 for (i = 0;
3087 i < conn->server_info->ptok->num_sids; ++i) {
3088 int sid_len = ndr_size_dom_sid(
3089 &conn->server_info->ptok->user_sids[i],
3092 sid_linearize(pdata + data_len, sid_len,
3093 &conn->server_info->ptok->user_sids[i]);
3094 data_len += sid_len;
3097 break;
3100 case SMB_MAC_QUERY_FS_INFO:
3102 * Thursby MAC extension... ONLY on NTFS filesystems
3103 * once we do streams then we don't need this
3105 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3106 data_len = 88;
3107 SIVAL(pdata,84,0x100); /* Don't support mac... */
3108 break;
3110 /* drop through */
3111 default:
3112 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3113 return;
3117 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3118 max_data_bytes);
3120 DEBUG( 4, ( "%s info_level = %d\n",
3121 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3123 return;
3126 /****************************************************************************
3127 Reply to a TRANS2_SETFSINFO (set filesystem info).
3128 ****************************************************************************/
3130 static void call_trans2setfsinfo(connection_struct *conn,
3131 struct smb_request *req,
3132 char **pparams, int total_params,
3133 char **ppdata, int total_data,
3134 unsigned int max_data_bytes)
3136 char *pdata = *ppdata;
3137 char *params = *pparams;
3138 uint16 info_level;
3140 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3142 /* */
3143 if (total_params < 4) {
3144 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3145 total_params));
3146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3147 return;
3150 info_level = SVAL(params,2);
3152 if (IS_IPC(conn)) {
3153 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3154 info_level != SMB_SET_CIFS_UNIX_INFO) {
3155 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3156 "info level (0x%x) on IPC$.\n",
3157 (unsigned int)info_level));
3158 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3159 return;
3163 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3164 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3165 DEBUG(0,("call_trans2setfsinfo: encryption required "
3166 "and info level 0x%x sent.\n",
3167 (unsigned int)info_level));
3168 exit_server_cleanly("encryption required "
3169 "on connection");
3170 return;
3174 switch(info_level) {
3175 case SMB_SET_CIFS_UNIX_INFO:
3177 uint16 client_unix_major;
3178 uint16 client_unix_minor;
3179 uint32 client_unix_cap_low;
3180 uint32 client_unix_cap_high;
3182 if (!lp_unix_extensions()) {
3183 reply_nterror(req,
3184 NT_STATUS_INVALID_LEVEL);
3185 return;
3188 /* There should be 12 bytes of capabilities set. */
3189 if (total_data < 8) {
3190 reply_nterror(
3191 req,
3192 NT_STATUS_INVALID_PARAMETER);
3193 return;
3195 client_unix_major = SVAL(pdata,0);
3196 client_unix_minor = SVAL(pdata,2);
3197 client_unix_cap_low = IVAL(pdata,4);
3198 client_unix_cap_high = IVAL(pdata,8);
3199 /* Just print these values for now. */
3200 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3201 cap_low = 0x%x, cap_high = 0x%x\n",
3202 (unsigned int)client_unix_major,
3203 (unsigned int)client_unix_minor,
3204 (unsigned int)client_unix_cap_low,
3205 (unsigned int)client_unix_cap_high ));
3207 /* Here is where we must switch to posix pathname processing... */
3208 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3209 lp_set_posix_pathnames();
3210 mangle_change_to_posix();
3213 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3214 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3215 /* Client that knows how to do posix locks,
3216 * but not posix open/mkdir operations. Set a
3217 * default type for read/write checks. */
3219 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3222 break;
3225 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3227 NTSTATUS status;
3228 size_t param_len = 0;
3229 size_t data_len = total_data;
3231 if (!lp_unix_extensions()) {
3232 reply_nterror(
3233 req,
3234 NT_STATUS_INVALID_LEVEL);
3235 return;
3238 if (lp_smb_encrypt(SNUM(conn)) == false) {
3239 reply_nterror(
3240 req,
3241 NT_STATUS_NOT_SUPPORTED);
3242 return;
3245 DEBUG( 4,("call_trans2setfsinfo: "
3246 "request transport encryption.\n"));
3248 status = srv_request_encryption_setup(conn,
3249 (unsigned char **)ppdata,
3250 &data_len,
3251 (unsigned char **)pparams,
3252 &param_len);
3254 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3255 !NT_STATUS_IS_OK(status)) {
3256 reply_nterror(req, status);
3257 return;
3260 send_trans2_replies(conn, req,
3261 *pparams,
3262 param_len,
3263 *ppdata,
3264 data_len,
3265 max_data_bytes);
3267 if (NT_STATUS_IS_OK(status)) {
3268 /* Server-side transport
3269 * encryption is now *on*. */
3270 status = srv_encryption_start(conn);
3271 if (!NT_STATUS_IS_OK(status)) {
3272 exit_server_cleanly(
3273 "Failure in setting "
3274 "up encrypted transport");
3277 return;
3280 case SMB_FS_QUOTA_INFORMATION:
3282 files_struct *fsp = NULL;
3283 SMB_NTQUOTA_STRUCT quotas;
3285 ZERO_STRUCT(quotas);
3287 /* access check */
3288 if ((conn->server_info->utok.uid != 0)
3289 ||!CAN_WRITE(conn)) {
3290 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3291 lp_servicename(SNUM(conn)),
3292 conn->server_info->unix_name));
3293 reply_doserror(req, ERRSRV, ERRaccess);
3294 return;
3297 /* note: normaly there're 48 bytes,
3298 * but we didn't use the last 6 bytes for now
3299 * --metze
3301 fsp = file_fsp(SVAL(params,0));
3303 if (!check_fsp_ntquota_handle(conn, req,
3304 fsp)) {
3305 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3306 reply_nterror(
3307 req, NT_STATUS_INVALID_HANDLE);
3308 return;
3311 if (total_data < 42) {
3312 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3313 total_data));
3314 reply_nterror(
3315 req,
3316 NT_STATUS_INVALID_PARAMETER);
3317 return;
3320 /* unknown_1 24 NULL bytes in pdata*/
3322 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3323 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3324 #ifdef LARGE_SMB_OFF_T
3325 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3326 #else /* LARGE_SMB_OFF_T */
3327 if ((IVAL(pdata,28) != 0)&&
3328 ((quotas.softlim != 0xFFFFFFFF)||
3329 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3330 /* more than 32 bits? */
3331 reply_nterror(
3332 req,
3333 NT_STATUS_INVALID_PARAMETER);
3334 return;
3336 #endif /* LARGE_SMB_OFF_T */
3338 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3339 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3340 #ifdef LARGE_SMB_OFF_T
3341 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3342 #else /* LARGE_SMB_OFF_T */
3343 if ((IVAL(pdata,36) != 0)&&
3344 ((quotas.hardlim != 0xFFFFFFFF)||
3345 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3346 /* more than 32 bits? */
3347 reply_nterror(
3348 req,
3349 NT_STATUS_INVALID_PARAMETER);
3350 return;
3352 #endif /* LARGE_SMB_OFF_T */
3354 /* quota_flags 2 bytes **/
3355 quotas.qflags = SVAL(pdata,40);
3357 /* unknown_2 6 NULL bytes follow*/
3359 /* now set the quotas */
3360 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3361 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3362 reply_doserror(req, ERRSRV, ERRerror);
3363 return;
3366 break;
3368 default:
3369 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3370 info_level));
3371 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3372 return;
3373 break;
3377 * sending this reply works fine,
3378 * but I'm not sure it's the same
3379 * like windows do...
3380 * --metze
3382 reply_outbuf(req, 10, 0);
3385 #if defined(HAVE_POSIX_ACLS)
3386 /****************************************************************************
3387 Utility function to count the number of entries in a POSIX acl.
3388 ****************************************************************************/
3390 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3392 unsigned int ace_count = 0;
3393 int entry_id = SMB_ACL_FIRST_ENTRY;
3394 SMB_ACL_ENTRY_T entry;
3396 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3397 /* get_next... */
3398 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3399 entry_id = SMB_ACL_NEXT_ENTRY;
3401 ace_count++;
3403 return ace_count;
3406 /****************************************************************************
3407 Utility function to marshall a POSIX acl into wire format.
3408 ****************************************************************************/
3410 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3412 int entry_id = SMB_ACL_FIRST_ENTRY;
3413 SMB_ACL_ENTRY_T entry;
3415 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3416 SMB_ACL_TAG_T tagtype;
3417 SMB_ACL_PERMSET_T permset;
3418 unsigned char perms = 0;
3419 unsigned int own_grp;
3421 /* get_next... */
3422 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3423 entry_id = SMB_ACL_NEXT_ENTRY;
3426 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3427 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3428 return False;
3431 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3432 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3433 return False;
3436 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3437 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3438 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3440 SCVAL(pdata,1,perms);
3442 switch (tagtype) {
3443 case SMB_ACL_USER_OBJ:
3444 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3445 own_grp = (unsigned int)pst->st_uid;
3446 SIVAL(pdata,2,own_grp);
3447 SIVAL(pdata,6,0);
3448 break;
3449 case SMB_ACL_USER:
3451 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3452 if (!puid) {
3453 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3454 return False;
3456 own_grp = (unsigned int)*puid;
3457 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3458 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3459 SIVAL(pdata,2,own_grp);
3460 SIVAL(pdata,6,0);
3461 break;
3463 case SMB_ACL_GROUP_OBJ:
3464 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3465 own_grp = (unsigned int)pst->st_gid;
3466 SIVAL(pdata,2,own_grp);
3467 SIVAL(pdata,6,0);
3468 break;
3469 case SMB_ACL_GROUP:
3471 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3472 if (!pgid) {
3473 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3474 return False;
3476 own_grp = (unsigned int)*pgid;
3477 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3478 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3479 SIVAL(pdata,2,own_grp);
3480 SIVAL(pdata,6,0);
3481 break;
3483 case SMB_ACL_MASK:
3484 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3485 SIVAL(pdata,2,0xFFFFFFFF);
3486 SIVAL(pdata,6,0xFFFFFFFF);
3487 break;
3488 case SMB_ACL_OTHER:
3489 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3490 SIVAL(pdata,2,0xFFFFFFFF);
3491 SIVAL(pdata,6,0xFFFFFFFF);
3492 break;
3493 default:
3494 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3495 return False;
3497 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3500 return True;
3502 #endif
3504 /****************************************************************************
3505 Store the FILE_UNIX_BASIC info.
3506 ****************************************************************************/
3508 static char *store_file_unix_basic(connection_struct *conn,
3509 char *pdata,
3510 files_struct *fsp,
3511 const SMB_STRUCT_STAT *psbuf)
3513 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3514 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3516 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3517 pdata += 8;
3519 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3520 pdata += 8;
3522 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3523 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3524 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3525 pdata += 24;
3527 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3528 SIVAL(pdata,4,0);
3529 pdata += 8;
3531 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3532 SIVAL(pdata,4,0);
3533 pdata += 8;
3535 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3536 pdata += 4;
3538 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3539 SIVAL(pdata,4,0);
3540 pdata += 8;
3542 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3543 SIVAL(pdata,4,0);
3544 pdata += 8;
3546 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3547 pdata += 8;
3549 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3550 SIVAL(pdata,4,0);
3551 pdata += 8;
3553 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3554 SIVAL(pdata,4,0);
3555 pdata += 8;
3557 return pdata;
3560 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3561 * the chflags(2) (or equivalent) flags.
3563 * XXX: this really should be behind the VFS interface. To do this, we would
3564 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3565 * Each VFS module could then implement its own mapping as appropriate for the
3566 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3568 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3569 info2_flags_map[] =
3571 #ifdef UF_NODUMP
3572 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3573 #endif
3575 #ifdef UF_IMMUTABLE
3576 { UF_IMMUTABLE, EXT_IMMUTABLE },
3577 #endif
3579 #ifdef UF_APPEND
3580 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3581 #endif
3583 #ifdef UF_HIDDEN
3584 { UF_HIDDEN, EXT_HIDDEN },
3585 #endif
3587 /* Do not remove. We need to guarantee that this array has at least one
3588 * entry to build on HP-UX.
3590 { 0, 0 }
3594 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3595 uint32 *smb_fflags, uint32 *smb_fmask)
3597 #ifdef HAVE_STAT_ST_FLAGS
3598 int i;
3600 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3601 *smb_fmask |= info2_flags_map[i].smb_fflag;
3602 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3603 *smb_fflags |= info2_flags_map[i].smb_fflag;
3606 #endif /* HAVE_STAT_ST_FLAGS */
3609 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3610 const uint32 smb_fflags,
3611 const uint32 smb_fmask,
3612 int *stat_fflags)
3614 #ifdef HAVE_STAT_ST_FLAGS
3615 uint32 max_fmask = 0;
3616 int i;
3618 *stat_fflags = psbuf->st_flags;
3620 /* For each flags requested in smb_fmask, check the state of the
3621 * corresponding flag in smb_fflags and set or clear the matching
3622 * stat flag.
3625 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3626 max_fmask |= info2_flags_map[i].smb_fflag;
3627 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3628 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3629 *stat_fflags |= info2_flags_map[i].stat_fflag;
3630 } else {
3631 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3636 /* If smb_fmask is asking to set any bits that are not supported by
3637 * our flag mappings, we should fail.
3639 if ((smb_fmask & max_fmask) != smb_fmask) {
3640 return False;
3643 return True;
3644 #else
3645 return False;
3646 #endif /* HAVE_STAT_ST_FLAGS */
3650 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3651 * of file flags and birth (create) time.
3653 static char *store_file_unix_basic_info2(connection_struct *conn,
3654 char *pdata,
3655 files_struct *fsp,
3656 const SMB_STRUCT_STAT *psbuf)
3658 uint32 file_flags = 0;
3659 uint32 flags_mask = 0;
3661 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3663 /* Create (birth) time 64 bit */
3664 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3665 pdata += 8;
3667 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3668 SIVAL(pdata, 0, file_flags); /* flags */
3669 SIVAL(pdata, 4, flags_mask); /* mask */
3670 pdata += 8;
3672 return pdata;
3675 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3676 const struct stream_struct *streams,
3677 char *data,
3678 unsigned int max_data_bytes,
3679 unsigned int *data_size)
3681 unsigned int i;
3682 unsigned int ofs = 0;
3684 for (i=0; i<num_streams; i++) {
3685 unsigned int next_offset;
3686 size_t namelen;
3687 smb_ucs2_t *namebuf;
3689 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3690 streams[i].name, &namelen) ||
3691 namelen <= 2)
3693 return NT_STATUS_INVALID_PARAMETER;
3697 * name_buf is now null-terminated, we need to marshall as not
3698 * terminated
3701 namelen -= 2;
3703 if (ofs + 24 + namelen > max_data_bytes) {
3704 TALLOC_FREE(namebuf);
3705 return NT_STATUS_BUFFER_TOO_SMALL;
3708 SIVAL(data, ofs+4, namelen);
3709 SOFF_T(data, ofs+8, streams[i].size);
3710 SOFF_T(data, ofs+16, streams[i].alloc_size);
3711 memcpy(data+ofs+24, namebuf, namelen);
3712 TALLOC_FREE(namebuf);
3714 next_offset = ofs + 24 + namelen;
3716 if (i == num_streams-1) {
3717 SIVAL(data, ofs, 0);
3719 else {
3720 unsigned int align = ndr_align_size(next_offset, 8);
3722 if (next_offset + align > max_data_bytes) {
3723 return NT_STATUS_BUFFER_TOO_SMALL;
3726 memset(data+next_offset, 0, align);
3727 next_offset += align;
3729 SIVAL(data, ofs, next_offset - ofs);
3730 ofs = next_offset;
3733 ofs = next_offset;
3736 *data_size = ofs;
3738 return NT_STATUS_OK;
3741 /****************************************************************************
3742 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3743 ****************************************************************************/
3745 static void call_trans2qpipeinfo(connection_struct *conn,
3746 struct smb_request *req,
3747 unsigned int tran_call,
3748 char **pparams, int total_params,
3749 char **ppdata, int total_data,
3750 unsigned int max_data_bytes)
3752 char *params = *pparams;
3753 char *pdata = *ppdata;
3754 unsigned int data_size = 0;
3755 unsigned int param_size = 2;
3756 uint16 info_level;
3757 smb_np_struct *p_pipe = NULL;
3759 if (!params) {
3760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3761 return;
3764 if (total_params < 4) {
3765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3766 return;
3769 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3770 if (p_pipe == NULL) {
3771 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3772 return;
3775 info_level = SVAL(params,2);
3777 *pparams = (char *)SMB_REALLOC(*pparams,2);
3778 if (*pparams == NULL) {
3779 reply_nterror(req, NT_STATUS_NO_MEMORY);
3780 return;
3782 params = *pparams;
3783 SSVAL(params,0,0);
3784 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3785 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3786 if (*ppdata == NULL ) {
3787 reply_nterror(req, NT_STATUS_NO_MEMORY);
3788 return;
3790 pdata = *ppdata;
3792 switch (info_level) {
3793 case SMB_FILE_STANDARD_INFORMATION:
3794 memset(pdata,0,24);
3795 SOFF_T(pdata,0,4096LL);
3796 SIVAL(pdata,16,1);
3797 SIVAL(pdata,20,1);
3798 data_size = 24;
3799 break;
3801 default:
3802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3803 return;
3806 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3807 max_data_bytes);
3809 return;
3812 /****************************************************************************
3813 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3814 file name or file id).
3815 ****************************************************************************/
3817 static void call_trans2qfilepathinfo(connection_struct *conn,
3818 struct smb_request *req,
3819 unsigned int tran_call,
3820 char **pparams, int total_params,
3821 char **ppdata, int total_data,
3822 unsigned int max_data_bytes)
3824 char *params = *pparams;
3825 char *pdata = *ppdata;
3826 char *dstart, *dend;
3827 uint16 info_level;
3828 int mode=0;
3829 int nlink;
3830 SMB_OFF_T file_size=0;
3831 SMB_BIG_UINT allocation_size=0;
3832 unsigned int data_size = 0;
3833 unsigned int param_size = 2;
3834 SMB_STRUCT_STAT sbuf;
3835 char *dos_fname = NULL;
3836 char *fname = NULL;
3837 char *fullpathname;
3838 char *base_name;
3839 char *p;
3840 SMB_OFF_T pos = 0;
3841 bool delete_pending = False;
3842 int len;
3843 time_t create_time, mtime, atime;
3844 struct timespec create_time_ts, mtime_ts, atime_ts;
3845 struct timespec write_time_ts;
3846 files_struct *fsp = NULL;
3847 struct file_id fileid;
3848 struct ea_list *ea_list = NULL;
3849 char *lock_data = NULL;
3850 bool ms_dfs_link = false;
3851 TALLOC_CTX *ctx = talloc_tos();
3853 if (!params) {
3854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3855 return;
3858 ZERO_STRUCT(sbuf);
3859 ZERO_STRUCT(write_time_ts);
3861 if (tran_call == TRANSACT2_QFILEINFO) {
3862 if (total_params < 4) {
3863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3864 return;
3867 if (IS_IPC(conn)) {
3868 call_trans2qpipeinfo(conn, req, tran_call,
3869 pparams, total_params,
3870 ppdata, total_data,
3871 max_data_bytes);
3872 return;
3875 fsp = file_fsp(SVAL(params,0));
3876 info_level = SVAL(params,2);
3878 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3880 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3881 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3882 return;
3885 /* Initial check for valid fsp ptr. */
3886 if (!check_fsp_open(conn, req, fsp)) {
3887 return;
3890 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3891 if (!fname) {
3892 reply_nterror(req, NT_STATUS_NO_MEMORY);
3893 return;
3896 if(fsp->fake_file_handle) {
3898 * This is actually for the QUOTA_FAKE_FILE --metze
3901 /* We know this name is ok, it's already passed the checks. */
3903 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3905 * This is actually a QFILEINFO on a directory
3906 * handle (returned from an NT SMB). NT5.0 seems
3907 * to do this call. JRA.
3910 if (INFO_LEVEL_IS_UNIX(info_level)) {
3911 /* Always do lstat for UNIX calls. */
3912 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3913 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3914 reply_unixerror(req,ERRDOS,ERRbadpath);
3915 return;
3917 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3918 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3919 reply_unixerror(req, ERRDOS, ERRbadpath);
3920 return;
3923 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3924 get_file_infos(fileid, &delete_pending, &write_time_ts);
3925 } else {
3927 * Original code - this is an open file.
3929 if (!check_fsp(conn, req, fsp)) {
3930 return;
3933 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3934 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3935 reply_unixerror(req, ERRDOS, ERRbadfid);
3936 return;
3938 pos = fsp->fh->position_information;
3939 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3940 get_file_infos(fileid, &delete_pending, &write_time_ts);
3943 } else {
3944 NTSTATUS status = NT_STATUS_OK;
3946 /* qpathinfo */
3947 if (total_params < 7) {
3948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3949 return;
3952 info_level = SVAL(params,0);
3954 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3956 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3958 return;
3961 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3962 total_params - 6,
3963 STR_TERMINATE, &status);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 reply_nterror(req, status);
3966 return;
3969 status = resolve_dfspath(ctx,
3970 conn,
3971 req->flags2 & FLAGS2_DFS_PATHNAMES,
3972 fname,
3973 &fname);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3976 reply_botherror(req,
3977 NT_STATUS_PATH_NOT_COVERED,
3978 ERRSRV, ERRbadpath);
3980 reply_nterror(req, status);
3981 return;
3984 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3985 if (!NT_STATUS_IS_OK(status)) {
3986 reply_nterror(req, status);
3987 return;
3989 status = check_name(conn, fname);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3992 reply_nterror(req, status);
3993 return;
3996 if (INFO_LEVEL_IS_UNIX(info_level)) {
3997 /* Always do lstat for UNIX calls. */
3998 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3999 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4000 reply_unixerror(req, ERRDOS, ERRbadpath);
4001 return;
4004 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4005 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4007 if (!ms_dfs_link) {
4008 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4009 reply_unixerror(req, ERRDOS, ERRbadpath);
4010 return;
4014 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4015 get_file_infos(fileid, &delete_pending, &write_time_ts);
4016 if (delete_pending) {
4017 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4018 return;
4022 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4023 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4024 return;
4027 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4028 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4030 p = strrchr_m(fname,'/');
4031 if (!p)
4032 base_name = fname;
4033 else
4034 base_name = p+1;
4036 if (ms_dfs_link) {
4037 mode = dos_mode_msdfs(conn,fname,&sbuf);
4038 } else {
4039 mode = dos_mode(conn,fname,&sbuf);
4041 if (!mode)
4042 mode = FILE_ATTRIBUTE_NORMAL;
4044 nlink = sbuf.st_nlink;
4046 if (nlink && (mode&aDIR)) {
4047 nlink = 1;
4050 if ((nlink > 0) && delete_pending) {
4051 nlink -= 1;
4054 fullpathname = fname;
4055 if (!(mode & aDIR))
4056 file_size = get_file_size(sbuf);
4058 /* Pull out any data sent here before we realloc. */
4059 switch (info_level) {
4060 case SMB_INFO_QUERY_EAS_FROM_LIST:
4062 /* Pull any EA list from the data portion. */
4063 uint32 ea_size;
4065 if (total_data < 4) {
4066 reply_nterror(
4067 req, NT_STATUS_INVALID_PARAMETER);
4068 return;
4070 ea_size = IVAL(pdata,0);
4072 if (total_data > 0 && ea_size != total_data) {
4073 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4074 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4075 reply_nterror(
4076 req, NT_STATUS_INVALID_PARAMETER);
4077 return;
4080 if (!lp_ea_support(SNUM(conn))) {
4081 reply_doserror(req, ERRDOS,
4082 ERReasnotsupported);
4083 return;
4086 /* Pull out the list of names. */
4087 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4088 if (!ea_list) {
4089 reply_nterror(
4090 req, NT_STATUS_INVALID_PARAMETER);
4091 return;
4093 break;
4096 case SMB_QUERY_POSIX_LOCK:
4098 if (fsp == NULL || fsp->fh->fd == -1) {
4099 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4100 return;
4103 if (total_data != POSIX_LOCK_DATA_SIZE) {
4104 reply_nterror(
4105 req, NT_STATUS_INVALID_PARAMETER);
4106 return;
4109 /* Copy the lock range data. */
4110 lock_data = (char *)TALLOC_MEMDUP(
4111 ctx, pdata, total_data);
4112 if (!lock_data) {
4113 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114 return;
4117 default:
4118 break;
4121 *pparams = (char *)SMB_REALLOC(*pparams,2);
4122 if (*pparams == NULL) {
4123 reply_nterror(req, NT_STATUS_NO_MEMORY);
4124 return;
4126 params = *pparams;
4127 SSVAL(params,0,0);
4128 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4129 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4130 if (*ppdata == NULL ) {
4131 reply_nterror(req, NT_STATUS_NO_MEMORY);
4132 return;
4134 pdata = *ppdata;
4135 dstart = pdata;
4136 dend = dstart + data_size - 1;
4138 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4139 mtime_ts = get_mtimespec(&sbuf);
4140 atime_ts = get_atimespec(&sbuf);
4142 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4144 if (!fsp) {
4145 /* Do we have this path open ? */
4146 files_struct *fsp1;
4147 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4148 fsp1 = file_find_di_first(fileid);
4149 if (fsp1 && fsp1->initial_allocation_size) {
4150 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4154 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4155 mtime_ts = write_time_ts;
4158 if (lp_dos_filetime_resolution(SNUM(conn))) {
4159 dos_filetime_timespec(&create_time_ts);
4160 dos_filetime_timespec(&mtime_ts);
4161 dos_filetime_timespec(&atime_ts);
4164 create_time = convert_timespec_to_time_t(create_time_ts);
4165 mtime = convert_timespec_to_time_t(mtime_ts);
4166 atime = convert_timespec_to_time_t(atime_ts);
4168 /* NT expects the name to be in an exact form of the *full*
4169 filename. See the trans2 torture test */
4170 if (ISDOT(base_name)) {
4171 dos_fname = talloc_strdup(ctx, "\\");
4172 if (!dos_fname) {
4173 reply_nterror(req, NT_STATUS_NO_MEMORY);
4174 return;
4176 } else {
4177 dos_fname = talloc_asprintf(ctx,
4178 "\\%s",
4179 fname);
4180 if (!dos_fname) {
4181 reply_nterror(req, NT_STATUS_NO_MEMORY);
4182 return;
4184 string_replace(dos_fname, '/', '\\');
4187 switch (info_level) {
4188 case SMB_INFO_STANDARD:
4189 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4190 data_size = 22;
4191 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4192 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4193 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4194 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4195 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4196 SSVAL(pdata,l1_attrFile,mode);
4197 break;
4199 case SMB_INFO_QUERY_EA_SIZE:
4201 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4202 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4203 data_size = 26;
4204 srv_put_dos_date2(pdata,0,create_time);
4205 srv_put_dos_date2(pdata,4,atime);
4206 srv_put_dos_date2(pdata,8,mtime); /* write time */
4207 SIVAL(pdata,12,(uint32)file_size);
4208 SIVAL(pdata,16,(uint32)allocation_size);
4209 SSVAL(pdata,20,mode);
4210 SIVAL(pdata,22,ea_size);
4211 break;
4214 case SMB_INFO_IS_NAME_VALID:
4215 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4216 if (tran_call == TRANSACT2_QFILEINFO) {
4217 /* os/2 needs this ? really ?*/
4218 reply_doserror(req, ERRDOS, ERRbadfunc);
4219 return;
4221 data_size = 0;
4222 param_size = 0;
4223 break;
4225 case SMB_INFO_QUERY_EAS_FROM_LIST:
4227 size_t total_ea_len = 0;
4228 struct ea_list *ea_file_list = NULL;
4230 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4232 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4233 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4235 if (!ea_list || (total_ea_len > data_size)) {
4236 data_size = 4;
4237 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4238 break;
4241 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4242 break;
4245 case SMB_INFO_QUERY_ALL_EAS:
4247 /* We have data_size bytes to put EA's into. */
4248 size_t total_ea_len = 0;
4250 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4252 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4253 if (!ea_list || (total_ea_len > data_size)) {
4254 data_size = 4;
4255 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4256 break;
4259 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4260 break;
4263 case SMB_FILE_BASIC_INFORMATION:
4264 case SMB_QUERY_FILE_BASIC_INFO:
4266 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4267 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4268 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4269 } else {
4270 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4271 data_size = 40;
4272 SIVAL(pdata,36,0);
4274 put_long_date_timespec(pdata,create_time_ts);
4275 put_long_date_timespec(pdata+8,atime_ts);
4276 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4277 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4278 SIVAL(pdata,32,mode);
4280 DEBUG(5,("SMB_QFBI - "));
4281 DEBUG(5,("create: %s ", ctime(&create_time)));
4282 DEBUG(5,("access: %s ", ctime(&atime)));
4283 DEBUG(5,("write: %s ", ctime(&mtime)));
4284 DEBUG(5,("change: %s ", ctime(&mtime)));
4285 DEBUG(5,("mode: %x\n", mode));
4286 break;
4288 case SMB_FILE_STANDARD_INFORMATION:
4289 case SMB_QUERY_FILE_STANDARD_INFO:
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4292 data_size = 24;
4293 SOFF_T(pdata,0,allocation_size);
4294 SOFF_T(pdata,8,file_size);
4295 SIVAL(pdata,16,nlink);
4296 SCVAL(pdata,20,delete_pending?1:0);
4297 SCVAL(pdata,21,(mode&aDIR)?1:0);
4298 SSVAL(pdata,22,0); /* Padding. */
4299 break;
4301 case SMB_FILE_EA_INFORMATION:
4302 case SMB_QUERY_FILE_EA_INFO:
4304 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4305 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4306 data_size = 4;
4307 SIVAL(pdata,0,ea_size);
4308 break;
4311 /* Get the 8.3 name - used if NT SMB was negotiated. */
4312 case SMB_QUERY_FILE_ALT_NAME_INFO:
4313 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4315 char mangled_name[13];
4316 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4317 if (!name_to_8_3(base_name,mangled_name,
4318 True,conn->params)) {
4319 reply_nterror(
4320 req,
4321 NT_STATUS_NO_MEMORY);
4323 len = srvstr_push(dstart, req->flags2,
4324 pdata+4, mangled_name,
4325 PTR_DIFF(dend, pdata+4),
4326 STR_UNICODE);
4327 data_size = 4 + len;
4328 SIVAL(pdata,0,len);
4329 break;
4332 case SMB_QUERY_FILE_NAME_INFO:
4334 this must be *exactly* right for ACLs on mapped drives to work
4336 len = srvstr_push(dstart, req->flags2,
4337 pdata+4, dos_fname,
4338 PTR_DIFF(dend, pdata+4),
4339 STR_UNICODE);
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4341 data_size = 4 + len;
4342 SIVAL(pdata,0,len);
4343 break;
4345 case SMB_FILE_ALLOCATION_INFORMATION:
4346 case SMB_QUERY_FILE_ALLOCATION_INFO:
4347 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4348 data_size = 8;
4349 SOFF_T(pdata,0,allocation_size);
4350 break;
4352 case SMB_FILE_END_OF_FILE_INFORMATION:
4353 case SMB_QUERY_FILE_END_OF_FILEINFO:
4354 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4355 data_size = 8;
4356 SOFF_T(pdata,0,file_size);
4357 break;
4359 case SMB_QUERY_FILE_ALL_INFO:
4360 case SMB_FILE_ALL_INFORMATION:
4362 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4363 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4364 put_long_date_timespec(pdata,create_time_ts);
4365 put_long_date_timespec(pdata+8,atime_ts);
4366 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4367 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4368 SIVAL(pdata,32,mode);
4369 SIVAL(pdata,36,0); /* padding. */
4370 pdata += 40;
4371 SOFF_T(pdata,0,allocation_size);
4372 SOFF_T(pdata,8,file_size);
4373 SIVAL(pdata,16,nlink);
4374 SCVAL(pdata,20,delete_pending);
4375 SCVAL(pdata,21,(mode&aDIR)?1:0);
4376 SSVAL(pdata,22,0);
4377 pdata += 24;
4378 SIVAL(pdata,0,ea_size);
4379 pdata += 4; /* EA info */
4380 len = srvstr_push(dstart, req->flags2,
4381 pdata+4, dos_fname,
4382 PTR_DIFF(dend, pdata+4),
4383 STR_UNICODE);
4384 SIVAL(pdata,0,len);
4385 pdata += 4 + len;
4386 data_size = PTR_DIFF(pdata,(*ppdata));
4387 break;
4389 case SMB_FILE_INTERNAL_INFORMATION:
4390 /* This should be an index number - looks like
4391 dev/ino to me :-)
4393 I think this causes us to fail the IFSKIT
4394 BasicFileInformationTest. -tpot */
4396 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4397 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4398 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4399 data_size = 8;
4400 break;
4402 case SMB_FILE_ACCESS_INFORMATION:
4403 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4404 if (fsp) {
4405 SIVAL(pdata,0,fsp->access_mask);
4406 } else {
4407 /* GENERIC_EXECUTE mapping from Windows */
4408 SIVAL(pdata,0,0x12019F);
4410 data_size = 4;
4411 break;
4413 case SMB_FILE_NAME_INFORMATION:
4414 /* Pathname with leading '\'. */
4416 size_t byte_len;
4417 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4419 SIVAL(pdata,0,byte_len);
4420 data_size = 4 + byte_len;
4421 break;
4424 case SMB_FILE_DISPOSITION_INFORMATION:
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4426 data_size = 1;
4427 SCVAL(pdata,0,delete_pending);
4428 break;
4430 case SMB_FILE_POSITION_INFORMATION:
4431 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4432 data_size = 8;
4433 SOFF_T(pdata,0,pos);
4434 break;
4436 case SMB_FILE_MODE_INFORMATION:
4437 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4438 SIVAL(pdata,0,mode);
4439 data_size = 4;
4440 break;
4442 case SMB_FILE_ALIGNMENT_INFORMATION:
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4444 SIVAL(pdata,0,0); /* No alignment needed. */
4445 data_size = 4;
4446 break;
4449 * NT4 server just returns "invalid query" to this - if we try
4450 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4451 * want this. JRA.
4453 /* The first statement above is false - verified using Thursby
4454 * client against NT4 -- gcolley.
4456 case SMB_QUERY_FILE_STREAM_INFO:
4457 case SMB_FILE_STREAM_INFORMATION: {
4458 unsigned int num_streams;
4459 struct stream_struct *streams;
4460 NTSTATUS status;
4462 DEBUG(10,("call_trans2qfilepathinfo: "
4463 "SMB_FILE_STREAM_INFORMATION\n"));
4465 status = SMB_VFS_STREAMINFO(
4466 conn, fsp, fname, talloc_tos(),
4467 &num_streams, &streams);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 DEBUG(10, ("could not get stream info: %s\n",
4471 nt_errstr(status)));
4472 reply_nterror(req, status);
4473 return;
4476 status = marshall_stream_info(num_streams, streams,
4477 pdata, max_data_bytes,
4478 &data_size);
4480 if (!NT_STATUS_IS_OK(status)) {
4481 DEBUG(10, ("marshall_stream_info failed: %s\n",
4482 nt_errstr(status)));
4483 reply_nterror(req, status);
4484 return;
4487 TALLOC_FREE(streams);
4489 break;
4491 case SMB_QUERY_COMPRESSION_INFO:
4492 case SMB_FILE_COMPRESSION_INFORMATION:
4493 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4494 SOFF_T(pdata,0,file_size);
4495 SIVAL(pdata,8,0); /* ??? */
4496 SIVAL(pdata,12,0); /* ??? */
4497 data_size = 16;
4498 break;
4500 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4501 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4502 put_long_date_timespec(pdata,create_time_ts);
4503 put_long_date_timespec(pdata+8,atime_ts);
4504 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4505 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4506 SOFF_T(pdata,32,allocation_size);
4507 SOFF_T(pdata,40,file_size);
4508 SIVAL(pdata,48,mode);
4509 SIVAL(pdata,52,0); /* ??? */
4510 data_size = 56;
4511 break;
4513 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4514 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4515 SIVAL(pdata,0,mode);
4516 SIVAL(pdata,4,0);
4517 data_size = 8;
4518 break;
4521 * CIFS UNIX Extensions.
4524 case SMB_QUERY_FILE_UNIX_BASIC:
4526 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4527 data_size = PTR_DIFF(pdata,(*ppdata));
4530 int i;
4531 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4533 for (i=0; i<100; i++)
4534 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4535 DEBUG(4,("\n"));
4538 break;
4540 case SMB_QUERY_FILE_UNIX_INFO2:
4542 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4543 data_size = PTR_DIFF(pdata,(*ppdata));
4546 int i;
4547 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4549 for (i=0; i<100; i++)
4550 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4551 DEBUG(4,("\n"));
4554 break;
4556 case SMB_QUERY_FILE_UNIX_LINK:
4558 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4560 if (!buffer) {
4561 reply_nterror(req, NT_STATUS_NO_MEMORY);
4562 return;
4565 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4566 #ifdef S_ISLNK
4567 if(!S_ISLNK(sbuf.st_mode)) {
4568 reply_unixerror(req, ERRSRV,
4569 ERRbadlink);
4570 return;
4572 #else
4573 reply_unixerror(req, ERRDOS, ERRbadlink);
4574 return;
4575 #endif
4576 len = SMB_VFS_READLINK(conn,fullpathname,
4577 buffer, PATH_MAX);
4578 if (len == -1) {
4579 reply_unixerror(req, ERRDOS,
4580 ERRnoaccess);
4581 return;
4583 buffer[len] = 0;
4584 len = srvstr_push(dstart, req->flags2,
4585 pdata, buffer,
4586 PTR_DIFF(dend, pdata),
4587 STR_TERMINATE);
4588 pdata += len;
4589 data_size = PTR_DIFF(pdata,(*ppdata));
4591 break;
4594 #if defined(HAVE_POSIX_ACLS)
4595 case SMB_QUERY_POSIX_ACL:
4597 SMB_ACL_T file_acl = NULL;
4598 SMB_ACL_T def_acl = NULL;
4599 uint16 num_file_acls = 0;
4600 uint16 num_def_acls = 0;
4602 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4603 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4604 } else {
4605 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4608 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4609 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4610 fname ));
4611 reply_nterror(
4612 req,
4613 NT_STATUS_NOT_IMPLEMENTED);
4614 return;
4617 if (S_ISDIR(sbuf.st_mode)) {
4618 if (fsp && fsp->is_directory) {
4619 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4620 } else {
4621 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4623 def_acl = free_empty_sys_acl(conn, def_acl);
4626 num_file_acls = count_acl_entries(conn, file_acl);
4627 num_def_acls = count_acl_entries(conn, def_acl);
4629 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4630 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4631 data_size,
4632 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4633 SMB_POSIX_ACL_HEADER_SIZE) ));
4634 if (file_acl) {
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4637 if (def_acl) {
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4640 reply_nterror(
4641 req,
4642 NT_STATUS_BUFFER_TOO_SMALL);
4643 return;
4646 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4647 SSVAL(pdata,2,num_file_acls);
4648 SSVAL(pdata,4,num_def_acls);
4649 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4650 if (file_acl) {
4651 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4653 if (def_acl) {
4654 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4656 reply_nterror(
4657 req, NT_STATUS_INTERNAL_ERROR);
4658 return;
4660 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4661 if (file_acl) {
4662 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4664 if (def_acl) {
4665 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4667 reply_nterror(
4668 req,
4669 NT_STATUS_INTERNAL_ERROR);
4670 return;
4673 if (file_acl) {
4674 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4676 if (def_acl) {
4677 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4679 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4680 break;
4682 #endif
4685 case SMB_QUERY_POSIX_LOCK:
4687 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4688 SMB_BIG_UINT count;
4689 SMB_BIG_UINT offset;
4690 uint32 lock_pid;
4691 enum brl_type lock_type;
4693 if (total_data != POSIX_LOCK_DATA_SIZE) {
4694 reply_nterror(
4695 req, NT_STATUS_INVALID_PARAMETER);
4696 return;
4699 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4700 case POSIX_LOCK_TYPE_READ:
4701 lock_type = READ_LOCK;
4702 break;
4703 case POSIX_LOCK_TYPE_WRITE:
4704 lock_type = WRITE_LOCK;
4705 break;
4706 case POSIX_LOCK_TYPE_UNLOCK:
4707 default:
4708 /* There's no point in asking for an unlock... */
4709 reply_nterror(
4710 req,
4711 NT_STATUS_INVALID_PARAMETER);
4712 return;
4715 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4716 #if defined(HAVE_LONGLONG)
4717 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4718 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4719 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4720 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4721 #else /* HAVE_LONGLONG */
4722 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4723 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4724 #endif /* HAVE_LONGLONG */
4726 status = query_lock(fsp,
4727 &lock_pid,
4728 &count,
4729 &offset,
4730 &lock_type,
4731 POSIX_LOCK);
4733 if (ERROR_WAS_LOCK_DENIED(status)) {
4734 /* Here we need to report who has it locked... */
4735 data_size = POSIX_LOCK_DATA_SIZE;
4737 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4738 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4739 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4740 #if defined(HAVE_LONGLONG)
4741 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4742 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4743 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4744 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4745 #else /* HAVE_LONGLONG */
4746 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4747 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4748 #endif /* HAVE_LONGLONG */
4750 } else if (NT_STATUS_IS_OK(status)) {
4751 /* For success we just return a copy of what we sent
4752 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4753 data_size = POSIX_LOCK_DATA_SIZE;
4754 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4755 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4756 } else {
4757 reply_nterror(req, status);
4758 return;
4760 break;
4763 default:
4764 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4765 return;
4768 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4769 max_data_bytes);
4771 return;
4774 /****************************************************************************
4775 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4776 code.
4777 ****************************************************************************/
4779 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4780 connection_struct *conn,
4781 const char *oldname_in,
4782 const char *newname_in)
4784 SMB_STRUCT_STAT sbuf1, sbuf2;
4785 char *last_component_oldname = NULL;
4786 char *last_component_newname = NULL;
4787 char *oldname = NULL;
4788 char *newname = NULL;
4789 NTSTATUS status = NT_STATUS_OK;
4791 ZERO_STRUCT(sbuf1);
4792 ZERO_STRUCT(sbuf2);
4794 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4795 &last_component_oldname, &sbuf1);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 return status;
4800 status = check_name(conn, oldname);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 return status;
4805 /* source must already exist. */
4806 if (!VALID_STAT(sbuf1)) {
4807 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4810 status = unix_convert(ctx, conn, newname_in, False, &newname,
4811 &last_component_newname, &sbuf2);
4812 if (!NT_STATUS_IS_OK(status)) {
4813 return status;
4816 status = check_name(conn, newname);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 return status;
4821 /* Disallow if newname already exists. */
4822 if (VALID_STAT(sbuf2)) {
4823 return NT_STATUS_OBJECT_NAME_COLLISION;
4826 /* No links from a directory. */
4827 if (S_ISDIR(sbuf1.st_mode)) {
4828 return NT_STATUS_FILE_IS_A_DIRECTORY;
4831 /* Ensure this is within the share. */
4832 status = check_reduced_name(conn, oldname);
4833 if (!NT_STATUS_IS_OK(status)) {
4834 return status;
4837 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4839 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4840 status = map_nt_error_from_unix(errno);
4841 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4842 nt_errstr(status), newname, oldname));
4845 return status;
4848 /****************************************************************************
4849 Deal with setting the time from any of the setfilepathinfo functions.
4850 ****************************************************************************/
4852 NTSTATUS smb_set_file_time(connection_struct *conn,
4853 files_struct *fsp,
4854 const char *fname,
4855 const SMB_STRUCT_STAT *psbuf,
4856 struct timespec ts[2],
4857 bool setting_write_time)
4859 uint32 action =
4860 FILE_NOTIFY_CHANGE_LAST_ACCESS
4861 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4863 if (!VALID_STAT(*psbuf)) {
4864 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4867 /* get some defaults (no modifications) if any info is zero or -1. */
4868 if (null_timespec(ts[0])) {
4869 ts[0] = get_atimespec(psbuf);
4870 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4873 if (null_timespec(ts[1])) {
4874 ts[1] = get_mtimespec(psbuf);
4875 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4878 if (!setting_write_time) {
4879 /* ts[1] comes from change time, not write time. */
4880 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4883 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4884 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4887 * Try and set the times of this file if
4888 * they are different from the current values.
4892 struct timespec mts = get_mtimespec(psbuf);
4893 struct timespec ats = get_atimespec(psbuf);
4894 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4895 return NT_STATUS_OK;
4899 if (setting_write_time) {
4901 * This was a setfileinfo on an open file.
4902 * NT does this a lot. We also need to
4903 * set the time here, as it can be read by
4904 * FindFirst/FindNext and with the patch for bug #2045
4905 * in smbd/fileio.c it ensures that this timestamp is
4906 * kept sticky even after a write. We save the request
4907 * away and will set it on file close and after a write. JRA.
4910 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4911 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4913 if (fsp != NULL) {
4914 set_sticky_write_time_fsp(fsp, ts[1]);
4915 } else {
4916 set_sticky_write_time_path(conn, fname,
4917 vfs_file_id_from_sbuf(conn, psbuf),
4918 ts[1]);
4922 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4924 if(file_ntimes(conn, fname, ts)!=0) {
4925 return map_nt_error_from_unix(errno);
4927 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4929 return NT_STATUS_OK;
4932 /****************************************************************************
4933 Deal with setting the dosmode from any of the setfilepathinfo functions.
4934 ****************************************************************************/
4936 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4937 const char *fname,
4938 SMB_STRUCT_STAT *psbuf,
4939 uint32 dosmode)
4941 if (!VALID_STAT(*psbuf)) {
4942 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4945 if (dosmode) {
4946 if (S_ISDIR(psbuf->st_mode)) {
4947 dosmode |= aDIR;
4948 } else {
4949 dosmode &= ~aDIR;
4953 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4955 /* check the mode isn't different, before changing it */
4956 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4958 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4959 fname, (unsigned int)dosmode ));
4961 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4962 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4963 fname, strerror(errno)));
4964 return map_nt_error_from_unix(errno);
4967 return NT_STATUS_OK;
4970 /****************************************************************************
4971 Deal with setting the size from any of the setfilepathinfo functions.
4972 ****************************************************************************/
4974 static NTSTATUS smb_set_file_size(connection_struct *conn,
4975 struct smb_request *req,
4976 files_struct *fsp,
4977 const char *fname,
4978 SMB_STRUCT_STAT *psbuf,
4979 SMB_OFF_T size)
4981 NTSTATUS status = NT_STATUS_OK;
4982 files_struct *new_fsp = NULL;
4984 if (!VALID_STAT(*psbuf)) {
4985 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4988 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4990 if (size == get_file_size(*psbuf)) {
4991 return NT_STATUS_OK;
4994 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4995 fname, (double)size ));
4997 if (fsp && fsp->fh->fd != -1) {
4998 /* Handle based call. */
4999 if (vfs_set_filelen(fsp, size) == -1) {
5000 return map_nt_error_from_unix(errno);
5002 trigger_write_time_update_immediate(fsp);
5003 return NT_STATUS_OK;
5006 status = open_file_ntcreate(conn, req, fname, psbuf,
5007 FILE_WRITE_ATTRIBUTES,
5008 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5009 FILE_OPEN,
5011 FILE_ATTRIBUTE_NORMAL,
5012 FORCE_OPLOCK_BREAK_TO_NONE,
5013 NULL, &new_fsp);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 /* NB. We check for open_was_deferred in the caller. */
5017 return status;
5020 if (vfs_set_filelen(new_fsp, size) == -1) {
5021 status = map_nt_error_from_unix(errno);
5022 close_file(new_fsp,NORMAL_CLOSE);
5023 return status;
5026 trigger_write_time_update_immediate(new_fsp);
5027 close_file(new_fsp,NORMAL_CLOSE);
5028 return NT_STATUS_OK;
5031 /****************************************************************************
5032 Deal with SMB_INFO_SET_EA.
5033 ****************************************************************************/
5035 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5036 const char *pdata,
5037 int total_data,
5038 files_struct *fsp,
5039 const char *fname)
5041 struct ea_list *ea_list = NULL;
5042 TALLOC_CTX *ctx = NULL;
5043 NTSTATUS status = NT_STATUS_OK;
5045 if (total_data < 10) {
5047 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5048 length. They seem to have no effect. Bug #3212. JRA */
5050 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5051 /* We're done. We only get EA info in this call. */
5052 return NT_STATUS_OK;
5055 return NT_STATUS_INVALID_PARAMETER;
5058 if (IVAL(pdata,0) > total_data) {
5059 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5060 IVAL(pdata,0), (unsigned int)total_data));
5061 return NT_STATUS_INVALID_PARAMETER;
5064 ctx = talloc_tos();
5065 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5066 if (!ea_list) {
5067 return NT_STATUS_INVALID_PARAMETER;
5069 status = set_ea(conn, fsp, fname, ea_list);
5071 return status;
5074 /****************************************************************************
5075 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5076 ****************************************************************************/
5078 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5079 const char *pdata,
5080 int total_data,
5081 files_struct *fsp,
5082 const char *fname,
5083 SMB_STRUCT_STAT *psbuf)
5085 NTSTATUS status = NT_STATUS_OK;
5086 bool delete_on_close;
5087 uint32 dosmode = 0;
5089 if (total_data < 1) {
5090 return NT_STATUS_INVALID_PARAMETER;
5093 if (fsp == NULL) {
5094 return NT_STATUS_INVALID_HANDLE;
5097 delete_on_close = (CVAL(pdata,0) ? True : False);
5098 dosmode = dos_mode(conn, fname, psbuf);
5100 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5101 "delete_on_close = %u\n",
5102 fsp->fsp_name,
5103 (unsigned int)dosmode,
5104 (unsigned int)delete_on_close ));
5106 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 return status;
5112 /* The set is across all open files on this dev/inode pair. */
5113 if (!set_delete_on_close(fsp, delete_on_close,
5114 &conn->server_info->utok)) {
5115 return NT_STATUS_ACCESS_DENIED;
5117 return NT_STATUS_OK;
5120 /****************************************************************************
5121 Deal with SMB_FILE_POSITION_INFORMATION.
5122 ****************************************************************************/
5124 static NTSTATUS smb_file_position_information(connection_struct *conn,
5125 const char *pdata,
5126 int total_data,
5127 files_struct *fsp)
5129 SMB_BIG_UINT position_information;
5131 if (total_data < 8) {
5132 return NT_STATUS_INVALID_PARAMETER;
5135 if (fsp == NULL) {
5136 /* Ignore on pathname based set. */
5137 return NT_STATUS_OK;
5140 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5141 #ifdef LARGE_SMB_OFF_T
5142 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5143 #else /* LARGE_SMB_OFF_T */
5144 if (IVAL(pdata,4) != 0) {
5145 /* more than 32 bits? */
5146 return NT_STATUS_INVALID_PARAMETER;
5148 #endif /* LARGE_SMB_OFF_T */
5150 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5151 fsp->fsp_name, (double)position_information ));
5152 fsp->fh->position_information = position_information;
5153 return NT_STATUS_OK;
5156 /****************************************************************************
5157 Deal with SMB_FILE_MODE_INFORMATION.
5158 ****************************************************************************/
5160 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5161 const char *pdata,
5162 int total_data)
5164 uint32 mode;
5166 if (total_data < 4) {
5167 return NT_STATUS_INVALID_PARAMETER;
5169 mode = IVAL(pdata,0);
5170 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5171 return NT_STATUS_INVALID_PARAMETER;
5173 return NT_STATUS_OK;
5176 /****************************************************************************
5177 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5178 ****************************************************************************/
5180 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5181 struct smb_request *req,
5182 const char *pdata,
5183 int total_data,
5184 const char *fname)
5186 char *link_target = NULL;
5187 const char *newname = fname;
5188 NTSTATUS status = NT_STATUS_OK;
5189 TALLOC_CTX *ctx = talloc_tos();
5191 /* Set a symbolic link. */
5192 /* Don't allow this if follow links is false. */
5194 if (total_data == 0) {
5195 return NT_STATUS_INVALID_PARAMETER;
5198 if (!lp_symlinks(SNUM(conn))) {
5199 return NT_STATUS_ACCESS_DENIED;
5202 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5203 total_data, STR_TERMINATE);
5205 if (!link_target) {
5206 return NT_STATUS_INVALID_PARAMETER;
5209 /* !widelinks forces the target path to be within the share. */
5210 /* This means we can interpret the target as a pathname. */
5211 if (!lp_widelinks(SNUM(conn))) {
5212 char *rel_name = NULL;
5213 char *last_dirp = NULL;
5215 if (*link_target == '/') {
5216 /* No absolute paths allowed. */
5217 return NT_STATUS_ACCESS_DENIED;
5219 rel_name = talloc_strdup(ctx,newname);
5220 if (!rel_name) {
5221 return NT_STATUS_NO_MEMORY;
5223 last_dirp = strrchr_m(rel_name, '/');
5224 if (last_dirp) {
5225 last_dirp[1] = '\0';
5226 } else {
5227 rel_name = talloc_strdup(ctx,"./");
5228 if (!rel_name) {
5229 return NT_STATUS_NO_MEMORY;
5232 rel_name = talloc_asprintf_append(rel_name,
5233 "%s",
5234 link_target);
5235 if (!rel_name) {
5236 return NT_STATUS_NO_MEMORY;
5239 status = check_name(conn, rel_name);
5240 if (!NT_STATUS_IS_OK(status)) {
5241 return status;
5245 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5246 newname, link_target ));
5248 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5249 return map_nt_error_from_unix(errno);
5252 return NT_STATUS_OK;
5255 /****************************************************************************
5256 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5257 ****************************************************************************/
5259 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5260 struct smb_request *req,
5261 const char *pdata, int total_data,
5262 const char *fname)
5264 char *oldname = NULL;
5265 TALLOC_CTX *ctx = talloc_tos();
5266 NTSTATUS status = NT_STATUS_OK;
5268 /* Set a hard link. */
5269 if (total_data == 0) {
5270 return NT_STATUS_INVALID_PARAMETER;
5273 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5274 total_data, STR_TERMINATE, &status);
5275 if (!NT_STATUS_IS_OK(status)) {
5276 return status;
5279 status = resolve_dfspath(ctx, conn,
5280 req->flags2 & FLAGS2_DFS_PATHNAMES,
5281 oldname,
5282 &oldname);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 return status;
5287 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5288 fname, oldname));
5290 return hardlink_internals(ctx, conn, oldname, fname);
5293 /****************************************************************************
5294 Deal with SMB_FILE_RENAME_INFORMATION.
5295 ****************************************************************************/
5297 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5298 struct smb_request *req,
5299 const char *pdata,
5300 int total_data,
5301 files_struct *fsp,
5302 const char *fname)
5304 bool overwrite;
5305 uint32 root_fid;
5306 uint32 len;
5307 char *newname = NULL;
5308 char *base_name = NULL;
5309 bool dest_has_wcard = False;
5310 NTSTATUS status = NT_STATUS_OK;
5311 char *p;
5312 TALLOC_CTX *ctx = talloc_tos();
5314 if (total_data < 13) {
5315 return NT_STATUS_INVALID_PARAMETER;
5318 overwrite = (CVAL(pdata,0) ? True : False);
5319 root_fid = IVAL(pdata,4);
5320 len = IVAL(pdata,8);
5322 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5323 return NT_STATUS_INVALID_PARAMETER;
5326 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5327 len, 0, &status,
5328 &dest_has_wcard);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 return status;
5333 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5334 newname));
5336 status = resolve_dfspath_wcard(ctx, conn,
5337 req->flags2 & FLAGS2_DFS_PATHNAMES,
5338 newname,
5339 &newname,
5340 &dest_has_wcard);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 return status;
5345 /* Check the new name has no '/' characters. */
5346 if (strchr_m(newname, '/')) {
5347 return NT_STATUS_NOT_SUPPORTED;
5350 if (fsp && fsp->base_fsp) {
5351 if (newname[0] != ':') {
5352 return NT_STATUS_NOT_SUPPORTED;
5354 base_name = talloc_asprintf(ctx, "%s%s",
5355 fsp->base_fsp->fsp_name,
5356 newname);
5357 if (!base_name) {
5358 return NT_STATUS_NO_MEMORY;
5360 } else {
5361 if (is_ntfs_stream_name(newname)) {
5362 return NT_STATUS_NOT_SUPPORTED;
5365 /* Create the base directory. */
5366 base_name = talloc_strdup(ctx, fname);
5367 if (!base_name) {
5368 return NT_STATUS_NO_MEMORY;
5370 p = strrchr_m(base_name, '/');
5371 if (p) {
5372 p[1] = '\0';
5373 } else {
5374 base_name = talloc_strdup(ctx, "./");
5375 if (!base_name) {
5376 return NT_STATUS_NO_MEMORY;
5379 /* Append the new name. */
5380 base_name = talloc_asprintf_append(base_name,
5381 "%s",
5382 newname);
5383 if (!base_name) {
5384 return NT_STATUS_NO_MEMORY;
5388 if (fsp) {
5389 SMB_STRUCT_STAT sbuf;
5390 char *newname_last_component = NULL;
5392 ZERO_STRUCT(sbuf);
5394 status = unix_convert(ctx, conn, newname, False,
5395 &newname,
5396 &newname_last_component,
5397 &sbuf);
5399 /* If an error we expect this to be
5400 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5402 if (!NT_STATUS_IS_OK(status)
5403 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5404 status)) {
5405 return status;
5408 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5409 fsp->fnum, fsp->fsp_name, base_name ));
5410 status = rename_internals_fsp(conn, fsp, base_name,
5411 newname_last_component, 0,
5412 overwrite);
5413 } else {
5414 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5415 fname, base_name ));
5416 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5417 overwrite, False, dest_has_wcard,
5418 FILE_WRITE_ATTRIBUTES);
5421 return status;
5424 /****************************************************************************
5425 Deal with SMB_SET_POSIX_ACL.
5426 ****************************************************************************/
5428 #if defined(HAVE_POSIX_ACLS)
5429 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5430 const char *pdata,
5431 int total_data,
5432 files_struct *fsp,
5433 const char *fname,
5434 SMB_STRUCT_STAT *psbuf)
5436 uint16 posix_acl_version;
5437 uint16 num_file_acls;
5438 uint16 num_def_acls;
5439 bool valid_file_acls = True;
5440 bool valid_def_acls = True;
5442 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5443 return NT_STATUS_INVALID_PARAMETER;
5445 posix_acl_version = SVAL(pdata,0);
5446 num_file_acls = SVAL(pdata,2);
5447 num_def_acls = SVAL(pdata,4);
5449 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5450 valid_file_acls = False;
5451 num_file_acls = 0;
5454 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5455 valid_def_acls = False;
5456 num_def_acls = 0;
5459 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5460 return NT_STATUS_INVALID_PARAMETER;
5463 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5464 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5465 return NT_STATUS_INVALID_PARAMETER;
5468 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5469 fname ? fname : fsp->fsp_name,
5470 (unsigned int)num_file_acls,
5471 (unsigned int)num_def_acls));
5473 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5474 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5475 return map_nt_error_from_unix(errno);
5478 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5479 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5480 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5481 return map_nt_error_from_unix(errno);
5483 return NT_STATUS_OK;
5485 #endif
5487 /****************************************************************************
5488 Deal with SMB_SET_POSIX_LOCK.
5489 ****************************************************************************/
5491 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5492 const struct smb_request *req,
5493 const char *pdata,
5494 int total_data,
5495 files_struct *fsp)
5497 SMB_BIG_UINT count;
5498 SMB_BIG_UINT offset;
5499 uint32 lock_pid;
5500 bool blocking_lock = False;
5501 enum brl_type lock_type;
5503 NTSTATUS status = NT_STATUS_OK;
5505 if (fsp == NULL || fsp->fh->fd == -1) {
5506 return NT_STATUS_INVALID_HANDLE;
5509 if (total_data != POSIX_LOCK_DATA_SIZE) {
5510 return NT_STATUS_INVALID_PARAMETER;
5513 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5514 case POSIX_LOCK_TYPE_READ:
5515 lock_type = READ_LOCK;
5516 break;
5517 case POSIX_LOCK_TYPE_WRITE:
5518 /* Return the right POSIX-mappable error code for files opened read-only. */
5519 if (!fsp->can_write) {
5520 return NT_STATUS_INVALID_HANDLE;
5522 lock_type = WRITE_LOCK;
5523 break;
5524 case POSIX_LOCK_TYPE_UNLOCK:
5525 lock_type = UNLOCK_LOCK;
5526 break;
5527 default:
5528 return NT_STATUS_INVALID_PARAMETER;
5531 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5532 blocking_lock = False;
5533 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5534 blocking_lock = True;
5535 } else {
5536 return NT_STATUS_INVALID_PARAMETER;
5539 if (!lp_blocking_locks(SNUM(conn))) {
5540 blocking_lock = False;
5543 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5544 #if defined(HAVE_LONGLONG)
5545 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5546 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5547 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5548 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5549 #else /* HAVE_LONGLONG */
5550 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5551 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5552 #endif /* HAVE_LONGLONG */
5554 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5555 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5556 fsp->fsp_name,
5557 (unsigned int)lock_type,
5558 (unsigned int)lock_pid,
5559 (double)count,
5560 (double)offset ));
5562 if (lock_type == UNLOCK_LOCK) {
5563 status = do_unlock(smbd_messaging_context(),
5564 fsp,
5565 lock_pid,
5566 count,
5567 offset,
5568 POSIX_LOCK);
5569 } else {
5570 uint32 block_smbpid;
5572 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5573 fsp,
5574 lock_pid,
5575 count,
5576 offset,
5577 lock_type,
5578 POSIX_LOCK,
5579 blocking_lock,
5580 &status,
5581 &block_smbpid);
5583 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5585 * A blocking lock was requested. Package up
5586 * this smb into a queued request and push it
5587 * onto the blocking lock queue.
5589 if(push_blocking_lock_request(br_lck,
5590 req,
5591 fsp,
5592 -1, /* infinite timeout. */
5594 lock_pid,
5595 lock_type,
5596 POSIX_LOCK,
5597 offset,
5598 count,
5599 block_smbpid)) {
5600 TALLOC_FREE(br_lck);
5601 return status;
5604 TALLOC_FREE(br_lck);
5607 return status;
5610 /****************************************************************************
5611 Deal with SMB_INFO_STANDARD.
5612 ****************************************************************************/
5614 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5615 const char *pdata,
5616 int total_data,
5617 files_struct *fsp,
5618 const char *fname,
5619 const SMB_STRUCT_STAT *psbuf)
5621 struct timespec ts[2];
5623 if (total_data < 12) {
5624 return NT_STATUS_INVALID_PARAMETER;
5627 /* access time */
5628 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5629 /* write time */
5630 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5632 DEBUG(10,("smb_set_info_standard: file %s\n",
5633 fname ? fname : fsp->fsp_name ));
5635 return smb_set_file_time(conn,
5636 fsp,
5637 fname,
5638 psbuf,
5640 true);
5643 /****************************************************************************
5644 Deal with SMB_SET_FILE_BASIC_INFO.
5645 ****************************************************************************/
5647 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5648 const char *pdata,
5649 int total_data,
5650 files_struct *fsp,
5651 const char *fname,
5652 SMB_STRUCT_STAT *psbuf)
5654 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5655 struct timespec write_time;
5656 struct timespec changed_time;
5657 uint32 dosmode = 0;
5658 struct timespec ts[2];
5659 NTSTATUS status = NT_STATUS_OK;
5660 bool setting_write_time = true;
5662 if (total_data < 36) {
5663 return NT_STATUS_INVALID_PARAMETER;
5666 /* Set the attributes */
5667 dosmode = IVAL(pdata,32);
5668 status = smb_set_file_dosmode(conn,
5669 fname,
5670 psbuf,
5671 dosmode);
5672 if (!NT_STATUS_IS_OK(status)) {
5673 return status;
5676 /* Ignore create time at offset pdata. */
5678 /* access time */
5679 ts[0] = interpret_long_date(pdata+8);
5681 write_time = interpret_long_date(pdata+16);
5682 changed_time = interpret_long_date(pdata+24);
5684 /* mtime */
5685 ts[1] = timespec_min(&write_time, &changed_time);
5687 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5688 ts[1] = write_time;
5691 /* Prefer a defined time to an undefined one. */
5692 if (null_timespec(ts[1])) {
5693 if (null_timespec(write_time)) {
5694 ts[1] = changed_time;
5695 setting_write_time = false;
5696 } else {
5697 ts[1] = write_time;
5701 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5702 fname ? fname : fsp->fsp_name ));
5704 return smb_set_file_time(conn,
5705 fsp,
5706 fname,
5707 psbuf,
5709 setting_write_time);
5712 /****************************************************************************
5713 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5714 ****************************************************************************/
5716 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5717 struct smb_request *req,
5718 const char *pdata,
5719 int total_data,
5720 files_struct *fsp,
5721 const char *fname,
5722 SMB_STRUCT_STAT *psbuf)
5724 SMB_BIG_UINT allocation_size = 0;
5725 NTSTATUS status = NT_STATUS_OK;
5726 files_struct *new_fsp = NULL;
5728 if (!VALID_STAT(*psbuf)) {
5729 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5732 if (total_data < 8) {
5733 return NT_STATUS_INVALID_PARAMETER;
5736 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5737 #ifdef LARGE_SMB_OFF_T
5738 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5739 #else /* LARGE_SMB_OFF_T */
5740 if (IVAL(pdata,4) != 0) {
5741 /* more than 32 bits? */
5742 return NT_STATUS_INVALID_PARAMETER;
5744 #endif /* LARGE_SMB_OFF_T */
5746 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5747 fname, (double)allocation_size ));
5749 if (allocation_size) {
5750 allocation_size = smb_roundup(conn, allocation_size);
5753 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5754 fname, (double)allocation_size ));
5756 if (fsp && fsp->fh->fd != -1) {
5757 /* Open file handle. */
5758 /* Only change if needed. */
5759 if (allocation_size != get_file_size(*psbuf)) {
5760 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5761 return map_nt_error_from_unix(errno);
5764 /* But always update the time. */
5766 * This is equivalent to a write. Ensure it's seen immediately
5767 * if there are no pending writes.
5769 trigger_write_time_update_immediate(fsp);
5770 return NT_STATUS_OK;
5773 /* Pathname or stat or directory file. */
5775 status = open_file_ntcreate(conn, req, fname, psbuf,
5776 FILE_WRITE_DATA,
5777 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5778 FILE_OPEN,
5780 FILE_ATTRIBUTE_NORMAL,
5781 FORCE_OPLOCK_BREAK_TO_NONE,
5782 NULL, &new_fsp);
5784 if (!NT_STATUS_IS_OK(status)) {
5785 /* NB. We check for open_was_deferred in the caller. */
5786 return status;
5789 /* Only change if needed. */
5790 if (allocation_size != get_file_size(*psbuf)) {
5791 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5792 status = map_nt_error_from_unix(errno);
5793 close_file(new_fsp,NORMAL_CLOSE);
5794 return status;
5798 /* Changing the allocation size should set the last mod time. */
5800 * This is equivalent to a write. Ensure it's seen immediately
5801 * if there are no pending writes.
5803 trigger_write_time_update_immediate(new_fsp);
5805 close_file(new_fsp,NORMAL_CLOSE);
5806 return NT_STATUS_OK;
5809 /****************************************************************************
5810 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5811 ****************************************************************************/
5813 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5814 struct smb_request *req,
5815 const char *pdata,
5816 int total_data,
5817 files_struct *fsp,
5818 const char *fname,
5819 SMB_STRUCT_STAT *psbuf)
5821 SMB_OFF_T size;
5823 if (total_data < 8) {
5824 return NT_STATUS_INVALID_PARAMETER;
5827 size = IVAL(pdata,0);
5828 #ifdef LARGE_SMB_OFF_T
5829 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5830 #else /* LARGE_SMB_OFF_T */
5831 if (IVAL(pdata,4) != 0) {
5832 /* more than 32 bits? */
5833 return NT_STATUS_INVALID_PARAMETER;
5835 #endif /* LARGE_SMB_OFF_T */
5836 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5837 "file %s to %.0f\n", fname, (double)size ));
5839 return smb_set_file_size(conn, req,
5840 fsp,
5841 fname,
5842 psbuf,
5843 size);
5846 /****************************************************************************
5847 Allow a UNIX info mknod.
5848 ****************************************************************************/
5850 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5851 const char *pdata,
5852 int total_data,
5853 const char *fname,
5854 SMB_STRUCT_STAT *psbuf)
5856 uint32 file_type = IVAL(pdata,56);
5857 #if defined(HAVE_MAKEDEV)
5858 uint32 dev_major = IVAL(pdata,60);
5859 uint32 dev_minor = IVAL(pdata,68);
5860 #endif
5861 SMB_DEV_T dev = (SMB_DEV_T)0;
5862 uint32 raw_unixmode = IVAL(pdata,84);
5863 NTSTATUS status;
5864 mode_t unixmode;
5866 if (total_data < 100) {
5867 return NT_STATUS_INVALID_PARAMETER;
5870 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5871 if (!NT_STATUS_IS_OK(status)) {
5872 return status;
5875 #if defined(HAVE_MAKEDEV)
5876 dev = makedev(dev_major, dev_minor);
5877 #endif
5879 switch (file_type) {
5880 #if defined(S_IFIFO)
5881 case UNIX_TYPE_FIFO:
5882 unixmode |= S_IFIFO;
5883 break;
5884 #endif
5885 #if defined(S_IFSOCK)
5886 case UNIX_TYPE_SOCKET:
5887 unixmode |= S_IFSOCK;
5888 break;
5889 #endif
5890 #if defined(S_IFCHR)
5891 case UNIX_TYPE_CHARDEV:
5892 unixmode |= S_IFCHR;
5893 break;
5894 #endif
5895 #if defined(S_IFBLK)
5896 case UNIX_TYPE_BLKDEV:
5897 unixmode |= S_IFBLK;
5898 break;
5899 #endif
5900 default:
5901 return NT_STATUS_INVALID_PARAMETER;
5904 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5905 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5907 /* Ok - do the mknod. */
5908 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5909 return map_nt_error_from_unix(errno);
5912 /* If any of the other "set" calls fail we
5913 * don't want to end up with a half-constructed mknod.
5916 if (lp_inherit_perms(SNUM(conn))) {
5917 inherit_access_posix_acl(
5918 conn, parent_dirname(fname),
5919 fname, unixmode);
5922 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5923 status = map_nt_error_from_unix(errno);
5924 SMB_VFS_UNLINK(conn,fname);
5925 return status;
5927 return NT_STATUS_OK;
5930 /****************************************************************************
5931 Deal with SMB_SET_FILE_UNIX_BASIC.
5932 ****************************************************************************/
5934 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5935 struct smb_request *req,
5936 const char *pdata,
5937 int total_data,
5938 files_struct *fsp,
5939 const char *fname,
5940 SMB_STRUCT_STAT *psbuf)
5942 struct timespec ts[2];
5943 uint32 raw_unixmode;
5944 mode_t unixmode;
5945 SMB_OFF_T size = 0;
5946 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5947 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5948 NTSTATUS status = NT_STATUS_OK;
5949 bool delete_on_fail = False;
5950 enum perm_type ptype;
5952 if (total_data < 100) {
5953 return NT_STATUS_INVALID_PARAMETER;
5956 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5957 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5958 size=IVAL(pdata,0); /* first 8 Bytes are size */
5959 #ifdef LARGE_SMB_OFF_T
5960 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5961 #else /* LARGE_SMB_OFF_T */
5962 if (IVAL(pdata,4) != 0) {
5963 /* more than 32 bits? */
5964 return NT_STATUS_INVALID_PARAMETER;
5966 #endif /* LARGE_SMB_OFF_T */
5969 ts[0] = interpret_long_date(pdata+24); /* access_time */
5970 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5971 set_owner = (uid_t)IVAL(pdata,40);
5972 set_grp = (gid_t)IVAL(pdata,48);
5973 raw_unixmode = IVAL(pdata,84);
5975 if (VALID_STAT(*psbuf)) {
5976 if (S_ISDIR(psbuf->st_mode)) {
5977 ptype = PERM_EXISTING_DIR;
5978 } else {
5979 ptype = PERM_EXISTING_FILE;
5981 } else {
5982 ptype = PERM_NEW_FILE;
5985 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 return status;
5990 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5991 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5992 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5994 if (!VALID_STAT(*psbuf)) {
5996 * The only valid use of this is to create character and block
5997 * devices, and named pipes. This is deprecated (IMHO) and
5998 * a new info level should be used for mknod. JRA.
6001 status = smb_unix_mknod(conn,
6002 pdata,
6003 total_data,
6004 fname,
6005 psbuf);
6006 if (!NT_STATUS_IS_OK(status)) {
6007 return status;
6010 /* Ensure we don't try and change anything else. */
6011 raw_unixmode = SMB_MODE_NO_CHANGE;
6012 size = get_file_size(*psbuf);
6013 ts[0] = get_atimespec(psbuf);
6014 ts[1] = get_mtimespec(psbuf);
6016 * We continue here as we might want to change the
6017 * owner uid/gid.
6019 delete_on_fail = True;
6022 #if 1
6023 /* Horrible backwards compatibility hack as an old server bug
6024 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6025 * */
6027 if (!size) {
6028 size = get_file_size(*psbuf);
6030 #endif
6033 * Deal with the UNIX specific mode set.
6036 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6037 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6038 (unsigned int)unixmode, fname ));
6039 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6040 return map_nt_error_from_unix(errno);
6045 * Deal with the UNIX specific uid set.
6048 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6049 int ret;
6051 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6052 (unsigned int)set_owner, fname ));
6054 if (S_ISLNK(psbuf->st_mode)) {
6055 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6056 } else {
6057 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6060 if (ret != 0) {
6061 status = map_nt_error_from_unix(errno);
6062 if (delete_on_fail) {
6063 SMB_VFS_UNLINK(conn,fname);
6065 return status;
6070 * Deal with the UNIX specific gid set.
6073 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6074 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6075 (unsigned int)set_owner, fname ));
6076 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6077 status = map_nt_error_from_unix(errno);
6078 if (delete_on_fail) {
6079 SMB_VFS_UNLINK(conn,fname);
6081 return status;
6085 /* Deal with any size changes. */
6087 status = smb_set_file_size(conn, req,
6088 fsp,
6089 fname,
6090 psbuf,
6091 size);
6092 if (!NT_STATUS_IS_OK(status)) {
6093 return status;
6096 /* Deal with any time changes. */
6098 return smb_set_file_time(conn,
6099 fsp,
6100 fname,
6101 psbuf,
6103 true);
6106 /****************************************************************************
6107 Deal with SMB_SET_FILE_UNIX_INFO2.
6108 ****************************************************************************/
6110 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6111 struct smb_request *req,
6112 const char *pdata,
6113 int total_data,
6114 files_struct *fsp,
6115 const char *fname,
6116 SMB_STRUCT_STAT *psbuf)
6118 NTSTATUS status;
6119 uint32 smb_fflags;
6120 uint32 smb_fmask;
6122 if (total_data < 116) {
6123 return NT_STATUS_INVALID_PARAMETER;
6126 /* Start by setting all the fields that are common between UNIX_BASIC
6127 * and UNIX_INFO2.
6129 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6130 fsp, fname, psbuf);
6131 if (!NT_STATUS_IS_OK(status)) {
6132 return status;
6135 smb_fflags = IVAL(pdata, 108);
6136 smb_fmask = IVAL(pdata, 112);
6138 /* NB: We should only attempt to alter the file flags if the client
6139 * sends a non-zero mask.
6141 if (smb_fmask != 0) {
6142 int stat_fflags = 0;
6144 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6145 &stat_fflags)) {
6146 /* Client asked to alter a flag we don't understand. */
6147 return NT_STATUS_INVALID_PARAMETER;
6150 if (fsp && fsp->fh->fd != -1) {
6151 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6152 return NT_STATUS_NOT_SUPPORTED;
6153 } else {
6154 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6155 return map_nt_error_from_unix(errno);
6160 /* XXX: need to add support for changing the create_time here. You
6161 * can do this for paths on Darwin with setattrlist(2). The right way
6162 * to hook this up is probably by extending the VFS utimes interface.
6165 return NT_STATUS_OK;
6168 /****************************************************************************
6169 Create a directory with POSIX semantics.
6170 ****************************************************************************/
6172 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6173 struct smb_request *req,
6174 char **ppdata,
6175 int total_data,
6176 const char *fname,
6177 SMB_STRUCT_STAT *psbuf,
6178 int *pdata_return_size)
6180 NTSTATUS status = NT_STATUS_OK;
6181 uint32 raw_unixmode = 0;
6182 uint32 mod_unixmode = 0;
6183 mode_t unixmode = (mode_t)0;
6184 files_struct *fsp = NULL;
6185 uint16 info_level_return = 0;
6186 int info;
6187 char *pdata = *ppdata;
6189 if (total_data < 18) {
6190 return NT_STATUS_INVALID_PARAMETER;
6193 raw_unixmode = IVAL(pdata,8);
6194 /* Next 4 bytes are not yet defined. */
6196 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 return status;
6201 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6203 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6204 fname, (unsigned int)unixmode ));
6206 status = open_directory(conn, req,
6207 fname,
6208 psbuf,
6209 FILE_READ_ATTRIBUTES, /* Just a stat open */
6210 FILE_SHARE_NONE, /* Ignored for stat opens */
6211 FILE_CREATE,
6213 mod_unixmode,
6214 &info,
6215 &fsp);
6217 if (NT_STATUS_IS_OK(status)) {
6218 close_file(fsp, NORMAL_CLOSE);
6221 info_level_return = SVAL(pdata,16);
6223 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6224 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6225 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6226 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6227 } else {
6228 *pdata_return_size = 12;
6231 /* Realloc the data size */
6232 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6233 if (*ppdata == NULL) {
6234 *pdata_return_size = 0;
6235 return NT_STATUS_NO_MEMORY;
6237 pdata = *ppdata;
6239 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6240 SSVAL(pdata,2,0); /* No fnum. */
6241 SIVAL(pdata,4,info); /* Was directory created. */
6243 switch (info_level_return) {
6244 case SMB_QUERY_FILE_UNIX_BASIC:
6245 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6246 SSVAL(pdata,10,0); /* Padding. */
6247 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6248 break;
6249 case SMB_QUERY_FILE_UNIX_INFO2:
6250 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6251 SSVAL(pdata,10,0); /* Padding. */
6252 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6253 break;
6254 default:
6255 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6256 SSVAL(pdata,10,0); /* Padding. */
6257 break;
6260 return status;
6263 /****************************************************************************
6264 Open/Create a file with POSIX semantics.
6265 ****************************************************************************/
6267 static NTSTATUS smb_posix_open(connection_struct *conn,
6268 struct smb_request *req,
6269 char **ppdata,
6270 int total_data,
6271 const char *fname,
6272 SMB_STRUCT_STAT *psbuf,
6273 int *pdata_return_size)
6275 bool extended_oplock_granted = False;
6276 char *pdata = *ppdata;
6277 uint32 flags = 0;
6278 uint32 wire_open_mode = 0;
6279 uint32 raw_unixmode = 0;
6280 uint32 mod_unixmode = 0;
6281 uint32 create_disp = 0;
6282 uint32 access_mask = 0;
6283 uint32 create_options = 0;
6284 NTSTATUS status = NT_STATUS_OK;
6285 mode_t unixmode = (mode_t)0;
6286 files_struct *fsp = NULL;
6287 int oplock_request = 0;
6288 int info = 0;
6289 uint16 info_level_return = 0;
6291 if (total_data < 18) {
6292 return NT_STATUS_INVALID_PARAMETER;
6295 flags = IVAL(pdata,0);
6296 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6297 if (oplock_request) {
6298 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6301 wire_open_mode = IVAL(pdata,4);
6303 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6304 return smb_posix_mkdir(conn, req,
6305 ppdata,
6306 total_data,
6307 fname,
6308 psbuf,
6309 pdata_return_size);
6312 switch (wire_open_mode & SMB_ACCMODE) {
6313 case SMB_O_RDONLY:
6314 access_mask = FILE_READ_DATA;
6315 break;
6316 case SMB_O_WRONLY:
6317 access_mask = FILE_WRITE_DATA;
6318 break;
6319 case SMB_O_RDWR:
6320 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6321 break;
6322 default:
6323 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6324 (unsigned int)wire_open_mode ));
6325 return NT_STATUS_INVALID_PARAMETER;
6328 wire_open_mode &= ~SMB_ACCMODE;
6330 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6331 create_disp = FILE_CREATE;
6332 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6333 create_disp = FILE_OVERWRITE_IF;
6334 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6335 create_disp = FILE_OPEN_IF;
6336 } else {
6337 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6338 (unsigned int)wire_open_mode ));
6339 return NT_STATUS_INVALID_PARAMETER;
6342 raw_unixmode = IVAL(pdata,8);
6343 /* Next 4 bytes are not yet defined. */
6345 status = unix_perms_from_wire(conn,
6346 psbuf,
6347 raw_unixmode,
6348 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6349 &unixmode);
6351 if (!NT_STATUS_IS_OK(status)) {
6352 return status;
6355 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6357 if (wire_open_mode & SMB_O_SYNC) {
6358 create_options |= FILE_WRITE_THROUGH;
6360 if (wire_open_mode & SMB_O_APPEND) {
6361 access_mask |= FILE_APPEND_DATA;
6363 if (wire_open_mode & SMB_O_DIRECT) {
6364 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6367 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6368 fname,
6369 (unsigned int)wire_open_mode,
6370 (unsigned int)unixmode ));
6372 status = open_file_ntcreate(conn, req,
6373 fname,
6374 psbuf,
6375 access_mask,
6376 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6377 create_disp,
6378 0, /* no create options yet. */
6379 mod_unixmode,
6380 oplock_request,
6381 &info,
6382 &fsp);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 return status;
6388 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6389 extended_oplock_granted = True;
6392 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6393 extended_oplock_granted = True;
6396 info_level_return = SVAL(pdata,16);
6398 /* Allocate the correct return size. */
6400 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6401 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6402 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6403 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6404 } else {
6405 *pdata_return_size = 12;
6408 /* Realloc the data size */
6409 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6410 if (*ppdata == NULL) {
6411 close_file(fsp,ERROR_CLOSE);
6412 *pdata_return_size = 0;
6413 return NT_STATUS_NO_MEMORY;
6415 pdata = *ppdata;
6417 if (extended_oplock_granted) {
6418 if (flags & REQUEST_BATCH_OPLOCK) {
6419 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6420 } else {
6421 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6423 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6424 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6425 } else {
6426 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6429 SSVAL(pdata,2,fsp->fnum);
6430 SIVAL(pdata,4,info); /* Was file created etc. */
6432 switch (info_level_return) {
6433 case SMB_QUERY_FILE_UNIX_BASIC:
6434 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6435 SSVAL(pdata,10,0); /* padding. */
6436 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6437 break;
6438 case SMB_QUERY_FILE_UNIX_INFO2:
6439 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6440 SSVAL(pdata,10,0); /* padding. */
6441 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6442 break;
6443 default:
6444 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6445 SSVAL(pdata,10,0); /* padding. */
6446 break;
6448 return NT_STATUS_OK;
6451 /****************************************************************************
6452 Delete a file with POSIX semantics.
6453 ****************************************************************************/
6455 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6456 struct smb_request *req,
6457 const char *pdata,
6458 int total_data,
6459 const char *fname,
6460 SMB_STRUCT_STAT *psbuf)
6462 NTSTATUS status = NT_STATUS_OK;
6463 files_struct *fsp = NULL;
6464 uint16 flags = 0;
6465 char del = 1;
6466 int info = 0;
6467 int i;
6468 struct share_mode_lock *lck = NULL;
6470 if (total_data < 2) {
6471 return NT_STATUS_INVALID_PARAMETER;
6474 flags = SVAL(pdata,0);
6476 if (!VALID_STAT(*psbuf)) {
6477 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6480 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6481 !VALID_STAT_OF_DIR(*psbuf)) {
6482 return NT_STATUS_NOT_A_DIRECTORY;
6485 DEBUG(10,("smb_posix_unlink: %s %s\n",
6486 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6487 fname));
6489 if (VALID_STAT_OF_DIR(*psbuf)) {
6490 status = open_directory(conn, req,
6491 fname,
6492 psbuf,
6493 DELETE_ACCESS,
6494 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6495 FILE_OPEN,
6497 FILE_FLAG_POSIX_SEMANTICS|0777,
6498 &info,
6499 &fsp);
6500 } else {
6502 status = open_file_ntcreate(conn, req,
6503 fname,
6504 psbuf,
6505 DELETE_ACCESS,
6506 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6507 FILE_OPEN,
6509 FILE_FLAG_POSIX_SEMANTICS|0777,
6510 0, /* No oplock, but break existing ones. */
6511 &info,
6512 &fsp);
6515 if (!NT_STATUS_IS_OK(status)) {
6516 return status;
6520 * Don't lie to client. If we can't really delete due to
6521 * non-POSIX opens return SHARING_VIOLATION.
6524 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6525 NULL);
6526 if (lck == NULL) {
6527 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6528 "lock for file %s\n", fsp->fsp_name));
6529 close_file(fsp, NORMAL_CLOSE);
6530 return NT_STATUS_INVALID_PARAMETER;
6534 * See if others still have the file open. If this is the case, then
6535 * don't delete. If all opens are POSIX delete we can set the delete
6536 * on close disposition.
6538 for (i=0; i<lck->num_share_modes; i++) {
6539 struct share_mode_entry *e = &lck->share_modes[i];
6540 if (is_valid_share_mode_entry(e)) {
6541 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6542 continue;
6544 /* Fail with sharing violation. */
6545 close_file(fsp, NORMAL_CLOSE);
6546 TALLOC_FREE(lck);
6547 return NT_STATUS_SHARING_VIOLATION;
6552 * Set the delete on close.
6554 status = smb_set_file_disposition_info(conn,
6555 &del,
6557 fsp,
6558 fname,
6559 psbuf);
6561 if (!NT_STATUS_IS_OK(status)) {
6562 close_file(fsp, NORMAL_CLOSE);
6563 TALLOC_FREE(lck);
6564 return status;
6566 TALLOC_FREE(lck);
6567 return close_file(fsp, NORMAL_CLOSE);
6570 /****************************************************************************
6571 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6572 ****************************************************************************/
6574 static void call_trans2setfilepathinfo(connection_struct *conn,
6575 struct smb_request *req,
6576 unsigned int tran_call,
6577 char **pparams, int total_params,
6578 char **ppdata, int total_data,
6579 unsigned int max_data_bytes)
6581 char *params = *pparams;
6582 char *pdata = *ppdata;
6583 uint16 info_level;
6584 SMB_STRUCT_STAT sbuf;
6585 char *fname = NULL;
6586 files_struct *fsp = NULL;
6587 NTSTATUS status = NT_STATUS_OK;
6588 int data_return_size = 0;
6589 TALLOC_CTX *ctx = talloc_tos();
6591 if (!params) {
6592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6593 return;
6596 ZERO_STRUCT(sbuf);
6598 if (tran_call == TRANSACT2_SETFILEINFO) {
6599 if (total_params < 4) {
6600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6601 return;
6604 fsp = file_fsp(SVAL(params,0));
6605 /* Basic check for non-null fsp. */
6606 if (!check_fsp_open(conn, req, fsp)) {
6607 return;
6609 info_level = SVAL(params,2);
6611 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6612 if (!fname) {
6613 reply_nterror(req, NT_STATUS_NO_MEMORY);
6614 return;
6617 if(fsp->is_directory || fsp->fh->fd == -1) {
6619 * This is actually a SETFILEINFO on a directory
6620 * handle (returned from an NT SMB). NT5.0 seems
6621 * to do this call. JRA.
6623 if (INFO_LEVEL_IS_UNIX(info_level)) {
6624 /* Always do lstat for UNIX calls. */
6625 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6626 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6627 reply_unixerror(req,ERRDOS,ERRbadpath);
6628 return;
6630 } else {
6631 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6632 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6633 reply_unixerror(req,ERRDOS,ERRbadpath);
6634 return;
6637 } else if (fsp->print_file) {
6639 * Doing a DELETE_ON_CLOSE should cancel a print job.
6641 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6642 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6644 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6646 SSVAL(params,0,0);
6647 send_trans2_replies(conn, req, params, 2,
6648 *ppdata, 0,
6649 max_data_bytes);
6650 return;
6651 } else {
6652 reply_unixerror(req, ERRDOS, ERRbadpath);
6653 return;
6655 } else {
6657 * Original code - this is an open file.
6659 if (!check_fsp(conn, req, fsp)) {
6660 return;
6663 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6664 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6665 reply_unixerror(req, ERRDOS, ERRbadfid);
6666 return;
6669 } else {
6670 /* set path info */
6671 if (total_params < 7) {
6672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6673 return;
6676 info_level = SVAL(params,0);
6677 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6678 total_params - 6, STR_TERMINATE,
6679 &status);
6680 if (!NT_STATUS_IS_OK(status)) {
6681 reply_nterror(req, status);
6682 return;
6685 status = resolve_dfspath(ctx, conn,
6686 req->flags2 & FLAGS2_DFS_PATHNAMES,
6687 fname,
6688 &fname);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6691 reply_botherror(req,
6692 NT_STATUS_PATH_NOT_COVERED,
6693 ERRSRV, ERRbadpath);
6694 return;
6696 reply_nterror(req, status);
6697 return;
6700 status = unix_convert(ctx, conn, fname, False,
6701 &fname, NULL, &sbuf);
6702 if (!NT_STATUS_IS_OK(status)) {
6703 reply_nterror(req, status);
6704 return;
6707 status = check_name(conn, fname);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 reply_nterror(req, status);
6710 return;
6713 if (INFO_LEVEL_IS_UNIX(info_level)) {
6715 * For CIFS UNIX extensions the target name may not exist.
6718 /* Always do lstat for UNIX calls. */
6719 SMB_VFS_LSTAT(conn,fname,&sbuf);
6721 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6722 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6723 reply_unixerror(req, ERRDOS, ERRbadpath);
6724 return;
6728 if (!CAN_WRITE(conn)) {
6729 reply_doserror(req, ERRSRV, ERRaccess);
6730 return;
6733 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6734 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6735 return;
6738 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6739 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6741 /* Realloc the parameter size */
6742 *pparams = (char *)SMB_REALLOC(*pparams,2);
6743 if (*pparams == NULL) {
6744 reply_nterror(req, NT_STATUS_NO_MEMORY);
6745 return;
6747 params = *pparams;
6749 SSVAL(params,0,0);
6751 switch (info_level) {
6753 case SMB_INFO_STANDARD:
6755 status = smb_set_info_standard(conn,
6756 pdata,
6757 total_data,
6758 fsp,
6759 fname,
6760 &sbuf);
6761 break;
6764 case SMB_INFO_SET_EA:
6766 status = smb_info_set_ea(conn,
6767 pdata,
6768 total_data,
6769 fsp,
6770 fname);
6771 break;
6774 case SMB_SET_FILE_BASIC_INFO:
6775 case SMB_FILE_BASIC_INFORMATION:
6777 status = smb_set_file_basic_info(conn,
6778 pdata,
6779 total_data,
6780 fsp,
6781 fname,
6782 &sbuf);
6783 break;
6786 case SMB_FILE_ALLOCATION_INFORMATION:
6787 case SMB_SET_FILE_ALLOCATION_INFO:
6789 status = smb_set_file_allocation_info(conn, req,
6790 pdata,
6791 total_data,
6792 fsp,
6793 fname,
6794 &sbuf);
6795 break;
6798 case SMB_FILE_END_OF_FILE_INFORMATION:
6799 case SMB_SET_FILE_END_OF_FILE_INFO:
6801 status = smb_set_file_end_of_file_info(conn, req,
6802 pdata,
6803 total_data,
6804 fsp,
6805 fname,
6806 &sbuf);
6807 break;
6810 case SMB_FILE_DISPOSITION_INFORMATION:
6811 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6813 #if 0
6814 /* JRA - We used to just ignore this on a path ?
6815 * Shouldn't this be invalid level on a pathname
6816 * based call ?
6818 if (tran_call != TRANSACT2_SETFILEINFO) {
6819 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6821 #endif
6822 status = smb_set_file_disposition_info(conn,
6823 pdata,
6824 total_data,
6825 fsp,
6826 fname,
6827 &sbuf);
6828 break;
6831 case SMB_FILE_POSITION_INFORMATION:
6833 status = smb_file_position_information(conn,
6834 pdata,
6835 total_data,
6836 fsp);
6837 break;
6840 /* From tridge Samba4 :
6841 * MODE_INFORMATION in setfileinfo (I have no
6842 * idea what "mode information" on a file is - it takes a value of 0,
6843 * 2, 4 or 6. What could it be?).
6846 case SMB_FILE_MODE_INFORMATION:
6848 status = smb_file_mode_information(conn,
6849 pdata,
6850 total_data);
6851 break;
6855 * CIFS UNIX extensions.
6858 case SMB_SET_FILE_UNIX_BASIC:
6860 status = smb_set_file_unix_basic(conn, req,
6861 pdata,
6862 total_data,
6863 fsp,
6864 fname,
6865 &sbuf);
6866 break;
6869 case SMB_SET_FILE_UNIX_INFO2:
6871 status = smb_set_file_unix_info2(conn, req,
6872 pdata,
6873 total_data,
6874 fsp,
6875 fname,
6876 &sbuf);
6877 break;
6880 case SMB_SET_FILE_UNIX_LINK:
6882 if (tran_call != TRANSACT2_SETPATHINFO) {
6883 /* We must have a pathname for this. */
6884 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6885 return;
6887 status = smb_set_file_unix_link(conn, req, pdata,
6888 total_data, fname);
6889 break;
6892 case SMB_SET_FILE_UNIX_HLINK:
6894 if (tran_call != TRANSACT2_SETPATHINFO) {
6895 /* We must have a pathname for this. */
6896 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6897 return;
6899 status = smb_set_file_unix_hlink(conn, req,
6900 pdata, total_data,
6901 fname);
6902 break;
6905 case SMB_FILE_RENAME_INFORMATION:
6907 status = smb_file_rename_information(conn, req,
6908 pdata, total_data,
6909 fsp, fname);
6910 break;
6913 #if defined(HAVE_POSIX_ACLS)
6914 case SMB_SET_POSIX_ACL:
6916 status = smb_set_posix_acl(conn,
6917 pdata,
6918 total_data,
6919 fsp,
6920 fname,
6921 &sbuf);
6922 break;
6924 #endif
6926 case SMB_SET_POSIX_LOCK:
6928 if (tran_call != TRANSACT2_SETFILEINFO) {
6929 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6930 return;
6932 status = smb_set_posix_lock(conn, req,
6933 pdata, total_data, fsp);
6934 break;
6937 case SMB_POSIX_PATH_OPEN:
6939 if (tran_call != TRANSACT2_SETPATHINFO) {
6940 /* We must have a pathname for this. */
6941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6942 return;
6945 status = smb_posix_open(conn, req,
6946 ppdata,
6947 total_data,
6948 fname,
6949 &sbuf,
6950 &data_return_size);
6951 break;
6954 case SMB_POSIX_PATH_UNLINK:
6956 if (tran_call != TRANSACT2_SETPATHINFO) {
6957 /* We must have a pathname for this. */
6958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6959 return;
6962 status = smb_posix_unlink(conn, req,
6963 pdata,
6964 total_data,
6965 fname,
6966 &sbuf);
6967 break;
6970 default:
6971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6972 return;
6976 if (!NT_STATUS_IS_OK(status)) {
6977 if (open_was_deferred(req->mid)) {
6978 /* We have re-scheduled this call. */
6979 return;
6981 if (blocking_lock_was_deferred(req->mid)) {
6982 /* We have re-scheduled this call. */
6983 return;
6985 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6986 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6987 ERRSRV, ERRbadpath);
6988 return;
6990 if (info_level == SMB_POSIX_PATH_OPEN) {
6991 reply_openerror(req, status);
6992 return;
6995 reply_nterror(req, status);
6996 return;
6999 SSVAL(params,0,0);
7000 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7001 max_data_bytes);
7003 return;
7006 /****************************************************************************
7007 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7008 ****************************************************************************/
7010 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7011 char **pparams, int total_params,
7012 char **ppdata, int total_data,
7013 unsigned int max_data_bytes)
7015 char *params = *pparams;
7016 char *pdata = *ppdata;
7017 char *directory = NULL;
7018 SMB_STRUCT_STAT sbuf;
7019 NTSTATUS status = NT_STATUS_OK;
7020 struct ea_list *ea_list = NULL;
7021 TALLOC_CTX *ctx = talloc_tos();
7023 if (!CAN_WRITE(conn)) {
7024 reply_doserror(req, ERRSRV, ERRaccess);
7025 return;
7028 if (total_params < 5) {
7029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7030 return;
7033 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7034 total_params - 4, STR_TERMINATE,
7035 &status);
7036 if (!NT_STATUS_IS_OK(status)) {
7037 reply_nterror(req, status);
7038 return;
7041 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7043 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7044 if (!NT_STATUS_IS_OK(status)) {
7045 reply_nterror(req, status);
7046 return;
7049 status = check_name(conn, directory);
7050 if (!NT_STATUS_IS_OK(status)) {
7051 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7052 reply_nterror(req, status);
7053 return;
7056 /* Any data in this call is an EA list. */
7057 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7058 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7059 return;
7063 * OS/2 workplace shell seems to send SET_EA requests of "null"
7064 * length (4 bytes containing IVAL 4).
7065 * They seem to have no effect. Bug #3212. JRA.
7068 if (total_data != 4) {
7069 if (total_data < 10) {
7070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7071 return;
7074 if (IVAL(pdata,0) > total_data) {
7075 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7076 IVAL(pdata,0), (unsigned int)total_data));
7077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7078 return;
7081 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7082 total_data - 4);
7083 if (!ea_list) {
7084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7085 return;
7088 /* If total_data == 4 Windows doesn't care what values
7089 * are placed in that field, it just ignores them.
7090 * The System i QNTC IBM SMB client puts bad values here,
7091 * so ignore them. */
7093 status = create_directory(conn, req, directory);
7095 if (!NT_STATUS_IS_OK(status)) {
7096 reply_nterror(req, status);
7097 return;
7100 /* Try and set any given EA. */
7101 if (ea_list) {
7102 status = set_ea(conn, NULL, directory, ea_list);
7103 if (!NT_STATUS_IS_OK(status)) {
7104 reply_nterror(req, status);
7105 return;
7109 /* Realloc the parameter and data sizes */
7110 *pparams = (char *)SMB_REALLOC(*pparams,2);
7111 if(*pparams == NULL) {
7112 reply_nterror(req, NT_STATUS_NO_MEMORY);
7113 return;
7115 params = *pparams;
7117 SSVAL(params,0,0);
7119 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7121 return;
7124 /****************************************************************************
7125 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7126 We don't actually do this - we just send a null response.
7127 ****************************************************************************/
7129 static void call_trans2findnotifyfirst(connection_struct *conn,
7130 struct smb_request *req,
7131 char **pparams, int total_params,
7132 char **ppdata, int total_data,
7133 unsigned int max_data_bytes)
7135 static uint16 fnf_handle = 257;
7136 char *params = *pparams;
7137 uint16 info_level;
7139 if (total_params < 6) {
7140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7141 return;
7144 info_level = SVAL(params,4);
7145 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7147 switch (info_level) {
7148 case 1:
7149 case 2:
7150 break;
7151 default:
7152 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7153 return;
7156 /* Realloc the parameter and data sizes */
7157 *pparams = (char *)SMB_REALLOC(*pparams,6);
7158 if (*pparams == NULL) {
7159 reply_nterror(req, NT_STATUS_NO_MEMORY);
7160 return;
7162 params = *pparams;
7164 SSVAL(params,0,fnf_handle);
7165 SSVAL(params,2,0); /* No changes */
7166 SSVAL(params,4,0); /* No EA errors */
7168 fnf_handle++;
7170 if(fnf_handle == 0)
7171 fnf_handle = 257;
7173 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7175 return;
7178 /****************************************************************************
7179 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7180 changes). Currently this does nothing.
7181 ****************************************************************************/
7183 static void call_trans2findnotifynext(connection_struct *conn,
7184 struct smb_request *req,
7185 char **pparams, int total_params,
7186 char **ppdata, int total_data,
7187 unsigned int max_data_bytes)
7189 char *params = *pparams;
7191 DEBUG(3,("call_trans2findnotifynext\n"));
7193 /* Realloc the parameter and data sizes */
7194 *pparams = (char *)SMB_REALLOC(*pparams,4);
7195 if (*pparams == NULL) {
7196 reply_nterror(req, NT_STATUS_NO_MEMORY);
7197 return;
7199 params = *pparams;
7201 SSVAL(params,0,0); /* No changes */
7202 SSVAL(params,2,0); /* No EA errors */
7204 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7206 return;
7209 /****************************************************************************
7210 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7211 ****************************************************************************/
7213 static void call_trans2getdfsreferral(connection_struct *conn,
7214 struct smb_request *req,
7215 char **pparams, int total_params,
7216 char **ppdata, int total_data,
7217 unsigned int max_data_bytes)
7219 char *params = *pparams;
7220 char *pathname = NULL;
7221 int reply_size = 0;
7222 int max_referral_level;
7223 NTSTATUS status = NT_STATUS_OK;
7224 TALLOC_CTX *ctx = talloc_tos();
7226 DEBUG(10,("call_trans2getdfsreferral\n"));
7228 if (total_params < 3) {
7229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7230 return;
7233 max_referral_level = SVAL(params,0);
7235 if(!lp_host_msdfs()) {
7236 reply_doserror(req, ERRDOS, ERRbadfunc);
7237 return;
7240 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7241 total_params - 2, STR_TERMINATE);
7242 if (!pathname) {
7243 reply_nterror(req, NT_STATUS_NOT_FOUND);
7244 return;
7246 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7247 ppdata,&status)) < 0) {
7248 reply_nterror(req, status);
7249 return;
7252 SSVAL(req->inbuf, smb_flg2,
7253 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7254 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7256 return;
7259 #define LMCAT_SPL 0x53
7260 #define LMFUNC_GETJOBID 0x60
7262 /****************************************************************************
7263 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7264 ****************************************************************************/
7266 static void call_trans2ioctl(connection_struct *conn,
7267 struct smb_request *req,
7268 char **pparams, int total_params,
7269 char **ppdata, int total_data,
7270 unsigned int max_data_bytes)
7272 char *pdata = *ppdata;
7273 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7275 /* check for an invalid fid before proceeding */
7277 if (!fsp) {
7278 reply_doserror(req, ERRDOS, ERRbadfid);
7279 return;
7282 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7283 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7284 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7285 if (*ppdata == NULL) {
7286 reply_nterror(req, NT_STATUS_NO_MEMORY);
7287 return;
7289 pdata = *ppdata;
7291 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7292 CAN ACCEPT THIS IN UNICODE. JRA. */
7294 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7295 srvstr_push(pdata, req->flags2, pdata + 2,
7296 global_myname(), 15,
7297 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7298 srvstr_push(pdata, req->flags2, pdata+18,
7299 lp_servicename(SNUM(conn)), 13,
7300 STR_ASCII|STR_TERMINATE); /* Service name */
7301 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7302 max_data_bytes);
7303 return;
7306 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7307 reply_doserror(req, ERRSRV, ERRerror);
7310 /****************************************************************************
7311 Reply to a SMBfindclose (stop trans2 directory search).
7312 ****************************************************************************/
7314 void reply_findclose(struct smb_request *req)
7316 int dptr_num;
7318 START_PROFILE(SMBfindclose);
7320 if (req->wct < 1) {
7321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7322 END_PROFILE(SMBfindclose);
7323 return;
7326 dptr_num = SVALS(req->inbuf,smb_vwv0);
7328 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7330 dptr_close(&dptr_num);
7332 reply_outbuf(req, 0, 0);
7334 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7336 END_PROFILE(SMBfindclose);
7337 return;
7340 /****************************************************************************
7341 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7342 ****************************************************************************/
7344 void reply_findnclose(struct smb_request *req)
7346 int dptr_num;
7348 START_PROFILE(SMBfindnclose);
7350 if (req->wct < 1) {
7351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7352 END_PROFILE(SMBfindnclose);
7353 return;
7356 dptr_num = SVAL(req->inbuf,smb_vwv0);
7358 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7360 /* We never give out valid handles for a
7361 findnotifyfirst - so any dptr_num is ok here.
7362 Just ignore it. */
7364 reply_outbuf(req, 0, 0);
7366 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7368 END_PROFILE(SMBfindnclose);
7369 return;
7372 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7373 struct trans_state *state)
7375 if (Protocol >= PROTOCOL_NT1) {
7376 req->flags2 |= 0x40; /* IS_LONG_NAME */
7377 SSVAL(req->inbuf,smb_flg2,req->flags2);
7380 if (conn->encrypt_level == Required && !req->encrypted) {
7381 if (state->call != TRANSACT2_QFSINFO &&
7382 state->call != TRANSACT2_SETFSINFO) {
7383 DEBUG(0,("handle_trans2: encryption required "
7384 "with call 0x%x\n",
7385 (unsigned int)state->call));
7386 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7387 return;
7391 /* Now we must call the relevant TRANS2 function */
7392 switch(state->call) {
7393 case TRANSACT2_OPEN:
7395 START_PROFILE(Trans2_open);
7396 call_trans2open(conn, req,
7397 &state->param, state->total_param,
7398 &state->data, state->total_data,
7399 state->max_data_return);
7400 END_PROFILE(Trans2_open);
7401 break;
7404 case TRANSACT2_FINDFIRST:
7406 START_PROFILE(Trans2_findfirst);
7407 call_trans2findfirst(conn, req,
7408 &state->param, state->total_param,
7409 &state->data, state->total_data,
7410 state->max_data_return);
7411 END_PROFILE(Trans2_findfirst);
7412 break;
7415 case TRANSACT2_FINDNEXT:
7417 START_PROFILE(Trans2_findnext);
7418 call_trans2findnext(conn, req,
7419 &state->param, state->total_param,
7420 &state->data, state->total_data,
7421 state->max_data_return);
7422 END_PROFILE(Trans2_findnext);
7423 break;
7426 case TRANSACT2_QFSINFO:
7428 START_PROFILE(Trans2_qfsinfo);
7429 call_trans2qfsinfo(conn, req,
7430 &state->param, state->total_param,
7431 &state->data, state->total_data,
7432 state->max_data_return);
7433 END_PROFILE(Trans2_qfsinfo);
7434 break;
7437 case TRANSACT2_SETFSINFO:
7439 START_PROFILE(Trans2_setfsinfo);
7440 call_trans2setfsinfo(conn, req,
7441 &state->param, state->total_param,
7442 &state->data, state->total_data,
7443 state->max_data_return);
7444 END_PROFILE(Trans2_setfsinfo);
7445 break;
7448 case TRANSACT2_QPATHINFO:
7449 case TRANSACT2_QFILEINFO:
7451 START_PROFILE(Trans2_qpathinfo);
7452 call_trans2qfilepathinfo(conn, req, state->call,
7453 &state->param, state->total_param,
7454 &state->data, state->total_data,
7455 state->max_data_return);
7456 END_PROFILE(Trans2_qpathinfo);
7457 break;
7460 case TRANSACT2_SETPATHINFO:
7461 case TRANSACT2_SETFILEINFO:
7463 START_PROFILE(Trans2_setpathinfo);
7464 call_trans2setfilepathinfo(conn, req, state->call,
7465 &state->param, state->total_param,
7466 &state->data, state->total_data,
7467 state->max_data_return);
7468 END_PROFILE(Trans2_setpathinfo);
7469 break;
7472 case TRANSACT2_FINDNOTIFYFIRST:
7474 START_PROFILE(Trans2_findnotifyfirst);
7475 call_trans2findnotifyfirst(conn, req,
7476 &state->param, state->total_param,
7477 &state->data, state->total_data,
7478 state->max_data_return);
7479 END_PROFILE(Trans2_findnotifyfirst);
7480 break;
7483 case TRANSACT2_FINDNOTIFYNEXT:
7485 START_PROFILE(Trans2_findnotifynext);
7486 call_trans2findnotifynext(conn, req,
7487 &state->param, state->total_param,
7488 &state->data, state->total_data,
7489 state->max_data_return);
7490 END_PROFILE(Trans2_findnotifynext);
7491 break;
7494 case TRANSACT2_MKDIR:
7496 START_PROFILE(Trans2_mkdir);
7497 call_trans2mkdir(conn, req,
7498 &state->param, state->total_param,
7499 &state->data, state->total_data,
7500 state->max_data_return);
7501 END_PROFILE(Trans2_mkdir);
7502 break;
7505 case TRANSACT2_GET_DFS_REFERRAL:
7507 START_PROFILE(Trans2_get_dfs_referral);
7508 call_trans2getdfsreferral(conn, req,
7509 &state->param, state->total_param,
7510 &state->data, state->total_data,
7511 state->max_data_return);
7512 END_PROFILE(Trans2_get_dfs_referral);
7513 break;
7516 case TRANSACT2_IOCTL:
7518 START_PROFILE(Trans2_ioctl);
7519 call_trans2ioctl(conn, req,
7520 &state->param, state->total_param,
7521 &state->data, state->total_data,
7522 state->max_data_return);
7523 END_PROFILE(Trans2_ioctl);
7524 break;
7527 default:
7528 /* Error in request */
7529 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7530 reply_doserror(req, ERRSRV,ERRerror);
7534 /****************************************************************************
7535 Reply to a SMBtrans2.
7536 ****************************************************************************/
7538 void reply_trans2(struct smb_request *req)
7540 connection_struct *conn = req->conn;
7541 unsigned int dsoff;
7542 unsigned int dscnt;
7543 unsigned int psoff;
7544 unsigned int pscnt;
7545 unsigned int tran_call;
7546 unsigned int size;
7547 unsigned int av_size;
7548 struct trans_state *state;
7549 NTSTATUS result;
7551 START_PROFILE(SMBtrans2);
7553 if (req->wct < 14) {
7554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7555 END_PROFILE(SMBtrans2);
7556 return;
7559 dsoff = SVAL(req->inbuf, smb_dsoff);
7560 dscnt = SVAL(req->inbuf, smb_dscnt);
7561 psoff = SVAL(req->inbuf, smb_psoff);
7562 pscnt = SVAL(req->inbuf, smb_pscnt);
7563 tran_call = SVAL(req->inbuf, smb_setup0);
7564 size = smb_len(req->inbuf) + 4;
7565 av_size = smb_len(req->inbuf);
7567 result = allow_new_trans(conn->pending_trans, req->mid);
7568 if (!NT_STATUS_IS_OK(result)) {
7569 DEBUG(2, ("Got invalid trans2 request: %s\n",
7570 nt_errstr(result)));
7571 reply_nterror(req, result);
7572 END_PROFILE(SMBtrans2);
7573 return;
7576 if (IS_IPC(conn)) {
7577 switch (tran_call) {
7578 /* List the allowed trans2 calls on IPC$ */
7579 case TRANSACT2_OPEN:
7580 case TRANSACT2_GET_DFS_REFERRAL:
7581 case TRANSACT2_QFILEINFO:
7582 case TRANSACT2_QFSINFO:
7583 case TRANSACT2_SETFSINFO:
7584 break;
7585 default:
7586 reply_doserror(req, ERRSRV, ERRaccess);
7587 END_PROFILE(SMBtrans2);
7588 return;
7592 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7593 DEBUG(0, ("talloc failed\n"));
7594 reply_nterror(req, NT_STATUS_NO_MEMORY);
7595 END_PROFILE(SMBtrans2);
7596 return;
7599 state->cmd = SMBtrans2;
7601 state->mid = req->mid;
7602 state->vuid = req->vuid;
7603 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7604 state->setup = NULL;
7605 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7606 state->param = NULL;
7607 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7608 state->data = NULL;
7609 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7610 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7611 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7612 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7613 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7615 state->call = tran_call;
7617 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7618 is so as a sanity check */
7619 if (state->setup_count != 1) {
7621 * Need to have rc=0 for ioctl to get job id for OS/2.
7622 * Network printing will fail if function is not successful.
7623 * Similar function in reply.c will be used if protocol
7624 * is LANMAN1.0 instead of LM1.2X002.
7625 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7626 * outbuf doesn't have to be set(only job id is used).
7628 if ( (state->setup_count == 4)
7629 && (tran_call == TRANSACT2_IOCTL)
7630 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7631 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7632 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7633 } else {
7634 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7635 DEBUG(2,("Transaction is %d\n",tran_call));
7636 TALLOC_FREE(state);
7637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7638 END_PROFILE(SMBtrans2);
7639 return;
7643 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7644 goto bad_param;
7646 if (state->total_data) {
7647 /* Can't use talloc here, the core routines do realloc on the
7648 * params and data. */
7649 state->data = (char *)SMB_MALLOC(state->total_data);
7650 if (state->data == NULL) {
7651 DEBUG(0,("reply_trans2: data malloc fail for %u "
7652 "bytes !\n", (unsigned int)state->total_data));
7653 TALLOC_FREE(state);
7654 reply_nterror(req, NT_STATUS_NO_MEMORY);
7655 END_PROFILE(SMBtrans2);
7656 return;
7659 if (dscnt > state->total_data ||
7660 dsoff+dscnt < dsoff) {
7661 goto bad_param;
7664 if (dsoff > av_size ||
7665 dscnt > av_size ||
7666 dsoff+dscnt > av_size) {
7667 goto bad_param;
7670 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7673 if (state->total_param) {
7674 /* Can't use talloc here, the core routines do realloc on the
7675 * params and data. */
7676 state->param = (char *)SMB_MALLOC(state->total_param);
7677 if (state->param == NULL) {
7678 DEBUG(0,("reply_trans: param malloc fail for %u "
7679 "bytes !\n", (unsigned int)state->total_param));
7680 SAFE_FREE(state->data);
7681 TALLOC_FREE(state);
7682 reply_nterror(req, NT_STATUS_NO_MEMORY);
7683 END_PROFILE(SMBtrans2);
7684 return;
7687 if (pscnt > state->total_param ||
7688 psoff+pscnt < psoff) {
7689 goto bad_param;
7692 if (psoff > av_size ||
7693 pscnt > av_size ||
7694 psoff+pscnt > av_size) {
7695 goto bad_param;
7698 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7701 state->received_data = dscnt;
7702 state->received_param = pscnt;
7704 if ((state->received_param == state->total_param) &&
7705 (state->received_data == state->total_data)) {
7707 handle_trans2(conn, req, state);
7709 SAFE_FREE(state->data);
7710 SAFE_FREE(state->param);
7711 TALLOC_FREE(state);
7712 END_PROFILE(SMBtrans2);
7713 return;
7716 DLIST_ADD(conn->pending_trans, state);
7718 /* We need to send an interim response then receive the rest
7719 of the parameter/data bytes */
7720 reply_outbuf(req, 0, 0);
7721 show_msg((char *)req->outbuf);
7722 END_PROFILE(SMBtrans2);
7723 return;
7725 bad_param:
7727 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7728 SAFE_FREE(state->data);
7729 SAFE_FREE(state->param);
7730 TALLOC_FREE(state);
7731 END_PROFILE(SMBtrans2);
7732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7736 /****************************************************************************
7737 Reply to a SMBtranss2
7738 ****************************************************************************/
7740 void reply_transs2(struct smb_request *req)
7742 connection_struct *conn = req->conn;
7743 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7744 struct trans_state *state;
7745 unsigned int size;
7746 unsigned int av_size;
7748 START_PROFILE(SMBtranss2);
7750 show_msg((char *)req->inbuf);
7752 if (req->wct < 8) {
7753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7754 END_PROFILE(SMBtranss2);
7755 return;
7758 size = smb_len(req->inbuf)+4;
7759 av_size = smb_len(req->inbuf);
7761 for (state = conn->pending_trans; state != NULL;
7762 state = state->next) {
7763 if (state->mid == req->mid) {
7764 break;
7768 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7770 END_PROFILE(SMBtranss2);
7771 return;
7774 /* Revise state->total_param and state->total_data in case they have
7775 changed downwards */
7777 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7778 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7779 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7780 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7782 pcnt = SVAL(req->inbuf, smb_spscnt);
7783 poff = SVAL(req->inbuf, smb_spsoff);
7784 pdisp = SVAL(req->inbuf, smb_spsdisp);
7786 dcnt = SVAL(req->inbuf, smb_sdscnt);
7787 doff = SVAL(req->inbuf, smb_sdsoff);
7788 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7790 state->received_param += pcnt;
7791 state->received_data += dcnt;
7793 if ((state->received_data > state->total_data) ||
7794 (state->received_param > state->total_param))
7795 goto bad_param;
7797 if (pcnt) {
7798 if (pdisp > state->total_param ||
7799 pcnt > state->total_param ||
7800 pdisp+pcnt > state->total_param ||
7801 pdisp+pcnt < pdisp) {
7802 goto bad_param;
7805 if (poff > av_size ||
7806 pcnt > av_size ||
7807 poff+pcnt > av_size ||
7808 poff+pcnt < poff) {
7809 goto bad_param;
7812 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7813 pcnt);
7816 if (dcnt) {
7817 if (ddisp > state->total_data ||
7818 dcnt > state->total_data ||
7819 ddisp+dcnt > state->total_data ||
7820 ddisp+dcnt < ddisp) {
7821 goto bad_param;
7824 if (doff > av_size ||
7825 dcnt > av_size ||
7826 doff+dcnt > av_size ||
7827 doff+dcnt < doff) {
7828 goto bad_param;
7831 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7832 dcnt);
7835 if ((state->received_param < state->total_param) ||
7836 (state->received_data < state->total_data)) {
7837 END_PROFILE(SMBtranss2);
7838 return;
7842 * construct_reply_common will copy smb_com from inbuf to
7843 * outbuf. SMBtranss2 is wrong here.
7845 SCVAL(req->inbuf,smb_com,SMBtrans2);
7847 handle_trans2(conn, req, state);
7849 DLIST_REMOVE(conn->pending_trans, state);
7850 SAFE_FREE(state->data);
7851 SAFE_FREE(state->param);
7852 TALLOC_FREE(state);
7854 END_PROFILE(SMBtranss2);
7855 return;
7857 bad_param:
7859 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7860 DLIST_REMOVE(conn->pending_trans, state);
7861 SAFE_FREE(state->data);
7862 SAFE_FREE(state->param);
7863 TALLOC_FREE(state);
7864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7865 END_PROFILE(SMBtranss2);
7866 return;