Revert "Fix nonempty blank lines in vfs_gpfs.c"
[Samba.git] / source3 / smbd / trans2.c
blob606e65679549ea5b6a13f40a0e35cd69e0f32db7
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 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t 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 uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
69 uint64_t ret;
71 if(S_ISDIR(sbuf->st_mode)) {
72 return 0;
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
77 #else
78 ret = (uint64_t)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);
772 * We might have SMBtrans2s in req which was transferred to
773 * the outbuf, fix that.
775 SCVAL(req->outbuf, smb_com, SMBtrans2);
777 /* Set total params and data to be sent */
778 SSVAL(req->outbuf,smb_tprcnt,paramsize);
779 SSVAL(req->outbuf,smb_tdrcnt,datasize);
781 /* Calculate how many parameters and data we can fit into
782 * this packet. Parameters get precedence
785 params_sent_thistime = MIN(params_to_send,useable_space);
786 data_sent_thistime = useable_space - params_sent_thistime;
787 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
789 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
791 /* smb_proff is the offset from the start of the SMB header to the
792 parameter bytes, however the first 4 bytes of outbuf are
793 the Netbios over TCP header. Thus use smb_base() to subtract
794 them from the calculation */
796 SSVAL(req->outbuf,smb_proff,
797 ((smb_buf(req->outbuf)+alignment_offset)
798 - smb_base(req->outbuf)));
800 if(params_sent_thistime == 0)
801 SSVAL(req->outbuf,smb_prdisp,0);
802 else
803 /* Absolute displacement of param bytes sent in this packet */
804 SSVAL(req->outbuf,smb_prdisp,pp - params);
806 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
807 if(data_sent_thistime == 0) {
808 SSVAL(req->outbuf,smb_droff,0);
809 SSVAL(req->outbuf,smb_drdisp, 0);
810 } else {
811 /* The offset of the data bytes is the offset of the
812 parameter bytes plus the number of parameters being sent this time */
813 SSVAL(req->outbuf, smb_droff,
814 ((smb_buf(req->outbuf)+alignment_offset)
815 - smb_base(req->outbuf))
816 + params_sent_thistime + data_alignment_offset);
817 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
820 /* Initialize the padding for alignment */
822 if (alignment_offset != 0) {
823 memset(smb_buf(req->outbuf), 0, alignment_offset);
826 /* Copy the param bytes into the packet */
828 if(params_sent_thistime) {
829 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
830 params_sent_thistime);
833 /* Copy in the data bytes */
834 if(data_sent_thistime) {
835 if (data_alignment_offset != 0) {
836 memset((smb_buf(req->outbuf)+alignment_offset+
837 params_sent_thistime), 0,
838 data_alignment_offset);
840 memcpy(smb_buf(req->outbuf)+alignment_offset
841 +params_sent_thistime+data_alignment_offset,
842 pd,data_sent_thistime);
845 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
846 params_sent_thistime, data_sent_thistime, useable_space));
847 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
848 params_to_send, data_to_send, paramsize, datasize));
850 if (overflow) {
851 error_packet_set((char *)req->outbuf,
852 ERRDOS,ERRbufferoverflow,
853 STATUS_BUFFER_OVERFLOW,
854 __LINE__,__FILE__);
857 /* Send the packet */
858 show_msg((char *)req->outbuf);
859 if (!srv_send_smb(smbd_server_fd(),
860 (char *)req->outbuf,
861 IS_CONN_ENCRYPTED(conn)))
862 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
864 TALLOC_FREE(req->outbuf);
866 pp += params_sent_thistime;
867 pd += data_sent_thistime;
869 params_to_send -= params_sent_thistime;
870 data_to_send -= data_sent_thistime;
872 /* Sanity check */
873 if(params_to_send < 0 || data_to_send < 0) {
874 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
875 params_to_send, data_to_send));
876 return;
880 return;
883 /****************************************************************************
884 Reply to a TRANSACT2_OPEN.
885 ****************************************************************************/
887 static void call_trans2open(connection_struct *conn,
888 struct smb_request *req,
889 char **pparams, int total_params,
890 char **ppdata, int total_data,
891 unsigned int max_data_bytes)
893 char *params = *pparams;
894 char *pdata = *ppdata;
895 int deny_mode;
896 int32 open_attr;
897 bool oplock_request;
898 #if 0
899 bool return_additional_info;
900 int16 open_sattr;
901 time_t open_time;
902 #endif
903 int open_ofun;
904 uint32 open_size;
905 char *pname;
906 char *fname = NULL;
907 SMB_OFF_T size=0;
908 int fattr=0,mtime=0;
909 SMB_INO_T inode = 0;
910 SMB_STRUCT_STAT sbuf;
911 int smb_action = 0;
912 files_struct *fsp;
913 struct ea_list *ea_list = NULL;
914 uint16 flags = 0;
915 NTSTATUS status;
916 uint32 access_mask;
917 uint32 share_mode;
918 uint32 create_disposition;
919 uint32 create_options = 0;
920 TALLOC_CTX *ctx = talloc_tos();
923 * Ensure we have enough parameters to perform the operation.
926 if (total_params < 29) {
927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 return;
931 flags = SVAL(params, 0);
932 deny_mode = SVAL(params, 2);
933 open_attr = SVAL(params,6);
934 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
935 if (oplock_request) {
936 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
939 #if 0
940 return_additional_info = BITSETW(params,0);
941 open_sattr = SVAL(params, 4);
942 open_time = make_unix_date3(params+8);
943 #endif
944 open_ofun = SVAL(params,12);
945 open_size = IVAL(params,14);
946 pname = &params[28];
948 if (IS_IPC(conn)) {
949 reply_doserror(req, ERRSRV, ERRaccess);
950 return;
953 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
954 total_params - 28, STR_TERMINATE,
955 &status);
956 if (!NT_STATUS_IS_OK(status)) {
957 reply_nterror(req, status);
958 return;
961 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
962 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
963 (unsigned int)open_ofun, open_size));
965 if (open_ofun == 0) {
966 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
967 return;
970 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
971 &access_mask,
972 &share_mode,
973 &create_disposition,
974 &create_options)) {
975 reply_doserror(req, ERRDOS, ERRbadaccess);
976 return;
979 /* Any data in this call is an EA list. */
980 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
981 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
982 return;
985 if (total_data != 4) {
986 if (total_data < 10) {
987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 return;
991 if (IVAL(pdata,0) > total_data) {
992 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
993 IVAL(pdata,0), (unsigned int)total_data));
994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
995 return;
998 ea_list = read_ea_list(talloc_tos(), pdata + 4,
999 total_data - 4);
1000 if (!ea_list) {
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1002 return;
1004 } else if (IVAL(pdata,0) != 4) {
1005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1006 return;
1009 status = SMB_VFS_CREATE_FILE(
1010 conn, /* conn */
1011 req, /* req */
1012 0, /* root_dir_fid */
1013 fname, /* fname */
1014 CFF_DOS_PATH, /* create_file_flags */
1015 access_mask, /* access_mask */
1016 share_mode, /* share_access */
1017 create_disposition, /* create_disposition*/
1018 create_options, /* create_options */
1019 open_attr, /* file_attributes */
1020 oplock_request, /* oplock_request */
1021 open_size, /* allocation_size */
1022 NULL, /* sd */
1023 ea_list, /* ea_list */
1024 &fsp, /* result */
1025 &smb_action, /* pinfo */
1026 &sbuf); /* psbuf */
1028 if (!NT_STATUS_IS_OK(status)) {
1029 if (open_was_deferred(req->mid)) {
1030 /* We have re-scheduled this call. */
1031 return;
1033 reply_openerror(req, status);
1034 return;
1037 size = get_file_size(sbuf);
1038 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1039 mtime = sbuf.st_mtime;
1040 inode = sbuf.st_ino;
1041 if (fattr & aDIR) {
1042 close_file(req, fsp, ERROR_CLOSE);
1043 reply_doserror(req, ERRDOS,ERRnoaccess);
1044 return;
1047 /* Realloc the size of parameters and data we will return */
1048 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1049 if(*pparams == NULL ) {
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1051 return;
1053 params = *pparams;
1055 SSVAL(params,0,fsp->fnum);
1056 SSVAL(params,2,fattr);
1057 srv_put_dos_date2(params,4, mtime);
1058 SIVAL(params,8, (uint32)size);
1059 SSVAL(params,12,deny_mode);
1060 SSVAL(params,14,0); /* open_type - file or directory. */
1061 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1063 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1064 smb_action |= EXTENDED_OPLOCK_GRANTED;
1067 SSVAL(params,18,smb_action);
1070 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1072 SIVAL(params,20,inode);
1073 SSVAL(params,24,0); /* Padding. */
1074 if (flags & 8) {
1075 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1076 SIVAL(params, 26, ea_size);
1077 } else {
1078 SIVAL(params, 26, 0);
1081 /* Send the required number of replies */
1082 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1085 /*********************************************************
1086 Routine to check if a given string matches exactly.
1087 as a special case a mask of "." does NOT match. That
1088 is required for correct wildcard semantics
1089 Case can be significant or not.
1090 **********************************************************/
1092 static bool exact_match(connection_struct *conn,
1093 const char *str,
1094 const char *mask)
1096 if (mask[0] == '.' && mask[1] == 0)
1097 return False;
1098 if (dptr_has_wild(conn->dirptr)) {
1099 return False;
1101 if (conn->case_sensitive)
1102 return strcmp(str,mask)==0;
1103 else
1104 return StrCaseCmp(str,mask) == 0;
1107 /****************************************************************************
1108 Return the filetype for UNIX extensions.
1109 ****************************************************************************/
1111 static uint32 unix_filetype(mode_t mode)
1113 if(S_ISREG(mode))
1114 return UNIX_TYPE_FILE;
1115 else if(S_ISDIR(mode))
1116 return UNIX_TYPE_DIR;
1117 #ifdef S_ISLNK
1118 else if(S_ISLNK(mode))
1119 return UNIX_TYPE_SYMLINK;
1120 #endif
1121 #ifdef S_ISCHR
1122 else if(S_ISCHR(mode))
1123 return UNIX_TYPE_CHARDEV;
1124 #endif
1125 #ifdef S_ISBLK
1126 else if(S_ISBLK(mode))
1127 return UNIX_TYPE_BLKDEV;
1128 #endif
1129 #ifdef S_ISFIFO
1130 else if(S_ISFIFO(mode))
1131 return UNIX_TYPE_FIFO;
1132 #endif
1133 #ifdef S_ISSOCK
1134 else if(S_ISSOCK(mode))
1135 return UNIX_TYPE_SOCKET;
1136 #endif
1138 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1139 return UNIX_TYPE_UNKNOWN;
1142 /****************************************************************************
1143 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1144 ****************************************************************************/
1146 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1148 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1149 SMB_STRUCT_STAT *psbuf,
1150 uint32 perms,
1151 enum perm_type ptype,
1152 mode_t *ret_perms)
1154 mode_t ret = 0;
1156 if (perms == SMB_MODE_NO_CHANGE) {
1157 if (!VALID_STAT(*psbuf)) {
1158 return NT_STATUS_INVALID_PARAMETER;
1159 } else {
1160 *ret_perms = psbuf->st_mode;
1161 return NT_STATUS_OK;
1165 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1166 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1167 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1168 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1169 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1170 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1171 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1172 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1173 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1174 #ifdef S_ISVTX
1175 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1176 #endif
1177 #ifdef S_ISGID
1178 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1179 #endif
1180 #ifdef S_ISUID
1181 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1182 #endif
1184 switch (ptype) {
1185 case PERM_NEW_FILE:
1186 /* Apply mode mask */
1187 ret &= lp_create_mask(SNUM(conn));
1188 /* Add in force bits */
1189 ret |= lp_force_create_mode(SNUM(conn));
1190 break;
1191 case PERM_NEW_DIR:
1192 ret &= lp_dir_mask(SNUM(conn));
1193 /* Add in force bits */
1194 ret |= lp_force_dir_mode(SNUM(conn));
1195 break;
1196 case PERM_EXISTING_FILE:
1197 /* Apply mode mask */
1198 ret &= lp_security_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_security_mode(SNUM(conn));
1201 break;
1202 case PERM_EXISTING_DIR:
1203 /* Apply mode mask */
1204 ret &= lp_dir_security_mask(SNUM(conn));
1205 /* Add in force bits */
1206 ret |= lp_force_dir_security_mode(SNUM(conn));
1207 break;
1210 *ret_perms = ret;
1211 return NT_STATUS_OK;
1214 /****************************************************************************
1215 Needed to show the msdfs symlinks as directories. Modifies psbuf
1216 to be a directory if it's a msdfs link.
1217 ****************************************************************************/
1219 static bool check_msdfs_link(connection_struct *conn,
1220 const char *pathname,
1221 SMB_STRUCT_STAT *psbuf)
1223 int saved_errno = errno;
1224 if(lp_host_msdfs() &&
1225 lp_msdfs_root(SNUM(conn)) &&
1226 is_msdfs_link(conn, pathname, psbuf)) {
1228 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1229 "as a directory\n",
1230 pathname));
1231 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1232 errno = saved_errno;
1233 return true;
1235 errno = saved_errno;
1236 return false;
1240 /****************************************************************************
1241 Get a level dependent lanman2 dir entry.
1242 ****************************************************************************/
1244 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1245 connection_struct *conn,
1246 uint16 flags2,
1247 const char *path_mask,
1248 uint32 dirtype,
1249 int info_level,
1250 int requires_resume_key,
1251 bool dont_descend,
1252 bool ask_sharemode,
1253 char **ppdata,
1254 char *base_data,
1255 char *end_data,
1256 int space_remaining,
1257 bool *out_of_space,
1258 bool *got_exact_match,
1259 int *last_entry_off,
1260 struct ea_list *name_list)
1262 const char *dname;
1263 bool found = False;
1264 SMB_STRUCT_STAT sbuf;
1265 const char *mask = NULL;
1266 char *pathreal = NULL;
1267 const char *fname = NULL;
1268 char *p, *q, *pdata = *ppdata;
1269 uint32 reskey=0;
1270 long prev_dirpos=0;
1271 uint32 mode=0;
1272 SMB_OFF_T file_size = 0;
1273 uint64_t allocation_size = 0;
1274 uint32 len;
1275 struct timespec mdate_ts, adate_ts, create_date_ts;
1276 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1277 char *nameptr;
1278 char *last_entry_ptr;
1279 bool was_8_3;
1280 uint32 nt_extmode; /* Used for NT connections instead of mode */
1281 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1282 bool check_mangled_names = lp_manglednames(conn->params);
1283 char mangled_name[13]; /* mangled 8.3 name. */
1285 *out_of_space = False;
1286 *got_exact_match = False;
1288 ZERO_STRUCT(mdate_ts);
1289 ZERO_STRUCT(adate_ts);
1290 ZERO_STRUCT(create_date_ts);
1292 if (!conn->dirptr) {
1293 return(False);
1296 p = strrchr_m(path_mask,'/');
1297 if(p != NULL) {
1298 if(p[1] == '\0') {
1299 mask = talloc_strdup(ctx,"*.*");
1300 } else {
1301 mask = p+1;
1303 } else {
1304 mask = path_mask;
1307 while (!found) {
1308 bool got_match;
1309 bool ms_dfs_link = False;
1311 /* Needed if we run out of space */
1312 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1313 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1316 * Due to bugs in NT client redirectors we are not using
1317 * resume keys any more - set them to zero.
1318 * Check out the related comments in findfirst/findnext.
1319 * JRA.
1322 reskey = 0;
1324 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1325 (long)conn->dirptr,curr_dirpos));
1327 if (!dname) {
1328 return(False);
1332 * fname may get mangled, dname is never mangled.
1333 * Whenever we're accessing the filesystem we use
1334 * pathreal which is composed from dname.
1337 pathreal = NULL;
1338 fname = dname;
1340 /* Mangle fname if it's an illegal name. */
1341 if (mangle_must_mangle(dname,conn->params)) {
1342 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1343 continue; /* Error - couldn't mangle. */
1345 fname = mangled_name;
1348 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1349 got_match = mask_match(fname, mask, conn->case_sensitive);
1352 if(!got_match && check_mangled_names &&
1353 !mangle_is_8_3(fname, False, conn->params)) {
1355 * It turns out that NT matches wildcards against
1356 * both long *and* short names. This may explain some
1357 * of the wildcard wierdness from old DOS clients
1358 * that some people have been seeing.... JRA.
1360 /* Force the mangling into 8.3. */
1361 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1362 continue; /* Error - couldn't mangle. */
1365 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1366 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1370 if (got_match) {
1371 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1373 if (dont_descend && !isdots) {
1374 continue;
1377 if (needslash) {
1378 pathreal = NULL;
1379 pathreal = talloc_asprintf(ctx,
1380 "%s/%s",
1381 conn->dirpath,
1382 dname);
1383 } else {
1384 pathreal = talloc_asprintf(ctx,
1385 "%s%s",
1386 conn->dirpath,
1387 dname);
1390 if (!pathreal) {
1391 return False;
1394 if (INFO_LEVEL_IS_UNIX(info_level)) {
1395 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1396 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1397 pathreal,strerror(errno)));
1398 TALLOC_FREE(pathreal);
1399 continue;
1401 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1402 /* Needed to show the msdfs symlinks as
1403 * directories */
1405 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1406 if (!ms_dfs_link) {
1407 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1408 pathreal,strerror(errno)));
1409 TALLOC_FREE(pathreal);
1410 continue;
1414 if (ms_dfs_link) {
1415 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1416 } else {
1417 mode = dos_mode(conn,pathreal,&sbuf);
1420 if (!dir_check_ftype(conn,mode,dirtype)) {
1421 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1422 TALLOC_FREE(pathreal);
1423 continue;
1426 if (!(mode & aDIR)) {
1427 file_size = get_file_size(sbuf);
1429 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1431 mdate_ts = get_mtimespec(&sbuf);
1432 adate_ts = get_atimespec(&sbuf);
1433 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1435 if (ask_sharemode) {
1436 struct timespec write_time_ts;
1437 struct file_id fileid;
1439 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1440 get_file_infos(fileid, NULL, &write_time_ts);
1441 if (!null_timespec(write_time_ts)) {
1442 mdate_ts = write_time_ts;
1446 if (lp_dos_filetime_resolution(SNUM(conn))) {
1447 dos_filetime_timespec(&create_date_ts);
1448 dos_filetime_timespec(&mdate_ts);
1449 dos_filetime_timespec(&adate_ts);
1452 create_date = convert_timespec_to_time_t(create_date_ts);
1453 mdate = convert_timespec_to_time_t(mdate_ts);
1454 adate = convert_timespec_to_time_t(adate_ts);
1456 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1458 found = True;
1460 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1464 p = pdata;
1465 last_entry_ptr = p;
1467 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1469 switch (info_level) {
1470 case SMB_FIND_INFO_STANDARD:
1471 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1472 if(requires_resume_key) {
1473 SIVAL(p,0,reskey);
1474 p += 4;
1476 srv_put_dos_date2(p,0,create_date);
1477 srv_put_dos_date2(p,4,adate);
1478 srv_put_dos_date2(p,8,mdate);
1479 SIVAL(p,12,(uint32)file_size);
1480 SIVAL(p,16,(uint32)allocation_size);
1481 SSVAL(p,20,mode);
1482 p += 23;
1483 nameptr = p;
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1485 p += ucs2_align(base_data, p, 0);
1487 len = srvstr_push(base_data, flags2, p,
1488 fname, PTR_DIFF(end_data, p),
1489 STR_TERMINATE);
1490 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1491 if (len > 2) {
1492 SCVAL(nameptr, -1, len - 2);
1493 } else {
1494 SCVAL(nameptr, -1, 0);
1496 } else {
1497 if (len > 1) {
1498 SCVAL(nameptr, -1, len - 1);
1499 } else {
1500 SCVAL(nameptr, -1, 0);
1503 p += len;
1504 break;
1506 case SMB_FIND_EA_SIZE:
1507 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1508 if(requires_resume_key) {
1509 SIVAL(p,0,reskey);
1510 p += 4;
1512 srv_put_dos_date2(p,0,create_date);
1513 srv_put_dos_date2(p,4,adate);
1514 srv_put_dos_date2(p,8,mdate);
1515 SIVAL(p,12,(uint32)file_size);
1516 SIVAL(p,16,(uint32)allocation_size);
1517 SSVAL(p,20,mode);
1519 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1520 SIVAL(p,22,ea_size); /* Extended attributes */
1522 p += 27;
1523 nameptr = p - 1;
1524 len = srvstr_push(base_data, flags2,
1525 p, fname, PTR_DIFF(end_data, p),
1526 STR_TERMINATE | STR_NOALIGN);
1527 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1528 if (len > 2) {
1529 len -= 2;
1530 } else {
1531 len = 0;
1533 } else {
1534 if (len > 1) {
1535 len -= 1;
1536 } else {
1537 len = 0;
1540 SCVAL(nameptr,0,len);
1541 p += len;
1542 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1543 break;
1545 case SMB_FIND_EA_LIST:
1547 struct ea_list *file_list = NULL;
1548 size_t ea_len = 0;
1550 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1551 if (!name_list) {
1552 return False;
1554 if(requires_resume_key) {
1555 SIVAL(p,0,reskey);
1556 p += 4;
1558 srv_put_dos_date2(p,0,create_date);
1559 srv_put_dos_date2(p,4,adate);
1560 srv_put_dos_date2(p,8,mdate);
1561 SIVAL(p,12,(uint32)file_size);
1562 SIVAL(p,16,(uint32)allocation_size);
1563 SSVAL(p,20,mode);
1564 p += 22; /* p now points to the EA area. */
1566 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1567 name_list = ea_list_union(name_list, file_list, &ea_len);
1569 /* We need to determine if this entry will fit in the space available. */
1570 /* Max string size is 255 bytes. */
1571 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1572 /* Move the dirptr back to prev_dirpos */
1573 dptr_SeekDir(conn->dirptr, prev_dirpos);
1574 *out_of_space = True;
1575 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1576 return False; /* Not finished - just out of space */
1579 /* Push the ea_data followed by the name. */
1580 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1581 nameptr = p;
1582 len = srvstr_push(base_data, flags2,
1583 p + 1, fname, PTR_DIFF(end_data, p+1),
1584 STR_TERMINATE | STR_NOALIGN);
1585 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1586 if (len > 2) {
1587 len -= 2;
1588 } else {
1589 len = 0;
1591 } else {
1592 if (len > 1) {
1593 len -= 1;
1594 } else {
1595 len = 0;
1598 SCVAL(nameptr,0,len);
1599 p += len + 1;
1600 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1601 break;
1604 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1605 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1606 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1607 p += 4;
1608 SIVAL(p,0,reskey); p += 4;
1609 put_long_date_timespec(p,create_date_ts); p += 8;
1610 put_long_date_timespec(p,adate_ts); p += 8;
1611 put_long_date_timespec(p,mdate_ts); p += 8;
1612 put_long_date_timespec(p,mdate_ts); p += 8;
1613 SOFF_T(p,0,file_size); p += 8;
1614 SOFF_T(p,0,allocation_size); p += 8;
1615 SIVAL(p,0,nt_extmode); p += 4;
1616 q = p; p += 4; /* q is placeholder for name length. */
1618 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1619 SIVAL(p,0,ea_size); /* Extended attributes */
1620 p += 4;
1622 /* Clear the short name buffer. This is
1623 * IMPORTANT as not doing so will trigger
1624 * a Win2k client bug. JRA.
1626 if (!was_8_3 && check_mangled_names) {
1627 if (!name_to_8_3(fname,mangled_name,True,
1628 conn->params)) {
1629 /* Error - mangle failed ! */
1630 memset(mangled_name,'\0',12);
1632 mangled_name[12] = 0;
1633 len = srvstr_push(base_data, flags2,
1634 p+2, mangled_name, 24,
1635 STR_UPPER|STR_UNICODE);
1636 if (len < 24) {
1637 memset(p + 2 + len,'\0',24 - len);
1639 SSVAL(p, 0, len);
1640 } else {
1641 memset(p,'\0',26);
1643 p += 2 + 24;
1644 len = srvstr_push(base_data, flags2, p,
1645 fname, PTR_DIFF(end_data, p),
1646 STR_TERMINATE_ASCII);
1647 SIVAL(q,0,len);
1648 p += len;
1649 SIVAL(p,0,0); /* Ensure any padding is null. */
1650 len = PTR_DIFF(p, pdata);
1651 len = (len + 3) & ~3;
1652 SIVAL(pdata,0,len);
1653 p = pdata + len;
1654 break;
1656 case SMB_FIND_FILE_DIRECTORY_INFO:
1657 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1658 p += 4;
1659 SIVAL(p,0,reskey); p += 4;
1660 put_long_date_timespec(p,create_date_ts); p += 8;
1661 put_long_date_timespec(p,adate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 put_long_date_timespec(p,mdate_ts); p += 8;
1664 SOFF_T(p,0,file_size); p += 8;
1665 SOFF_T(p,0,allocation_size); p += 8;
1666 SIVAL(p,0,nt_extmode); p += 4;
1667 len = srvstr_push(base_data, flags2,
1668 p + 4, fname, PTR_DIFF(end_data, p+4),
1669 STR_TERMINATE_ASCII);
1670 SIVAL(p,0,len);
1671 p += 4 + len;
1672 SIVAL(p,0,0); /* Ensure any padding is null. */
1673 len = PTR_DIFF(p, pdata);
1674 len = (len + 3) & ~3;
1675 SIVAL(pdata,0,len);
1676 p = pdata + len;
1677 break;
1679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1681 p += 4;
1682 SIVAL(p,0,reskey); p += 4;
1683 put_long_date_timespec(p,create_date_ts); p += 8;
1684 put_long_date_timespec(p,adate_ts); p += 8;
1685 put_long_date_timespec(p,mdate_ts); p += 8;
1686 put_long_date_timespec(p,mdate_ts); p += 8;
1687 SOFF_T(p,0,file_size); p += 8;
1688 SOFF_T(p,0,allocation_size); p += 8;
1689 SIVAL(p,0,nt_extmode); p += 4;
1690 q = p; p += 4; /* q is placeholder for name length. */
1692 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1693 SIVAL(p,0,ea_size); /* Extended attributes */
1694 p +=4;
1696 len = srvstr_push(base_data, flags2, p,
1697 fname, PTR_DIFF(end_data, p),
1698 STR_TERMINATE_ASCII);
1699 SIVAL(q, 0, len);
1700 p += len;
1702 SIVAL(p,0,0); /* Ensure any padding is null. */
1703 len = PTR_DIFF(p, pdata);
1704 len = (len + 3) & ~3;
1705 SIVAL(pdata,0,len);
1706 p = pdata + len;
1707 break;
1709 case SMB_FIND_FILE_NAMES_INFO:
1710 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1711 p += 4;
1712 SIVAL(p,0,reskey); p += 4;
1713 p += 4;
1714 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1715 acl on a dir (tridge) */
1716 len = srvstr_push(base_data, flags2, p,
1717 fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE_ASCII);
1719 SIVAL(p, -4, len);
1720 p += len;
1721 SIVAL(p,0,0); /* Ensure any padding is null. */
1722 len = PTR_DIFF(p, pdata);
1723 len = (len + 3) & ~3;
1724 SIVAL(pdata,0,len);
1725 p = pdata + len;
1726 break;
1728 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1729 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1730 p += 4;
1731 SIVAL(p,0,reskey); p += 4;
1732 put_long_date_timespec(p,create_date_ts); p += 8;
1733 put_long_date_timespec(p,adate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 put_long_date_timespec(p,mdate_ts); p += 8;
1736 SOFF_T(p,0,file_size); p += 8;
1737 SOFF_T(p,0,allocation_size); p += 8;
1738 SIVAL(p,0,nt_extmode); p += 4;
1739 q = p; p += 4; /* q is placeholder for name length. */
1741 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1742 SIVAL(p,0,ea_size); /* Extended attributes */
1743 p +=4;
1745 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1746 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1747 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1748 len = srvstr_push(base_data, flags2, p,
1749 fname, PTR_DIFF(end_data, p),
1750 STR_TERMINATE_ASCII);
1751 SIVAL(q, 0, len);
1752 p += len;
1753 SIVAL(p,0,0); /* Ensure any padding is null. */
1754 len = PTR_DIFF(p, pdata);
1755 len = (len + 3) & ~3;
1756 SIVAL(pdata,0,len);
1757 p = pdata + len;
1758 break;
1760 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1761 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1762 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1763 p += 4;
1764 SIVAL(p,0,reskey); p += 4;
1765 put_long_date_timespec(p,create_date_ts); p += 8;
1766 put_long_date_timespec(p,adate_ts); p += 8;
1767 put_long_date_timespec(p,mdate_ts); p += 8;
1768 put_long_date_timespec(p,mdate_ts); p += 8;
1769 SOFF_T(p,0,file_size); p += 8;
1770 SOFF_T(p,0,allocation_size); p += 8;
1771 SIVAL(p,0,nt_extmode); p += 4;
1772 q = p; p += 4; /* q is placeholder for name length */
1774 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1775 SIVAL(p,0,ea_size); /* Extended attributes */
1776 p +=4;
1778 /* Clear the short name buffer. This is
1779 * IMPORTANT as not doing so will trigger
1780 * a Win2k client bug. JRA.
1782 if (!was_8_3 && check_mangled_names) {
1783 if (!name_to_8_3(fname,mangled_name,True,
1784 conn->params)) {
1785 /* Error - mangle failed ! */
1786 memset(mangled_name,'\0',12);
1788 mangled_name[12] = 0;
1789 len = srvstr_push(base_data, flags2,
1790 p+2, mangled_name, 24,
1791 STR_UPPER|STR_UNICODE);
1792 SSVAL(p, 0, len);
1793 if (len < 24) {
1794 memset(p + 2 + len,'\0',24 - len);
1796 SSVAL(p, 0, len);
1797 } else {
1798 memset(p,'\0',26);
1800 p += 26;
1801 SSVAL(p,0,0); p += 2; /* Reserved ? */
1802 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1803 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1804 len = srvstr_push(base_data, flags2, p,
1805 fname, PTR_DIFF(end_data, p),
1806 STR_TERMINATE_ASCII);
1807 SIVAL(q,0,len);
1808 p += len;
1809 SIVAL(p,0,0); /* Ensure any padding is null. */
1810 len = PTR_DIFF(p, pdata);
1811 len = (len + 3) & ~3;
1812 SIVAL(pdata,0,len);
1813 p = pdata + len;
1814 break;
1816 /* CIFS UNIX Extension. */
1818 case SMB_FIND_FILE_UNIX:
1819 case SMB_FIND_FILE_UNIX_INFO2:
1820 p+= 4;
1821 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1823 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1825 if (info_level == SMB_FIND_FILE_UNIX) {
1826 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1827 p = store_file_unix_basic(conn, p,
1828 NULL, &sbuf);
1829 len = srvstr_push(base_data, flags2, p,
1830 fname, PTR_DIFF(end_data, p),
1831 STR_TERMINATE);
1832 } else {
1833 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1834 p = store_file_unix_basic_info2(conn, p,
1835 NULL, &sbuf);
1836 nameptr = p;
1837 p += 4;
1838 len = srvstr_push(base_data, flags2, p, fname,
1839 PTR_DIFF(end_data, p), 0);
1840 SIVAL(nameptr, 0, len);
1843 p += len;
1844 SIVAL(p,0,0); /* Ensure any padding is null. */
1846 len = PTR_DIFF(p, pdata);
1847 len = (len + 3) & ~3;
1848 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1849 p = pdata + len;
1850 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1852 break;
1854 default:
1855 return(False);
1859 if (PTR_DIFF(p,pdata) > space_remaining) {
1860 /* Move the dirptr back to prev_dirpos */
1861 dptr_SeekDir(conn->dirptr, prev_dirpos);
1862 *out_of_space = True;
1863 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1864 return False; /* Not finished - just out of space */
1867 /* Setup the last entry pointer, as an offset from base_data */
1868 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1869 /* Advance the data pointer to the next slot */
1870 *ppdata = p;
1872 return(found);
1875 /****************************************************************************
1876 Reply to a TRANS2_FINDFIRST.
1877 ****************************************************************************/
1879 static void call_trans2findfirst(connection_struct *conn,
1880 struct smb_request *req,
1881 char **pparams, int total_params,
1882 char **ppdata, int total_data,
1883 unsigned int max_data_bytes)
1885 /* We must be careful here that we don't return more than the
1886 allowed number of data bytes. If this means returning fewer than
1887 maxentries then so be it. We assume that the redirector has
1888 enough room for the fixed number of parameter bytes it has
1889 requested. */
1890 char *params = *pparams;
1891 char *pdata = *ppdata;
1892 char *data_end;
1893 uint32 dirtype;
1894 int maxentries;
1895 uint16 findfirst_flags;
1896 bool close_after_first;
1897 bool close_if_end;
1898 bool requires_resume_key;
1899 int info_level;
1900 char *directory = NULL;
1901 char *mask = NULL;
1902 char *p;
1903 int last_entry_off=0;
1904 int dptr_num = -1;
1905 int numentries = 0;
1906 int i;
1907 bool finished = False;
1908 bool dont_descend = False;
1909 bool out_of_space = False;
1910 int space_remaining;
1911 bool mask_contains_wcard = False;
1912 SMB_STRUCT_STAT sbuf;
1913 struct ea_list *ea_list = NULL;
1914 NTSTATUS ntstatus = NT_STATUS_OK;
1915 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1916 TALLOC_CTX *ctx = talloc_tos();
1918 if (total_params < 13) {
1919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1920 return;
1923 dirtype = SVAL(params,0);
1924 maxentries = SVAL(params,2);
1925 findfirst_flags = SVAL(params,4);
1926 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1927 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1928 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1929 info_level = SVAL(params,6);
1931 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1932 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1933 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1934 info_level, max_data_bytes));
1936 if (!maxentries) {
1937 /* W2K3 seems to treat zero as 1. */
1938 maxentries = 1;
1941 switch (info_level) {
1942 case SMB_FIND_INFO_STANDARD:
1943 case SMB_FIND_EA_SIZE:
1944 case SMB_FIND_EA_LIST:
1945 case SMB_FIND_FILE_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_NAMES_INFO:
1948 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1949 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1950 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1951 break;
1952 case SMB_FIND_FILE_UNIX:
1953 case SMB_FIND_FILE_UNIX_INFO2:
1954 /* Always use filesystem for UNIX mtime query. */
1955 ask_sharemode = false;
1956 if (!lp_unix_extensions()) {
1957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1958 return;
1960 break;
1961 default:
1962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1963 return;
1966 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1967 params+12, total_params - 12,
1968 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 reply_nterror(req, ntstatus);
1971 return;
1974 ntstatus = resolve_dfspath_wcard(ctx, conn,
1975 req->flags2 & FLAGS2_DFS_PATHNAMES,
1976 directory,
1977 &directory,
1978 &mask_contains_wcard);
1979 if (!NT_STATUS_IS_OK(ntstatus)) {
1980 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1981 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1982 ERRSRV, ERRbadpath);
1983 return;
1985 reply_nterror(req, ntstatus);
1986 return;
1989 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1990 if (!NT_STATUS_IS_OK(ntstatus)) {
1991 reply_nterror(req, ntstatus);
1992 return;
1995 ntstatus = check_name(conn, directory);
1996 if (!NT_STATUS_IS_OK(ntstatus)) {
1997 reply_nterror(req, ntstatus);
1998 return;
2001 p = strrchr_m(directory,'/');
2002 if(p == NULL) {
2003 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2004 if((directory[0] == '.') && (directory[1] == '\0')) {
2005 mask = talloc_strdup(ctx,"*");
2006 if (!mask) {
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 return;
2010 mask_contains_wcard = True;
2012 directory = talloc_strdup(talloc_tos(), "./");
2013 if (!directory) {
2014 reply_nterror(req, NT_STATUS_NO_MEMORY);
2015 return;
2017 } else {
2018 *p = 0;
2021 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2023 if (info_level == SMB_FIND_EA_LIST) {
2024 uint32 ea_size;
2026 if (total_data < 4) {
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 return;
2031 ea_size = IVAL(pdata,0);
2032 if (ea_size != total_data) {
2033 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2034 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2036 return;
2039 if (!lp_ea_support(SNUM(conn))) {
2040 reply_doserror(req, ERRDOS, ERReasnotsupported);
2041 return;
2044 /* Pull out the list of names. */
2045 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2046 if (!ea_list) {
2047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2048 return;
2052 *ppdata = (char *)SMB_REALLOC(
2053 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2054 if(*ppdata == NULL ) {
2055 reply_nterror(req, NT_STATUS_NO_MEMORY);
2056 return;
2058 pdata = *ppdata;
2059 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2061 /* Realloc the params space */
2062 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2063 if (*pparams == NULL) {
2064 reply_nterror(req, NT_STATUS_NO_MEMORY);
2065 return;
2067 params = *pparams;
2069 /* Save the wildcard match and attribs we are using on this directory -
2070 needed as lanman2 assumes these are being saved between calls */
2072 ntstatus = dptr_create(conn,
2073 directory,
2074 False,
2075 True,
2076 req->smbpid,
2077 mask,
2078 mask_contains_wcard,
2079 dirtype,
2080 &conn->dirptr);
2082 if (!NT_STATUS_IS_OK(ntstatus)) {
2083 reply_nterror(req, ntstatus);
2084 return;
2087 dptr_num = dptr_dnum(conn->dirptr);
2088 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2090 /* We don't need to check for VOL here as this is returned by
2091 a different TRANS2 call. */
2093 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2094 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2095 dont_descend = True;
2097 p = pdata;
2098 space_remaining = max_data_bytes;
2099 out_of_space = False;
2101 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2102 bool got_exact_match = False;
2104 /* this is a heuristic to avoid seeking the dirptr except when
2105 absolutely necessary. It allows for a filename of about 40 chars */
2106 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2107 out_of_space = True;
2108 finished = False;
2109 } else {
2110 finished = !get_lanman2_dir_entry(ctx,
2111 conn,
2112 req->flags2,
2113 mask,dirtype,info_level,
2114 requires_resume_key,dont_descend,
2115 ask_sharemode,
2116 &p,pdata,data_end,
2117 space_remaining, &out_of_space,
2118 &got_exact_match,
2119 &last_entry_off, ea_list);
2122 if (finished && out_of_space)
2123 finished = False;
2125 if (!finished && !out_of_space)
2126 numentries++;
2129 * As an optimisation if we know we aren't looking
2130 * for a wildcard name (ie. the name matches the wildcard exactly)
2131 * then we can finish on any (first) match.
2132 * This speeds up large directory searches. JRA.
2135 if(got_exact_match)
2136 finished = True;
2138 /* Ensure space_remaining never goes -ve. */
2139 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2140 space_remaining = 0;
2141 out_of_space = true;
2142 } else {
2143 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2147 /* Check if we can close the dirptr */
2148 if(close_after_first || (finished && close_if_end)) {
2149 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2150 dptr_close(&dptr_num);
2154 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2155 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2156 * the protocol level is less than NT1. Tested with smbclient. JRA.
2157 * This should fix the OS/2 client bug #2335.
2160 if(numentries == 0) {
2161 dptr_close(&dptr_num);
2162 if (Protocol < PROTOCOL_NT1) {
2163 reply_doserror(req, ERRDOS, ERRnofiles);
2164 return;
2165 } else {
2166 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2167 ERRDOS, ERRbadfile);
2168 return;
2172 /* At this point pdata points to numentries directory entries. */
2174 /* Set up the return parameter block */
2175 SSVAL(params,0,dptr_num);
2176 SSVAL(params,2,numentries);
2177 SSVAL(params,4,finished);
2178 SSVAL(params,6,0); /* Never an EA error */
2179 SSVAL(params,8,last_entry_off);
2181 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2182 max_data_bytes);
2184 if ((! *directory) && dptr_path(dptr_num)) {
2185 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2186 if (!directory) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2192 smb_fn_name(req->cmd),
2193 mask, directory, dirtype, numentries ) );
2196 * Force a name mangle here to ensure that the
2197 * mask as an 8.3 name is top of the mangled cache.
2198 * The reasons for this are subtle. Don't remove
2199 * this code unless you know what you are doing
2200 * (see PR#13758). JRA.
2203 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2204 char mangled_name[13];
2205 name_to_8_3(mask, mangled_name, True, conn->params);
2208 return;
2211 /****************************************************************************
2212 Reply to a TRANS2_FINDNEXT.
2213 ****************************************************************************/
2215 static void call_trans2findnext(connection_struct *conn,
2216 struct smb_request *req,
2217 char **pparams, int total_params,
2218 char **ppdata, int total_data,
2219 unsigned int max_data_bytes)
2221 /* We must be careful here that we don't return more than the
2222 allowed number of data bytes. If this means returning fewer than
2223 maxentries then so be it. We assume that the redirector has
2224 enough room for the fixed number of parameter bytes it has
2225 requested. */
2226 char *params = *pparams;
2227 char *pdata = *ppdata;
2228 char *data_end;
2229 int dptr_num;
2230 int maxentries;
2231 uint16 info_level;
2232 uint32 resume_key;
2233 uint16 findnext_flags;
2234 bool close_after_request;
2235 bool close_if_end;
2236 bool requires_resume_key;
2237 bool continue_bit;
2238 bool mask_contains_wcard = False;
2239 char *resume_name = NULL;
2240 const char *mask = NULL;
2241 const char *directory = NULL;
2242 char *p = NULL;
2243 uint16 dirtype;
2244 int numentries = 0;
2245 int i, last_entry_off=0;
2246 bool finished = False;
2247 bool dont_descend = False;
2248 bool out_of_space = False;
2249 int space_remaining;
2250 struct ea_list *ea_list = NULL;
2251 NTSTATUS ntstatus = NT_STATUS_OK;
2252 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2253 TALLOC_CTX *ctx = talloc_tos();
2255 if (total_params < 13) {
2256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2257 return;
2260 dptr_num = SVAL(params,0);
2261 maxentries = SVAL(params,2);
2262 info_level = SVAL(params,4);
2263 resume_key = IVAL(params,6);
2264 findnext_flags = SVAL(params,10);
2265 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2266 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2267 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2268 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2270 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2271 params+12,
2272 total_params - 12, STR_TERMINATE, &ntstatus,
2273 &mask_contains_wcard);
2274 if (!NT_STATUS_IS_OK(ntstatus)) {
2275 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2276 complain (it thinks we're asking for the directory above the shared
2277 path or an invalid name). Catch this as the resume name is only compared, never used in
2278 a file access. JRA. */
2279 srvstr_pull_talloc(ctx, params, req->flags2,
2280 &resume_name, params+12,
2281 total_params - 12,
2282 STR_TERMINATE);
2284 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2285 reply_nterror(req, ntstatus);
2286 return;
2290 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2291 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2292 resume_key = %d resume name = %s continue=%d level = %d\n",
2293 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2294 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2296 if (!maxentries) {
2297 /* W2K3 seems to treat zero as 1. */
2298 maxentries = 1;
2301 switch (info_level) {
2302 case SMB_FIND_INFO_STANDARD:
2303 case SMB_FIND_EA_SIZE:
2304 case SMB_FIND_EA_LIST:
2305 case SMB_FIND_FILE_DIRECTORY_INFO:
2306 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_NAMES_INFO:
2308 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2309 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2310 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2311 break;
2312 case SMB_FIND_FILE_UNIX:
2313 case SMB_FIND_FILE_UNIX_INFO2:
2314 /* Always use filesystem for UNIX mtime query. */
2315 ask_sharemode = false;
2316 if (!lp_unix_extensions()) {
2317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 return;
2320 break;
2321 default:
2322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2323 return;
2326 if (info_level == SMB_FIND_EA_LIST) {
2327 uint32 ea_size;
2329 if (total_data < 4) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 return;
2334 ea_size = IVAL(pdata,0);
2335 if (ea_size != total_data) {
2336 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2337 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2339 return;
2342 if (!lp_ea_support(SNUM(conn))) {
2343 reply_doserror(req, ERRDOS, ERReasnotsupported);
2344 return;
2347 /* Pull out the list of names. */
2348 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2349 if (!ea_list) {
2350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2351 return;
2355 *ppdata = (char *)SMB_REALLOC(
2356 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2357 if(*ppdata == NULL) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 return;
2362 pdata = *ppdata;
2363 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2365 /* Realloc the params space */
2366 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2367 if(*pparams == NULL ) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 return;
2372 params = *pparams;
2374 /* Check that the dptr is valid */
2375 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2376 reply_doserror(req, ERRDOS, ERRnofiles);
2377 return;
2380 string_set(&conn->dirpath,dptr_path(dptr_num));
2382 /* Get the wildcard mask from the dptr */
2383 if((p = dptr_wcard(dptr_num))== NULL) {
2384 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2385 reply_doserror(req, ERRDOS, ERRnofiles);
2386 return;
2389 mask = p;
2390 directory = conn->dirpath;
2392 /* Get the attr mask from the dptr */
2393 dirtype = dptr_attr(dptr_num);
2395 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2396 dptr_num, mask, dirtype,
2397 (long)conn->dirptr,
2398 dptr_TellDir(conn->dirptr)));
2400 /* We don't need to check for VOL here as this is returned by
2401 a different TRANS2 call. */
2403 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2404 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2405 dont_descend = True;
2407 p = pdata;
2408 space_remaining = max_data_bytes;
2409 out_of_space = False;
2412 * Seek to the correct position. We no longer use the resume key but
2413 * depend on the last file name instead.
2416 if(*resume_name && !continue_bit) {
2417 SMB_STRUCT_STAT st;
2419 long current_pos = 0;
2421 * Remember, name_to_8_3 is called by
2422 * get_lanman2_dir_entry(), so the resume name
2423 * could be mangled. Ensure we check the unmangled name.
2426 if (mangle_is_mangled(resume_name, conn->params)) {
2427 char *new_resume_name = NULL;
2428 mangle_lookup_name_from_8_3(ctx,
2429 resume_name,
2430 &new_resume_name,
2431 conn->params);
2432 if (new_resume_name) {
2433 resume_name = new_resume_name;
2438 * Fix for NT redirector problem triggered by resume key indexes
2439 * changing between directory scans. We now return a resume key of 0
2440 * and instead look for the filename to continue from (also given
2441 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2442 * findfirst/findnext (as is usual) then the directory pointer
2443 * should already be at the correct place.
2446 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2447 } /* end if resume_name && !continue_bit */
2449 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2450 bool got_exact_match = False;
2452 /* this is a heuristic to avoid seeking the dirptr except when
2453 absolutely necessary. It allows for a filename of about 40 chars */
2454 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2455 out_of_space = True;
2456 finished = False;
2457 } else {
2458 finished = !get_lanman2_dir_entry(ctx,
2459 conn,
2460 req->flags2,
2461 mask,dirtype,info_level,
2462 requires_resume_key,dont_descend,
2463 ask_sharemode,
2464 &p,pdata,data_end,
2465 space_remaining, &out_of_space,
2466 &got_exact_match,
2467 &last_entry_off, ea_list);
2470 if (finished && out_of_space)
2471 finished = False;
2473 if (!finished && !out_of_space)
2474 numentries++;
2477 * As an optimisation if we know we aren't looking
2478 * for a wildcard name (ie. the name matches the wildcard exactly)
2479 * then we can finish on any (first) match.
2480 * This speeds up large directory searches. JRA.
2483 if(got_exact_match)
2484 finished = True;
2486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2489 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2490 smb_fn_name(req->cmd),
2491 mask, directory, dirtype, numentries ) );
2493 /* Check if we can close the dirptr */
2494 if(close_after_request || (finished && close_if_end)) {
2495 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2496 dptr_close(&dptr_num); /* This frees up the saved mask */
2499 /* Set up the return parameter block */
2500 SSVAL(params,0,numentries);
2501 SSVAL(params,2,finished);
2502 SSVAL(params,4,0); /* Never an EA error */
2503 SSVAL(params,6,last_entry_off);
2505 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2506 max_data_bytes);
2508 return;
2511 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2513 E_md4hash(lp_servicename(SNUM(conn)),objid);
2514 return objid;
2517 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2519 SMB_ASSERT(extended_info != NULL);
2521 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2522 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2523 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2524 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2525 #ifdef SAMBA_VERSION_REVISION
2526 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2527 #endif
2528 extended_info->samba_subversion = 0;
2529 #ifdef SAMBA_VERSION_RC_RELEASE
2530 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2531 #else
2532 #ifdef SAMBA_VERSION_PRE_RELEASE
2533 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2534 #endif
2535 #endif
2536 #ifdef SAMBA_VERSION_VENDOR_PATCH
2537 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2538 #endif
2539 extended_info->samba_gitcommitdate = 0;
2540 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2541 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2542 #endif
2544 memset(extended_info->samba_version_string, 0,
2545 sizeof(extended_info->samba_version_string));
2547 snprintf (extended_info->samba_version_string,
2548 sizeof(extended_info->samba_version_string),
2549 "%s", samba_version_string());
2552 /****************************************************************************
2553 Reply to a TRANS2_QFSINFO (query filesystem info).
2554 ****************************************************************************/
2556 static void call_trans2qfsinfo(connection_struct *conn,
2557 struct smb_request *req,
2558 char **pparams, int total_params,
2559 char **ppdata, int total_data,
2560 unsigned int max_data_bytes)
2562 char *pdata, *end_data;
2563 char *params = *pparams;
2564 uint16 info_level;
2565 int data_len, len;
2566 SMB_STRUCT_STAT st;
2567 const char *vname = volume_label(SNUM(conn));
2568 int snum = SNUM(conn);
2569 char *fstype = lp_fstype(SNUM(conn));
2570 uint32 additional_flags = 0;
2572 if (total_params < 2) {
2573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2574 return;
2577 info_level = SVAL(params,0);
2579 if (IS_IPC(conn)) {
2580 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2581 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2582 "info level (0x%x) on IPC$.\n",
2583 (unsigned int)info_level));
2584 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2585 return;
2589 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2590 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2591 DEBUG(0,("call_trans2qfsinfo: encryption required "
2592 "and info level 0x%x sent.\n",
2593 (unsigned int)info_level));
2594 exit_server_cleanly("encryption required "
2595 "on connection");
2596 return;
2600 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2602 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2603 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2604 reply_doserror(req, ERRSRV, ERRinvdevice);
2605 return;
2608 *ppdata = (char *)SMB_REALLOC(
2609 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2610 if (*ppdata == NULL ) {
2611 reply_nterror(req, NT_STATUS_NO_MEMORY);
2612 return;
2615 pdata = *ppdata;
2616 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2617 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2619 switch (info_level) {
2620 case SMB_INFO_ALLOCATION:
2622 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2623 data_len = 18;
2624 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2625 reply_unixerror(req, ERRHRD, ERRgeneral);
2626 return;
2629 block_size = lp_block_size(snum);
2630 if (bsize < block_size) {
2631 uint64_t factor = block_size/bsize;
2632 bsize = block_size;
2633 dsize /= factor;
2634 dfree /= factor;
2636 if (bsize > block_size) {
2637 uint64_t factor = bsize/block_size;
2638 bsize = block_size;
2639 dsize *= factor;
2640 dfree *= factor;
2642 bytes_per_sector = 512;
2643 sectors_per_unit = bsize/bytes_per_sector;
2645 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2647 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2649 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2650 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2651 SIVAL(pdata,l1_cUnit,dsize);
2652 SIVAL(pdata,l1_cUnitAvail,dfree);
2653 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2654 break;
2657 case SMB_INFO_VOLUME:
2658 /* Return volume name */
2660 * Add volume serial number - hash of a combination of
2661 * the called hostname and the service name.
2663 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2665 * Win2k3 and previous mess this up by sending a name length
2666 * one byte short. I believe only older clients (OS/2 Win9x) use
2667 * this call so try fixing this by adding a terminating null to
2668 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2670 len = srvstr_push(
2671 pdata, req->flags2,
2672 pdata+l2_vol_szVolLabel, vname,
2673 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2674 STR_NOALIGN|STR_TERMINATE);
2675 SCVAL(pdata,l2_vol_cch,len);
2676 data_len = l2_vol_szVolLabel + len;
2677 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2678 (unsigned)st.st_ctime, len, vname));
2679 break;
2681 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2682 case SMB_FS_ATTRIBUTE_INFORMATION:
2684 additional_flags = 0;
2685 #if defined(HAVE_SYS_QUOTAS)
2686 additional_flags |= FILE_VOLUME_QUOTAS;
2687 #endif
2689 if(lp_nt_acl_support(SNUM(conn))) {
2690 additional_flags |= FILE_PERSISTENT_ACLS;
2693 /* Capabilities are filled in at connection time through STATVFS call */
2694 additional_flags |= conn->fs_capabilities;
2696 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2697 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2698 additional_flags); /* FS ATTRIBUTES */
2700 SIVAL(pdata,4,255); /* Max filename component length */
2701 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2702 and will think we can't do long filenames */
2703 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2704 PTR_DIFF(end_data, pdata+12),
2705 STR_UNICODE);
2706 SIVAL(pdata,8,len);
2707 data_len = 12 + len;
2708 break;
2710 case SMB_QUERY_FS_LABEL_INFO:
2711 case SMB_FS_LABEL_INFORMATION:
2712 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2713 PTR_DIFF(end_data, pdata+4), 0);
2714 data_len = 4 + len;
2715 SIVAL(pdata,0,len);
2716 break;
2718 case SMB_QUERY_FS_VOLUME_INFO:
2719 case SMB_FS_VOLUME_INFORMATION:
2722 * Add volume serial number - hash of a combination of
2723 * the called hostname and the service name.
2725 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2726 (str_checksum(get_local_machine_name())<<16));
2728 /* Max label len is 32 characters. */
2729 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2730 PTR_DIFF(end_data, pdata+18),
2731 STR_UNICODE);
2732 SIVAL(pdata,12,len);
2733 data_len = 18+len;
2735 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2736 (int)strlen(vname),vname, lp_servicename(snum)));
2737 break;
2739 case SMB_QUERY_FS_SIZE_INFO:
2740 case SMB_FS_SIZE_INFORMATION:
2742 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2743 data_len = 24;
2744 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2745 reply_unixerror(req, ERRHRD, ERRgeneral);
2746 return;
2748 block_size = lp_block_size(snum);
2749 if (bsize < block_size) {
2750 uint64_t factor = block_size/bsize;
2751 bsize = block_size;
2752 dsize /= factor;
2753 dfree /= factor;
2755 if (bsize > block_size) {
2756 uint64_t factor = bsize/block_size;
2757 bsize = block_size;
2758 dsize *= factor;
2759 dfree *= factor;
2761 bytes_per_sector = 512;
2762 sectors_per_unit = bsize/bytes_per_sector;
2763 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2764 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2765 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2766 SBIG_UINT(pdata,0,dsize);
2767 SBIG_UINT(pdata,8,dfree);
2768 SIVAL(pdata,16,sectors_per_unit);
2769 SIVAL(pdata,20,bytes_per_sector);
2770 break;
2773 case SMB_FS_FULL_SIZE_INFORMATION:
2775 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2776 data_len = 32;
2777 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2778 reply_unixerror(req, ERRHRD, ERRgeneral);
2779 return;
2781 block_size = lp_block_size(snum);
2782 if (bsize < block_size) {
2783 uint64_t factor = block_size/bsize;
2784 bsize = block_size;
2785 dsize /= factor;
2786 dfree /= factor;
2788 if (bsize > block_size) {
2789 uint64_t factor = bsize/block_size;
2790 bsize = block_size;
2791 dsize *= factor;
2792 dfree *= factor;
2794 bytes_per_sector = 512;
2795 sectors_per_unit = bsize/bytes_per_sector;
2796 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2797 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2798 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2799 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2800 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2801 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2802 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2803 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2804 break;
2807 case SMB_QUERY_FS_DEVICE_INFO:
2808 case SMB_FS_DEVICE_INFORMATION:
2809 data_len = 8;
2810 SIVAL(pdata,0,0); /* dev type */
2811 SIVAL(pdata,4,0); /* characteristics */
2812 break;
2814 #ifdef HAVE_SYS_QUOTAS
2815 case SMB_FS_QUOTA_INFORMATION:
2817 * what we have to send --metze:
2819 * Unknown1: 24 NULL bytes
2820 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2821 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2822 * Quota Flags: 2 byte :
2823 * Unknown3: 6 NULL bytes
2825 * 48 bytes total
2827 * details for Quota Flags:
2829 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2830 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2831 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2832 * 0x0001 Enable Quotas: enable quota for this fs
2836 /* we need to fake up a fsp here,
2837 * because its not send in this call
2839 files_struct fsp;
2840 SMB_NTQUOTA_STRUCT quotas;
2842 ZERO_STRUCT(fsp);
2843 ZERO_STRUCT(quotas);
2845 fsp.conn = conn;
2846 fsp.fnum = -1;
2848 /* access check */
2849 if (conn->server_info->utok.uid != 0) {
2850 DEBUG(0,("set_user_quota: access_denied "
2851 "service [%s] user [%s]\n",
2852 lp_servicename(SNUM(conn)),
2853 conn->server_info->unix_name));
2854 reply_doserror(req, ERRDOS, ERRnoaccess);
2855 return;
2858 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2859 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2860 reply_doserror(req, ERRSRV, ERRerror);
2861 return;
2864 data_len = 48;
2866 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2868 /* Unknown1 24 NULL bytes*/
2869 SBIG_UINT(pdata,0,(uint64_t)0);
2870 SBIG_UINT(pdata,8,(uint64_t)0);
2871 SBIG_UINT(pdata,16,(uint64_t)0);
2873 /* Default Soft Quota 8 bytes */
2874 SBIG_UINT(pdata,24,quotas.softlim);
2876 /* Default Hard Quota 8 bytes */
2877 SBIG_UINT(pdata,32,quotas.hardlim);
2879 /* Quota flag 2 bytes */
2880 SSVAL(pdata,40,quotas.qflags);
2882 /* Unknown3 6 NULL bytes */
2883 SSVAL(pdata,42,0);
2884 SIVAL(pdata,44,0);
2886 break;
2888 #endif /* HAVE_SYS_QUOTAS */
2889 case SMB_FS_OBJECTID_INFORMATION:
2891 unsigned char objid[16];
2892 struct smb_extended_info extended_info;
2893 memcpy(pdata,create_volume_objectid(conn, objid),16);
2894 samba_extended_info_version (&extended_info);
2895 SIVAL(pdata,16,extended_info.samba_magic);
2896 SIVAL(pdata,20,extended_info.samba_version);
2897 SIVAL(pdata,24,extended_info.samba_subversion);
2898 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2899 memcpy(pdata+36,extended_info.samba_version_string,28);
2900 data_len = 64;
2901 break;
2905 * Query the version and capabilities of the CIFS UNIX extensions
2906 * in use.
2909 case SMB_QUERY_CIFS_UNIX_INFO:
2911 bool large_write = lp_min_receive_file_size() &&
2912 !srv_is_signing_active();
2913 bool large_read = !srv_is_signing_active();
2914 int encrypt_caps = 0;
2916 if (!lp_unix_extensions()) {
2917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2918 return;
2921 switch (conn->encrypt_level) {
2922 case 0:
2923 encrypt_caps = 0;
2924 break;
2925 case 1:
2926 case Auto:
2927 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2928 break;
2929 case Required:
2930 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2931 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2932 large_write = false;
2933 large_read = false;
2934 break;
2937 data_len = 12;
2938 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2939 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2941 /* We have POSIX ACLs, pathname, encryption,
2942 * large read/write, and locking capability. */
2944 SBIG_UINT(pdata,4,((uint64_t)(
2945 CIFS_UNIX_POSIX_ACLS_CAP|
2946 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2947 CIFS_UNIX_FCNTL_LOCKS_CAP|
2948 CIFS_UNIX_EXTATTR_CAP|
2949 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2950 encrypt_caps|
2951 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2952 (large_write ?
2953 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2954 break;
2957 case SMB_QUERY_POSIX_FS_INFO:
2959 int rc;
2960 vfs_statvfs_struct svfs;
2962 if (!lp_unix_extensions()) {
2963 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2964 return;
2967 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2969 if (!rc) {
2970 data_len = 56;
2971 SIVAL(pdata,0,svfs.OptimalTransferSize);
2972 SIVAL(pdata,4,svfs.BlockSize);
2973 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2974 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2975 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2976 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2977 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2978 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2979 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2980 #ifdef EOPNOTSUPP
2981 } else if (rc == EOPNOTSUPP) {
2982 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2983 return;
2984 #endif /* EOPNOTSUPP */
2985 } else {
2986 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2987 reply_doserror(req, ERRSRV, ERRerror);
2988 return;
2990 break;
2993 case SMB_QUERY_POSIX_WHOAMI:
2995 uint32_t flags = 0;
2996 uint32_t sid_bytes;
2997 int i;
2999 if (!lp_unix_extensions()) {
3000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3001 return;
3004 if (max_data_bytes < 40) {
3005 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3006 return;
3009 /* We ARE guest if global_sid_Builtin_Guests is
3010 * in our list of SIDs.
3012 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3013 conn->server_info->ptok)) {
3014 flags |= SMB_WHOAMI_GUEST;
3017 /* We are NOT guest if global_sid_Authenticated_Users
3018 * is in our list of SIDs.
3020 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3021 conn->server_info->ptok)) {
3022 flags &= ~SMB_WHOAMI_GUEST;
3025 /* NOTE: 8 bytes for UID/GID, irrespective of native
3026 * platform size. This matches
3027 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3029 data_len = 4 /* flags */
3030 + 4 /* flag mask */
3031 + 8 /* uid */
3032 + 8 /* gid */
3033 + 4 /* ngroups */
3034 + 4 /* num_sids */
3035 + 4 /* SID bytes */
3036 + 4 /* pad/reserved */
3037 + (conn->server_info->utok.ngroups * 8)
3038 /* groups list */
3039 + (conn->server_info->ptok->num_sids *
3040 SID_MAX_SIZE)
3041 /* SID list */;
3043 SIVAL(pdata, 0, flags);
3044 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3045 SBIG_UINT(pdata, 8,
3046 (uint64_t)conn->server_info->utok.uid);
3047 SBIG_UINT(pdata, 16,
3048 (uint64_t)conn->server_info->utok.gid);
3051 if (data_len >= max_data_bytes) {
3052 /* Potential overflow, skip the GIDs and SIDs. */
3054 SIVAL(pdata, 24, 0); /* num_groups */
3055 SIVAL(pdata, 28, 0); /* num_sids */
3056 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3057 SIVAL(pdata, 36, 0); /* reserved */
3059 data_len = 40;
3060 break;
3063 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3064 SIVAL(pdata, 28, conn->server_info->num_sids);
3066 /* We walk the SID list twice, but this call is fairly
3067 * infrequent, and I don't expect that it's performance
3068 * sensitive -- jpeach
3070 for (i = 0, sid_bytes = 0;
3071 i < conn->server_info->ptok->num_sids; ++i) {
3072 sid_bytes += ndr_size_dom_sid(
3073 &conn->server_info->ptok->user_sids[i],
3077 /* SID list byte count */
3078 SIVAL(pdata, 32, sid_bytes);
3080 /* 4 bytes pad/reserved - must be zero */
3081 SIVAL(pdata, 36, 0);
3082 data_len = 40;
3084 /* GID list */
3085 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3086 SBIG_UINT(pdata, data_len,
3087 (uint64_t)conn->server_info->utok.groups[i]);
3088 data_len += 8;
3091 /* SID list */
3092 for (i = 0;
3093 i < conn->server_info->ptok->num_sids; ++i) {
3094 int sid_len = ndr_size_dom_sid(
3095 &conn->server_info->ptok->user_sids[i],
3098 sid_linearize(pdata + data_len, sid_len,
3099 &conn->server_info->ptok->user_sids[i]);
3100 data_len += sid_len;
3103 break;
3106 case SMB_MAC_QUERY_FS_INFO:
3108 * Thursby MAC extension... ONLY on NTFS filesystems
3109 * once we do streams then we don't need this
3111 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3112 data_len = 88;
3113 SIVAL(pdata,84,0x100); /* Don't support mac... */
3114 break;
3116 /* drop through */
3117 default:
3118 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3119 return;
3123 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3124 max_data_bytes);
3126 DEBUG( 4, ( "%s info_level = %d\n",
3127 smb_fn_name(req->cmd), info_level) );
3129 return;
3132 /****************************************************************************
3133 Reply to a TRANS2_SETFSINFO (set filesystem info).
3134 ****************************************************************************/
3136 static void call_trans2setfsinfo(connection_struct *conn,
3137 struct smb_request *req,
3138 char **pparams, int total_params,
3139 char **ppdata, int total_data,
3140 unsigned int max_data_bytes)
3142 char *pdata = *ppdata;
3143 char *params = *pparams;
3144 uint16 info_level;
3146 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3148 /* */
3149 if (total_params < 4) {
3150 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3151 total_params));
3152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3153 return;
3156 info_level = SVAL(params,2);
3158 if (IS_IPC(conn)) {
3159 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3160 info_level != SMB_SET_CIFS_UNIX_INFO) {
3161 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3162 "info level (0x%x) on IPC$.\n",
3163 (unsigned int)info_level));
3164 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3165 return;
3169 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3170 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3171 DEBUG(0,("call_trans2setfsinfo: encryption required "
3172 "and info level 0x%x sent.\n",
3173 (unsigned int)info_level));
3174 exit_server_cleanly("encryption required "
3175 "on connection");
3176 return;
3180 switch(info_level) {
3181 case SMB_SET_CIFS_UNIX_INFO:
3183 uint16 client_unix_major;
3184 uint16 client_unix_minor;
3185 uint32 client_unix_cap_low;
3186 uint32 client_unix_cap_high;
3188 if (!lp_unix_extensions()) {
3189 reply_nterror(req,
3190 NT_STATUS_INVALID_LEVEL);
3191 return;
3194 /* There should be 12 bytes of capabilities set. */
3195 if (total_data < 8) {
3196 reply_nterror(
3197 req,
3198 NT_STATUS_INVALID_PARAMETER);
3199 return;
3201 client_unix_major = SVAL(pdata,0);
3202 client_unix_minor = SVAL(pdata,2);
3203 client_unix_cap_low = IVAL(pdata,4);
3204 client_unix_cap_high = IVAL(pdata,8);
3205 /* Just print these values for now. */
3206 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3207 cap_low = 0x%x, cap_high = 0x%x\n",
3208 (unsigned int)client_unix_major,
3209 (unsigned int)client_unix_minor,
3210 (unsigned int)client_unix_cap_low,
3211 (unsigned int)client_unix_cap_high ));
3213 /* Here is where we must switch to posix pathname processing... */
3214 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3215 lp_set_posix_pathnames();
3216 mangle_change_to_posix();
3219 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3220 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3221 /* Client that knows how to do posix locks,
3222 * but not posix open/mkdir operations. Set a
3223 * default type for read/write checks. */
3225 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3228 break;
3231 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3233 NTSTATUS status;
3234 size_t param_len = 0;
3235 size_t data_len = total_data;
3237 if (!lp_unix_extensions()) {
3238 reply_nterror(
3239 req,
3240 NT_STATUS_INVALID_LEVEL);
3241 return;
3244 if (lp_smb_encrypt(SNUM(conn)) == false) {
3245 reply_nterror(
3246 req,
3247 NT_STATUS_NOT_SUPPORTED);
3248 return;
3251 DEBUG( 4,("call_trans2setfsinfo: "
3252 "request transport encryption.\n"));
3254 status = srv_request_encryption_setup(conn,
3255 (unsigned char **)ppdata,
3256 &data_len,
3257 (unsigned char **)pparams,
3258 &param_len);
3260 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3261 !NT_STATUS_IS_OK(status)) {
3262 reply_nterror(req, status);
3263 return;
3266 send_trans2_replies(conn, req,
3267 *pparams,
3268 param_len,
3269 *ppdata,
3270 data_len,
3271 max_data_bytes);
3273 if (NT_STATUS_IS_OK(status)) {
3274 /* Server-side transport
3275 * encryption is now *on*. */
3276 status = srv_encryption_start(conn);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 exit_server_cleanly(
3279 "Failure in setting "
3280 "up encrypted transport");
3283 return;
3286 case SMB_FS_QUOTA_INFORMATION:
3288 files_struct *fsp = NULL;
3289 SMB_NTQUOTA_STRUCT quotas;
3291 ZERO_STRUCT(quotas);
3293 /* access check */
3294 if ((conn->server_info->utok.uid != 0)
3295 ||!CAN_WRITE(conn)) {
3296 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3297 lp_servicename(SNUM(conn)),
3298 conn->server_info->unix_name));
3299 reply_doserror(req, ERRSRV, ERRaccess);
3300 return;
3303 /* note: normaly there're 48 bytes,
3304 * but we didn't use the last 6 bytes for now
3305 * --metze
3307 fsp = file_fsp(req, SVAL(params,0));
3309 if (!check_fsp_ntquota_handle(conn, req,
3310 fsp)) {
3311 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3312 reply_nterror(
3313 req, NT_STATUS_INVALID_HANDLE);
3314 return;
3317 if (total_data < 42) {
3318 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3319 total_data));
3320 reply_nterror(
3321 req,
3322 NT_STATUS_INVALID_PARAMETER);
3323 return;
3326 /* unknown_1 24 NULL bytes in pdata*/
3328 /* the soft quotas 8 bytes (uint64_t)*/
3329 quotas.softlim = (uint64_t)IVAL(pdata,24);
3330 #ifdef LARGE_SMB_OFF_T
3331 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3332 #else /* LARGE_SMB_OFF_T */
3333 if ((IVAL(pdata,28) != 0)&&
3334 ((quotas.softlim != 0xFFFFFFFF)||
3335 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3336 /* more than 32 bits? */
3337 reply_nterror(
3338 req,
3339 NT_STATUS_INVALID_PARAMETER);
3340 return;
3342 #endif /* LARGE_SMB_OFF_T */
3344 /* the hard quotas 8 bytes (uint64_t)*/
3345 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3346 #ifdef LARGE_SMB_OFF_T
3347 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3348 #else /* LARGE_SMB_OFF_T */
3349 if ((IVAL(pdata,36) != 0)&&
3350 ((quotas.hardlim != 0xFFFFFFFF)||
3351 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3352 /* more than 32 bits? */
3353 reply_nterror(
3354 req,
3355 NT_STATUS_INVALID_PARAMETER);
3356 return;
3358 #endif /* LARGE_SMB_OFF_T */
3360 /* quota_flags 2 bytes **/
3361 quotas.qflags = SVAL(pdata,40);
3363 /* unknown_2 6 NULL bytes follow*/
3365 /* now set the quotas */
3366 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3367 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3368 reply_doserror(req, ERRSRV, ERRerror);
3369 return;
3372 break;
3374 default:
3375 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3376 info_level));
3377 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3378 return;
3379 break;
3383 * sending this reply works fine,
3384 * but I'm not sure it's the same
3385 * like windows do...
3386 * --metze
3388 reply_outbuf(req, 10, 0);
3391 #if defined(HAVE_POSIX_ACLS)
3392 /****************************************************************************
3393 Utility function to count the number of entries in a POSIX acl.
3394 ****************************************************************************/
3396 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3398 unsigned int ace_count = 0;
3399 int entry_id = SMB_ACL_FIRST_ENTRY;
3400 SMB_ACL_ENTRY_T entry;
3402 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3403 /* get_next... */
3404 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3405 entry_id = SMB_ACL_NEXT_ENTRY;
3407 ace_count++;
3409 return ace_count;
3412 /****************************************************************************
3413 Utility function to marshall a POSIX acl into wire format.
3414 ****************************************************************************/
3416 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3418 int entry_id = SMB_ACL_FIRST_ENTRY;
3419 SMB_ACL_ENTRY_T entry;
3421 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3422 SMB_ACL_TAG_T tagtype;
3423 SMB_ACL_PERMSET_T permset;
3424 unsigned char perms = 0;
3425 unsigned int own_grp;
3427 /* get_next... */
3428 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3429 entry_id = SMB_ACL_NEXT_ENTRY;
3432 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3433 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3434 return False;
3437 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3438 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3439 return False;
3442 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3443 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3446 SCVAL(pdata,1,perms);
3448 switch (tagtype) {
3449 case SMB_ACL_USER_OBJ:
3450 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3451 own_grp = (unsigned int)pst->st_uid;
3452 SIVAL(pdata,2,own_grp);
3453 SIVAL(pdata,6,0);
3454 break;
3455 case SMB_ACL_USER:
3457 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3458 if (!puid) {
3459 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3460 return False;
3462 own_grp = (unsigned int)*puid;
3463 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3464 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3465 SIVAL(pdata,2,own_grp);
3466 SIVAL(pdata,6,0);
3467 break;
3469 case SMB_ACL_GROUP_OBJ:
3470 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3471 own_grp = (unsigned int)pst->st_gid;
3472 SIVAL(pdata,2,own_grp);
3473 SIVAL(pdata,6,0);
3474 break;
3475 case SMB_ACL_GROUP:
3477 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3478 if (!pgid) {
3479 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3480 return False;
3482 own_grp = (unsigned int)*pgid;
3483 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3484 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3485 SIVAL(pdata,2,own_grp);
3486 SIVAL(pdata,6,0);
3487 break;
3489 case SMB_ACL_MASK:
3490 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3491 SIVAL(pdata,2,0xFFFFFFFF);
3492 SIVAL(pdata,6,0xFFFFFFFF);
3493 break;
3494 case SMB_ACL_OTHER:
3495 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3496 SIVAL(pdata,2,0xFFFFFFFF);
3497 SIVAL(pdata,6,0xFFFFFFFF);
3498 break;
3499 default:
3500 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3501 return False;
3503 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3506 return True;
3508 #endif
3510 /****************************************************************************
3511 Store the FILE_UNIX_BASIC info.
3512 ****************************************************************************/
3514 static char *store_file_unix_basic(connection_struct *conn,
3515 char *pdata,
3516 files_struct *fsp,
3517 const SMB_STRUCT_STAT *psbuf)
3519 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3520 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3522 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3523 pdata += 8;
3525 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3526 pdata += 8;
3528 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3529 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3530 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3531 pdata += 24;
3533 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3534 SIVAL(pdata,4,0);
3535 pdata += 8;
3537 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3538 SIVAL(pdata,4,0);
3539 pdata += 8;
3541 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3542 pdata += 4;
3544 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3545 SIVAL(pdata,4,0);
3546 pdata += 8;
3548 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3549 SIVAL(pdata,4,0);
3550 pdata += 8;
3552 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3553 pdata += 8;
3555 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3556 SIVAL(pdata,4,0);
3557 pdata += 8;
3559 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3560 SIVAL(pdata,4,0);
3561 pdata += 8;
3563 return pdata;
3566 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3567 * the chflags(2) (or equivalent) flags.
3569 * XXX: this really should be behind the VFS interface. To do this, we would
3570 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3571 * Each VFS module could then implement its own mapping as appropriate for the
3572 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3574 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3575 info2_flags_map[] =
3577 #ifdef UF_NODUMP
3578 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3579 #endif
3581 #ifdef UF_IMMUTABLE
3582 { UF_IMMUTABLE, EXT_IMMUTABLE },
3583 #endif
3585 #ifdef UF_APPEND
3586 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3587 #endif
3589 #ifdef UF_HIDDEN
3590 { UF_HIDDEN, EXT_HIDDEN },
3591 #endif
3593 /* Do not remove. We need to guarantee that this array has at least one
3594 * entry to build on HP-UX.
3596 { 0, 0 }
3600 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3601 uint32 *smb_fflags, uint32 *smb_fmask)
3603 #ifdef HAVE_STAT_ST_FLAGS
3604 int i;
3606 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3607 *smb_fmask |= info2_flags_map[i].smb_fflag;
3608 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3609 *smb_fflags |= info2_flags_map[i].smb_fflag;
3612 #endif /* HAVE_STAT_ST_FLAGS */
3615 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3616 const uint32 smb_fflags,
3617 const uint32 smb_fmask,
3618 int *stat_fflags)
3620 #ifdef HAVE_STAT_ST_FLAGS
3621 uint32 max_fmask = 0;
3622 int i;
3624 *stat_fflags = psbuf->st_flags;
3626 /* For each flags requested in smb_fmask, check the state of the
3627 * corresponding flag in smb_fflags and set or clear the matching
3628 * stat flag.
3631 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3632 max_fmask |= info2_flags_map[i].smb_fflag;
3633 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3634 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3635 *stat_fflags |= info2_flags_map[i].stat_fflag;
3636 } else {
3637 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3642 /* If smb_fmask is asking to set any bits that are not supported by
3643 * our flag mappings, we should fail.
3645 if ((smb_fmask & max_fmask) != smb_fmask) {
3646 return False;
3649 return True;
3650 #else
3651 return False;
3652 #endif /* HAVE_STAT_ST_FLAGS */
3656 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3657 * of file flags and birth (create) time.
3659 static char *store_file_unix_basic_info2(connection_struct *conn,
3660 char *pdata,
3661 files_struct *fsp,
3662 const SMB_STRUCT_STAT *psbuf)
3664 uint32 file_flags = 0;
3665 uint32 flags_mask = 0;
3667 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3669 /* Create (birth) time 64 bit */
3670 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3671 pdata += 8;
3673 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3674 SIVAL(pdata, 0, file_flags); /* flags */
3675 SIVAL(pdata, 4, flags_mask); /* mask */
3676 pdata += 8;
3678 return pdata;
3681 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3682 const struct stream_struct *streams,
3683 char *data,
3684 unsigned int max_data_bytes,
3685 unsigned int *data_size)
3687 unsigned int i;
3688 unsigned int ofs = 0;
3690 for (i=0; i<num_streams; i++) {
3691 unsigned int next_offset;
3692 size_t namelen;
3693 smb_ucs2_t *namebuf;
3695 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3696 streams[i].name, &namelen) ||
3697 namelen <= 2)
3699 return NT_STATUS_INVALID_PARAMETER;
3703 * name_buf is now null-terminated, we need to marshall as not
3704 * terminated
3707 namelen -= 2;
3709 if (ofs + 24 + namelen > max_data_bytes) {
3710 TALLOC_FREE(namebuf);
3711 return NT_STATUS_BUFFER_TOO_SMALL;
3714 SIVAL(data, ofs+4, namelen);
3715 SOFF_T(data, ofs+8, streams[i].size);
3716 SOFF_T(data, ofs+16, streams[i].alloc_size);
3717 memcpy(data+ofs+24, namebuf, namelen);
3718 TALLOC_FREE(namebuf);
3720 next_offset = ofs + 24 + namelen;
3722 if (i == num_streams-1) {
3723 SIVAL(data, ofs, 0);
3725 else {
3726 unsigned int align = ndr_align_size(next_offset, 8);
3728 if (next_offset + align > max_data_bytes) {
3729 return NT_STATUS_BUFFER_TOO_SMALL;
3732 memset(data+next_offset, 0, align);
3733 next_offset += align;
3735 SIVAL(data, ofs, next_offset - ofs);
3736 ofs = next_offset;
3739 ofs = next_offset;
3742 *data_size = ofs;
3744 return NT_STATUS_OK;
3747 /****************************************************************************
3748 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3749 ****************************************************************************/
3751 static void call_trans2qpipeinfo(connection_struct *conn,
3752 struct smb_request *req,
3753 unsigned int tran_call,
3754 char **pparams, int total_params,
3755 char **ppdata, int total_data,
3756 unsigned int max_data_bytes)
3758 char *params = *pparams;
3759 char *pdata = *ppdata;
3760 unsigned int data_size = 0;
3761 unsigned int param_size = 2;
3762 uint16 info_level;
3763 files_struct *fsp;
3765 if (!params) {
3766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767 return;
3770 if (total_params < 4) {
3771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3772 return;
3775 fsp = file_fsp(req, SVAL(params,0));
3776 if (!fsp_is_np(fsp)) {
3777 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3778 return;
3781 info_level = SVAL(params,2);
3783 *pparams = (char *)SMB_REALLOC(*pparams,2);
3784 if (*pparams == NULL) {
3785 reply_nterror(req, NT_STATUS_NO_MEMORY);
3786 return;
3788 params = *pparams;
3789 SSVAL(params,0,0);
3790 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3791 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3792 if (*ppdata == NULL ) {
3793 reply_nterror(req, NT_STATUS_NO_MEMORY);
3794 return;
3796 pdata = *ppdata;
3798 switch (info_level) {
3799 case SMB_FILE_STANDARD_INFORMATION:
3800 memset(pdata,0,24);
3801 SOFF_T(pdata,0,4096LL);
3802 SIVAL(pdata,16,1);
3803 SIVAL(pdata,20,1);
3804 data_size = 24;
3805 break;
3807 default:
3808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3809 return;
3812 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3813 max_data_bytes);
3815 return;
3818 /****************************************************************************
3819 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3820 file name or file id).
3821 ****************************************************************************/
3823 static void call_trans2qfilepathinfo(connection_struct *conn,
3824 struct smb_request *req,
3825 unsigned int tran_call,
3826 char **pparams, int total_params,
3827 char **ppdata, int total_data,
3828 unsigned int max_data_bytes)
3830 char *params = *pparams;
3831 char *pdata = *ppdata;
3832 char *dstart, *dend;
3833 uint16 info_level;
3834 int mode=0;
3835 int nlink;
3836 SMB_OFF_T file_size=0;
3837 uint64_t allocation_size=0;
3838 unsigned int data_size = 0;
3839 unsigned int param_size = 2;
3840 SMB_STRUCT_STAT sbuf;
3841 char *dos_fname = NULL;
3842 char *fname = NULL;
3843 char *fullpathname;
3844 char *base_name;
3845 char *p;
3846 SMB_OFF_T pos = 0;
3847 bool delete_pending = False;
3848 int len;
3849 time_t create_time, mtime, atime;
3850 struct timespec create_time_ts, mtime_ts, atime_ts;
3851 struct timespec write_time_ts;
3852 files_struct *fsp = NULL;
3853 struct file_id fileid;
3854 struct ea_list *ea_list = NULL;
3855 char *lock_data = NULL;
3856 bool ms_dfs_link = false;
3857 TALLOC_CTX *ctx = talloc_tos();
3859 if (!params) {
3860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3861 return;
3864 ZERO_STRUCT(sbuf);
3865 ZERO_STRUCT(write_time_ts);
3867 if (tran_call == TRANSACT2_QFILEINFO) {
3868 if (total_params < 4) {
3869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3870 return;
3873 if (IS_IPC(conn)) {
3874 call_trans2qpipeinfo(conn, req, tran_call,
3875 pparams, total_params,
3876 ppdata, total_data,
3877 max_data_bytes);
3878 return;
3881 fsp = file_fsp(req, SVAL(params,0));
3882 info_level = SVAL(params,2);
3884 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3886 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3887 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3888 return;
3891 /* Initial check for valid fsp ptr. */
3892 if (!check_fsp_open(conn, req, fsp)) {
3893 return;
3896 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3897 if (!fname) {
3898 reply_nterror(req, NT_STATUS_NO_MEMORY);
3899 return;
3902 if(fsp->fake_file_handle) {
3904 * This is actually for the QUOTA_FAKE_FILE --metze
3907 /* We know this name is ok, it's already passed the checks. */
3909 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3911 * This is actually a QFILEINFO on a directory
3912 * handle (returned from an NT SMB). NT5.0 seems
3913 * to do this call. JRA.
3916 if (INFO_LEVEL_IS_UNIX(info_level)) {
3917 /* Always do lstat for UNIX calls. */
3918 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3919 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3920 reply_unixerror(req,ERRDOS,ERRbadpath);
3921 return;
3923 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3924 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3925 reply_unixerror(req, ERRDOS, ERRbadpath);
3926 return;
3929 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3930 get_file_infos(fileid, &delete_pending, &write_time_ts);
3931 } else {
3933 * Original code - this is an open file.
3935 if (!check_fsp(conn, req, fsp)) {
3936 return;
3939 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3940 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3941 reply_unixerror(req, ERRDOS, ERRbadfid);
3942 return;
3944 pos = fsp->fh->position_information;
3945 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3946 get_file_infos(fileid, &delete_pending, &write_time_ts);
3949 } else {
3950 NTSTATUS status = NT_STATUS_OK;
3952 /* qpathinfo */
3953 if (total_params < 7) {
3954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3955 return;
3958 info_level = SVAL(params,0);
3960 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3962 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3963 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3964 return;
3967 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3968 total_params - 6,
3969 STR_TERMINATE, &status);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 reply_nterror(req, status);
3972 return;
3975 status = resolve_dfspath(ctx,
3976 conn,
3977 req->flags2 & FLAGS2_DFS_PATHNAMES,
3978 fname,
3979 &fname);
3980 if (!NT_STATUS_IS_OK(status)) {
3981 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3982 reply_botherror(req,
3983 NT_STATUS_PATH_NOT_COVERED,
3984 ERRSRV, ERRbadpath);
3986 reply_nterror(req, status);
3987 return;
3990 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 reply_nterror(req, status);
3993 return;
3995 status = check_name(conn, fname);
3996 if (!NT_STATUS_IS_OK(status)) {
3997 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3998 reply_nterror(req, status);
3999 return;
4002 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4003 && is_ntfs_stream_name(fname)) {
4004 char *base;
4005 SMB_STRUCT_STAT bsbuf;
4007 status = split_ntfs_stream_name(talloc_tos(), fname,
4008 &base, NULL);
4009 if (!NT_STATUS_IS_OK(status)) {
4010 DEBUG(10, ("create_file_unixpath: "
4011 "split_ntfs_stream_name failed: %s\n",
4012 nt_errstr(status)));
4013 reply_nterror(req, status);
4014 return;
4017 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4019 if (INFO_LEVEL_IS_UNIX(info_level)) {
4020 /* Always do lstat for UNIX calls. */
4021 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4022 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4023 reply_unixerror(req,ERRDOS,ERRbadpath);
4024 return;
4026 } else {
4027 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4028 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4029 reply_unixerror(req,ERRDOS,ERRbadpath);
4030 return;
4034 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4035 get_file_infos(fileid, &delete_pending, NULL);
4036 if (delete_pending) {
4037 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4038 return;
4042 if (INFO_LEVEL_IS_UNIX(info_level)) {
4043 /* Always do lstat for UNIX calls. */
4044 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4045 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4046 reply_unixerror(req, ERRDOS, ERRbadpath);
4047 return;
4050 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4051 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4053 if (!ms_dfs_link) {
4054 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4055 reply_unixerror(req, ERRDOS, ERRbadpath);
4056 return;
4060 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4061 get_file_infos(fileid, &delete_pending, &write_time_ts);
4062 if (delete_pending) {
4063 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4064 return;
4068 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4069 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4070 return;
4073 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4074 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4076 p = strrchr_m(fname,'/');
4077 if (!p)
4078 base_name = fname;
4079 else
4080 base_name = p+1;
4082 if (ms_dfs_link) {
4083 mode = dos_mode_msdfs(conn,fname,&sbuf);
4084 } else {
4085 mode = dos_mode(conn,fname,&sbuf);
4087 if (!mode)
4088 mode = FILE_ATTRIBUTE_NORMAL;
4090 nlink = sbuf.st_nlink;
4092 if (nlink && (mode&aDIR)) {
4093 nlink = 1;
4096 if ((nlink > 0) && delete_pending) {
4097 nlink -= 1;
4100 fullpathname = fname;
4101 if (!(mode & aDIR))
4102 file_size = get_file_size(sbuf);
4104 /* Pull out any data sent here before we realloc. */
4105 switch (info_level) {
4106 case SMB_INFO_QUERY_EAS_FROM_LIST:
4108 /* Pull any EA list from the data portion. */
4109 uint32 ea_size;
4111 if (total_data < 4) {
4112 reply_nterror(
4113 req, NT_STATUS_INVALID_PARAMETER);
4114 return;
4116 ea_size = IVAL(pdata,0);
4118 if (total_data > 0 && ea_size != total_data) {
4119 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4120 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4121 reply_nterror(
4122 req, NT_STATUS_INVALID_PARAMETER);
4123 return;
4126 if (!lp_ea_support(SNUM(conn))) {
4127 reply_doserror(req, ERRDOS,
4128 ERReasnotsupported);
4129 return;
4132 /* Pull out the list of names. */
4133 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4134 if (!ea_list) {
4135 reply_nterror(
4136 req, NT_STATUS_INVALID_PARAMETER);
4137 return;
4139 break;
4142 case SMB_QUERY_POSIX_LOCK:
4144 if (fsp == NULL || fsp->fh->fd == -1) {
4145 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4146 return;
4149 if (total_data != POSIX_LOCK_DATA_SIZE) {
4150 reply_nterror(
4151 req, NT_STATUS_INVALID_PARAMETER);
4152 return;
4155 /* Copy the lock range data. */
4156 lock_data = (char *)TALLOC_MEMDUP(
4157 ctx, pdata, total_data);
4158 if (!lock_data) {
4159 reply_nterror(req, NT_STATUS_NO_MEMORY);
4160 return;
4163 default:
4164 break;
4167 *pparams = (char *)SMB_REALLOC(*pparams,2);
4168 if (*pparams == NULL) {
4169 reply_nterror(req, NT_STATUS_NO_MEMORY);
4170 return;
4172 params = *pparams;
4173 SSVAL(params,0,0);
4174 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4175 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4176 if (*ppdata == NULL ) {
4177 reply_nterror(req, NT_STATUS_NO_MEMORY);
4178 return;
4180 pdata = *ppdata;
4181 dstart = pdata;
4182 dend = dstart + data_size - 1;
4184 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4185 mtime_ts = get_mtimespec(&sbuf);
4186 atime_ts = get_atimespec(&sbuf);
4188 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4190 if (!fsp) {
4191 /* Do we have this path open ? */
4192 files_struct *fsp1;
4193 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4194 fsp1 = file_find_di_first(fileid);
4195 if (fsp1 && fsp1->initial_allocation_size) {
4196 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4200 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4201 mtime_ts = write_time_ts;
4204 if (lp_dos_filetime_resolution(SNUM(conn))) {
4205 dos_filetime_timespec(&create_time_ts);
4206 dos_filetime_timespec(&mtime_ts);
4207 dos_filetime_timespec(&atime_ts);
4210 create_time = convert_timespec_to_time_t(create_time_ts);
4211 mtime = convert_timespec_to_time_t(mtime_ts);
4212 atime = convert_timespec_to_time_t(atime_ts);
4214 /* NT expects the name to be in an exact form of the *full*
4215 filename. See the trans2 torture test */
4216 if (ISDOT(base_name)) {
4217 dos_fname = talloc_strdup(ctx, "\\");
4218 if (!dos_fname) {
4219 reply_nterror(req, NT_STATUS_NO_MEMORY);
4220 return;
4222 } else {
4223 dos_fname = talloc_asprintf(ctx,
4224 "\\%s",
4225 fname);
4226 if (!dos_fname) {
4227 reply_nterror(req, NT_STATUS_NO_MEMORY);
4228 return;
4230 string_replace(dos_fname, '/', '\\');
4233 switch (info_level) {
4234 case SMB_INFO_STANDARD:
4235 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4236 data_size = 22;
4237 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4238 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4239 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4240 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4241 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4242 SSVAL(pdata,l1_attrFile,mode);
4243 break;
4245 case SMB_INFO_QUERY_EA_SIZE:
4247 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4249 data_size = 26;
4250 srv_put_dos_date2(pdata,0,create_time);
4251 srv_put_dos_date2(pdata,4,atime);
4252 srv_put_dos_date2(pdata,8,mtime); /* write time */
4253 SIVAL(pdata,12,(uint32)file_size);
4254 SIVAL(pdata,16,(uint32)allocation_size);
4255 SSVAL(pdata,20,mode);
4256 SIVAL(pdata,22,ea_size);
4257 break;
4260 case SMB_INFO_IS_NAME_VALID:
4261 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4262 if (tran_call == TRANSACT2_QFILEINFO) {
4263 /* os/2 needs this ? really ?*/
4264 reply_doserror(req, ERRDOS, ERRbadfunc);
4265 return;
4267 data_size = 0;
4268 param_size = 0;
4269 break;
4271 case SMB_INFO_QUERY_EAS_FROM_LIST:
4273 size_t total_ea_len = 0;
4274 struct ea_list *ea_file_list = NULL;
4276 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4278 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4279 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4281 if (!ea_list || (total_ea_len > data_size)) {
4282 data_size = 4;
4283 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4284 break;
4287 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4288 break;
4291 case SMB_INFO_QUERY_ALL_EAS:
4293 /* We have data_size bytes to put EA's into. */
4294 size_t total_ea_len = 0;
4296 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4298 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4299 if (!ea_list || (total_ea_len > data_size)) {
4300 data_size = 4;
4301 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4302 break;
4305 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4306 break;
4309 case SMB_FILE_BASIC_INFORMATION:
4310 case SMB_QUERY_FILE_BASIC_INFO:
4312 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4313 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4314 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4315 } else {
4316 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4317 data_size = 40;
4318 SIVAL(pdata,36,0);
4320 put_long_date_timespec(pdata,create_time_ts);
4321 put_long_date_timespec(pdata+8,atime_ts);
4322 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4323 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4324 SIVAL(pdata,32,mode);
4326 DEBUG(5,("SMB_QFBI - "));
4327 DEBUG(5,("create: %s ", ctime(&create_time)));
4328 DEBUG(5,("access: %s ", ctime(&atime)));
4329 DEBUG(5,("write: %s ", ctime(&mtime)));
4330 DEBUG(5,("change: %s ", ctime(&mtime)));
4331 DEBUG(5,("mode: %x\n", mode));
4332 break;
4334 case SMB_FILE_STANDARD_INFORMATION:
4335 case SMB_QUERY_FILE_STANDARD_INFO:
4337 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4338 data_size = 24;
4339 SOFF_T(pdata,0,allocation_size);
4340 SOFF_T(pdata,8,file_size);
4341 SIVAL(pdata,16,nlink);
4342 SCVAL(pdata,20,delete_pending?1:0);
4343 SCVAL(pdata,21,(mode&aDIR)?1:0);
4344 SSVAL(pdata,22,0); /* Padding. */
4345 break;
4347 case SMB_FILE_EA_INFORMATION:
4348 case SMB_QUERY_FILE_EA_INFO:
4350 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4351 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4352 data_size = 4;
4353 SIVAL(pdata,0,ea_size);
4354 break;
4357 /* Get the 8.3 name - used if NT SMB was negotiated. */
4358 case SMB_QUERY_FILE_ALT_NAME_INFO:
4359 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4361 char mangled_name[13];
4362 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4363 if (!name_to_8_3(base_name,mangled_name,
4364 True,conn->params)) {
4365 reply_nterror(
4366 req,
4367 NT_STATUS_NO_MEMORY);
4369 len = srvstr_push(dstart, req->flags2,
4370 pdata+4, mangled_name,
4371 PTR_DIFF(dend, pdata+4),
4372 STR_UNICODE);
4373 data_size = 4 + len;
4374 SIVAL(pdata,0,len);
4375 break;
4378 case SMB_QUERY_FILE_NAME_INFO:
4380 this must be *exactly* right for ACLs on mapped drives to work
4382 len = srvstr_push(dstart, req->flags2,
4383 pdata+4, dos_fname,
4384 PTR_DIFF(dend, pdata+4),
4385 STR_UNICODE);
4386 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4387 data_size = 4 + len;
4388 SIVAL(pdata,0,len);
4389 break;
4391 case SMB_FILE_ALLOCATION_INFORMATION:
4392 case SMB_QUERY_FILE_ALLOCATION_INFO:
4393 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4394 data_size = 8;
4395 SOFF_T(pdata,0,allocation_size);
4396 break;
4398 case SMB_FILE_END_OF_FILE_INFORMATION:
4399 case SMB_QUERY_FILE_END_OF_FILEINFO:
4400 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4401 data_size = 8;
4402 SOFF_T(pdata,0,file_size);
4403 break;
4405 case SMB_QUERY_FILE_ALL_INFO:
4406 case SMB_FILE_ALL_INFORMATION:
4408 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4409 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4410 put_long_date_timespec(pdata,create_time_ts);
4411 put_long_date_timespec(pdata+8,atime_ts);
4412 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4413 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4414 SIVAL(pdata,32,mode);
4415 SIVAL(pdata,36,0); /* padding. */
4416 pdata += 40;
4417 SOFF_T(pdata,0,allocation_size);
4418 SOFF_T(pdata,8,file_size);
4419 SIVAL(pdata,16,nlink);
4420 SCVAL(pdata,20,delete_pending);
4421 SCVAL(pdata,21,(mode&aDIR)?1:0);
4422 SSVAL(pdata,22,0);
4423 pdata += 24;
4424 SIVAL(pdata,0,ea_size);
4425 pdata += 4; /* EA info */
4426 len = srvstr_push(dstart, req->flags2,
4427 pdata+4, dos_fname,
4428 PTR_DIFF(dend, pdata+4),
4429 STR_UNICODE);
4430 SIVAL(pdata,0,len);
4431 pdata += 4 + len;
4432 data_size = PTR_DIFF(pdata,(*ppdata));
4433 break;
4435 case SMB_FILE_INTERNAL_INFORMATION:
4436 /* This should be an index number - looks like
4437 dev/ino to me :-)
4439 I think this causes us to fail the IFSKIT
4440 BasicFileInformationTest. -tpot */
4442 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4443 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4444 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4445 data_size = 8;
4446 break;
4448 case SMB_FILE_ACCESS_INFORMATION:
4449 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4450 if (fsp) {
4451 SIVAL(pdata,0,fsp->access_mask);
4452 } else {
4453 /* GENERIC_EXECUTE mapping from Windows */
4454 SIVAL(pdata,0,0x12019F);
4456 data_size = 4;
4457 break;
4459 case SMB_FILE_NAME_INFORMATION:
4460 /* Pathname with leading '\'. */
4462 size_t byte_len;
4463 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4465 SIVAL(pdata,0,byte_len);
4466 data_size = 4 + byte_len;
4467 break;
4470 case SMB_FILE_DISPOSITION_INFORMATION:
4471 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4472 data_size = 1;
4473 SCVAL(pdata,0,delete_pending);
4474 break;
4476 case SMB_FILE_POSITION_INFORMATION:
4477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4478 data_size = 8;
4479 SOFF_T(pdata,0,pos);
4480 break;
4482 case SMB_FILE_MODE_INFORMATION:
4483 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4484 SIVAL(pdata,0,mode);
4485 data_size = 4;
4486 break;
4488 case SMB_FILE_ALIGNMENT_INFORMATION:
4489 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4490 SIVAL(pdata,0,0); /* No alignment needed. */
4491 data_size = 4;
4492 break;
4495 * NT4 server just returns "invalid query" to this - if we try
4496 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4497 * want this. JRA.
4499 /* The first statement above is false - verified using Thursby
4500 * client against NT4 -- gcolley.
4502 case SMB_QUERY_FILE_STREAM_INFO:
4503 case SMB_FILE_STREAM_INFORMATION: {
4504 unsigned int num_streams;
4505 struct stream_struct *streams;
4506 NTSTATUS status;
4508 DEBUG(10,("call_trans2qfilepathinfo: "
4509 "SMB_FILE_STREAM_INFORMATION\n"));
4511 status = SMB_VFS_STREAMINFO(
4512 conn, fsp, fname, talloc_tos(),
4513 &num_streams, &streams);
4515 if (!NT_STATUS_IS_OK(status)) {
4516 DEBUG(10, ("could not get stream info: %s\n",
4517 nt_errstr(status)));
4518 reply_nterror(req, status);
4519 return;
4522 status = marshall_stream_info(num_streams, streams,
4523 pdata, max_data_bytes,
4524 &data_size);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 DEBUG(10, ("marshall_stream_info failed: %s\n",
4528 nt_errstr(status)));
4529 reply_nterror(req, status);
4530 return;
4533 TALLOC_FREE(streams);
4535 break;
4537 case SMB_QUERY_COMPRESSION_INFO:
4538 case SMB_FILE_COMPRESSION_INFORMATION:
4539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4540 SOFF_T(pdata,0,file_size);
4541 SIVAL(pdata,8,0); /* ??? */
4542 SIVAL(pdata,12,0); /* ??? */
4543 data_size = 16;
4544 break;
4546 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4547 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4548 put_long_date_timespec(pdata,create_time_ts);
4549 put_long_date_timespec(pdata+8,atime_ts);
4550 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4551 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4552 SOFF_T(pdata,32,allocation_size);
4553 SOFF_T(pdata,40,file_size);
4554 SIVAL(pdata,48,mode);
4555 SIVAL(pdata,52,0); /* ??? */
4556 data_size = 56;
4557 break;
4559 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4561 SIVAL(pdata,0,mode);
4562 SIVAL(pdata,4,0);
4563 data_size = 8;
4564 break;
4567 * CIFS UNIX Extensions.
4570 case SMB_QUERY_FILE_UNIX_BASIC:
4572 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4573 data_size = PTR_DIFF(pdata,(*ppdata));
4576 int i;
4577 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4579 for (i=0; i<100; i++)
4580 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4581 DEBUG(4,("\n"));
4584 break;
4586 case SMB_QUERY_FILE_UNIX_INFO2:
4588 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4589 data_size = PTR_DIFF(pdata,(*ppdata));
4592 int i;
4593 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4595 for (i=0; i<100; i++)
4596 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4597 DEBUG(4,("\n"));
4600 break;
4602 case SMB_QUERY_FILE_UNIX_LINK:
4604 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4606 if (!buffer) {
4607 reply_nterror(req, NT_STATUS_NO_MEMORY);
4608 return;
4611 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4612 #ifdef S_ISLNK
4613 if(!S_ISLNK(sbuf.st_mode)) {
4614 reply_unixerror(req, ERRSRV,
4615 ERRbadlink);
4616 return;
4618 #else
4619 reply_unixerror(req, ERRDOS, ERRbadlink);
4620 return;
4621 #endif
4622 len = SMB_VFS_READLINK(conn,fullpathname,
4623 buffer, PATH_MAX);
4624 if (len == -1) {
4625 reply_unixerror(req, ERRDOS,
4626 ERRnoaccess);
4627 return;
4629 buffer[len] = 0;
4630 len = srvstr_push(dstart, req->flags2,
4631 pdata, buffer,
4632 PTR_DIFF(dend, pdata),
4633 STR_TERMINATE);
4634 pdata += len;
4635 data_size = PTR_DIFF(pdata,(*ppdata));
4637 break;
4640 #if defined(HAVE_POSIX_ACLS)
4641 case SMB_QUERY_POSIX_ACL:
4643 SMB_ACL_T file_acl = NULL;
4644 SMB_ACL_T def_acl = NULL;
4645 uint16 num_file_acls = 0;
4646 uint16 num_def_acls = 0;
4648 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4649 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4650 } else {
4651 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4654 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4655 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4656 fname ));
4657 reply_nterror(
4658 req,
4659 NT_STATUS_NOT_IMPLEMENTED);
4660 return;
4663 if (S_ISDIR(sbuf.st_mode)) {
4664 if (fsp && fsp->is_directory) {
4665 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4666 } else {
4667 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4669 def_acl = free_empty_sys_acl(conn, def_acl);
4672 num_file_acls = count_acl_entries(conn, file_acl);
4673 num_def_acls = count_acl_entries(conn, def_acl);
4675 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4676 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4677 data_size,
4678 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4679 SMB_POSIX_ACL_HEADER_SIZE) ));
4680 if (file_acl) {
4681 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4683 if (def_acl) {
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4686 reply_nterror(
4687 req,
4688 NT_STATUS_BUFFER_TOO_SMALL);
4689 return;
4692 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4693 SSVAL(pdata,2,num_file_acls);
4694 SSVAL(pdata,4,num_def_acls);
4695 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4696 if (file_acl) {
4697 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4699 if (def_acl) {
4700 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4702 reply_nterror(
4703 req, NT_STATUS_INTERNAL_ERROR);
4704 return;
4706 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4707 if (file_acl) {
4708 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4710 if (def_acl) {
4711 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4713 reply_nterror(
4714 req,
4715 NT_STATUS_INTERNAL_ERROR);
4716 return;
4719 if (file_acl) {
4720 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4722 if (def_acl) {
4723 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4725 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4726 break;
4728 #endif
4731 case SMB_QUERY_POSIX_LOCK:
4733 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4734 uint64_t count;
4735 uint64_t offset;
4736 uint32 lock_pid;
4737 enum brl_type lock_type;
4739 if (total_data != POSIX_LOCK_DATA_SIZE) {
4740 reply_nterror(
4741 req, NT_STATUS_INVALID_PARAMETER);
4742 return;
4745 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4746 case POSIX_LOCK_TYPE_READ:
4747 lock_type = READ_LOCK;
4748 break;
4749 case POSIX_LOCK_TYPE_WRITE:
4750 lock_type = WRITE_LOCK;
4751 break;
4752 case POSIX_LOCK_TYPE_UNLOCK:
4753 default:
4754 /* There's no point in asking for an unlock... */
4755 reply_nterror(
4756 req,
4757 NT_STATUS_INVALID_PARAMETER);
4758 return;
4761 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4762 #if defined(HAVE_LONGLONG)
4763 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4764 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4765 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4766 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4767 #else /* HAVE_LONGLONG */
4768 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4769 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4770 #endif /* HAVE_LONGLONG */
4772 status = query_lock(fsp,
4773 &lock_pid,
4774 &count,
4775 &offset,
4776 &lock_type,
4777 POSIX_LOCK);
4779 if (ERROR_WAS_LOCK_DENIED(status)) {
4780 /* Here we need to report who has it locked... */
4781 data_size = POSIX_LOCK_DATA_SIZE;
4783 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4784 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4785 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4786 #if defined(HAVE_LONGLONG)
4787 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4788 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4789 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4790 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4791 #else /* HAVE_LONGLONG */
4792 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4793 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4794 #endif /* HAVE_LONGLONG */
4796 } else if (NT_STATUS_IS_OK(status)) {
4797 /* For success we just return a copy of what we sent
4798 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4799 data_size = POSIX_LOCK_DATA_SIZE;
4800 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4801 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4802 } else {
4803 reply_nterror(req, status);
4804 return;
4806 break;
4809 default:
4810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4811 return;
4814 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4815 max_data_bytes);
4817 return;
4820 /****************************************************************************
4821 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4822 code.
4823 ****************************************************************************/
4825 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4826 connection_struct *conn,
4827 const char *oldname_in,
4828 const char *newname_in)
4830 SMB_STRUCT_STAT sbuf1, sbuf2;
4831 char *last_component_oldname = NULL;
4832 char *last_component_newname = NULL;
4833 char *oldname = NULL;
4834 char *newname = NULL;
4835 NTSTATUS status = NT_STATUS_OK;
4837 ZERO_STRUCT(sbuf1);
4838 ZERO_STRUCT(sbuf2);
4840 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4841 &last_component_oldname, &sbuf1);
4842 if (!NT_STATUS_IS_OK(status)) {
4843 return status;
4846 status = check_name(conn, oldname);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 return status;
4851 /* source must already exist. */
4852 if (!VALID_STAT(sbuf1)) {
4853 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4856 status = unix_convert(ctx, conn, newname_in, False, &newname,
4857 &last_component_newname, &sbuf2);
4858 if (!NT_STATUS_IS_OK(status)) {
4859 return status;
4862 status = check_name(conn, newname);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 return status;
4867 /* Disallow if newname already exists. */
4868 if (VALID_STAT(sbuf2)) {
4869 return NT_STATUS_OBJECT_NAME_COLLISION;
4872 /* No links from a directory. */
4873 if (S_ISDIR(sbuf1.st_mode)) {
4874 return NT_STATUS_FILE_IS_A_DIRECTORY;
4877 /* Ensure this is within the share. */
4878 status = check_reduced_name(conn, oldname);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 return status;
4883 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4885 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4886 status = map_nt_error_from_unix(errno);
4887 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4888 nt_errstr(status), newname, oldname));
4891 return status;
4894 /****************************************************************************
4895 Deal with setting the time from any of the setfilepathinfo functions.
4896 ****************************************************************************/
4898 NTSTATUS smb_set_file_time(connection_struct *conn,
4899 files_struct *fsp,
4900 const char *fname,
4901 const SMB_STRUCT_STAT *psbuf,
4902 struct timespec ts[2],
4903 bool setting_write_time)
4905 uint32 action =
4906 FILE_NOTIFY_CHANGE_LAST_ACCESS
4907 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4909 if (!VALID_STAT(*psbuf)) {
4910 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4913 /* get some defaults (no modifications) if any info is zero or -1. */
4914 if (null_timespec(ts[0])) {
4915 ts[0] = get_atimespec(psbuf);
4916 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4919 if (null_timespec(ts[1])) {
4920 ts[1] = get_mtimespec(psbuf);
4921 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4924 if (!setting_write_time) {
4925 /* ts[1] comes from change time, not write time. */
4926 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4929 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4930 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4933 * Try and set the times of this file if
4934 * they are different from the current values.
4938 struct timespec mts = get_mtimespec(psbuf);
4939 struct timespec ats = get_atimespec(psbuf);
4940 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4941 return NT_STATUS_OK;
4945 if (setting_write_time) {
4947 * This was a setfileinfo on an open file.
4948 * NT does this a lot. We also need to
4949 * set the time here, as it can be read by
4950 * FindFirst/FindNext and with the patch for bug #2045
4951 * in smbd/fileio.c it ensures that this timestamp is
4952 * kept sticky even after a write. We save the request
4953 * away and will set it on file close and after a write. JRA.
4956 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4957 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4959 if (fsp != NULL) {
4960 if (fsp->base_fsp) {
4961 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4962 } else {
4963 set_sticky_write_time_fsp(fsp, ts[1]);
4965 } else {
4966 set_sticky_write_time_path(conn, fname,
4967 vfs_file_id_from_sbuf(conn, psbuf),
4968 ts[1]);
4972 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4974 if (fsp && fsp->base_fsp) {
4975 fname = fsp->base_fsp->fsp_name;
4978 if(file_ntimes(conn, fname, ts)!=0) {
4979 return map_nt_error_from_unix(errno);
4981 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4983 return NT_STATUS_OK;
4986 /****************************************************************************
4987 Deal with setting the dosmode from any of the setfilepathinfo functions.
4988 ****************************************************************************/
4990 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4991 const char *fname,
4992 SMB_STRUCT_STAT *psbuf,
4993 uint32 dosmode)
4995 if (!VALID_STAT(*psbuf)) {
4996 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4999 if (dosmode) {
5000 if (S_ISDIR(psbuf->st_mode)) {
5001 dosmode |= aDIR;
5002 } else {
5003 dosmode &= ~aDIR;
5007 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5009 /* check the mode isn't different, before changing it */
5010 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5012 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5013 fname, (unsigned int)dosmode ));
5015 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5016 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5017 fname, strerror(errno)));
5018 return map_nt_error_from_unix(errno);
5021 return NT_STATUS_OK;
5024 /****************************************************************************
5025 Deal with setting the size from any of the setfilepathinfo functions.
5026 ****************************************************************************/
5028 static NTSTATUS smb_set_file_size(connection_struct *conn,
5029 struct smb_request *req,
5030 files_struct *fsp,
5031 const char *fname,
5032 SMB_STRUCT_STAT *psbuf,
5033 SMB_OFF_T size)
5035 NTSTATUS status = NT_STATUS_OK;
5036 files_struct *new_fsp = NULL;
5038 if (!VALID_STAT(*psbuf)) {
5039 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5042 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5044 if (size == get_file_size(*psbuf)) {
5045 return NT_STATUS_OK;
5048 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5049 fname, (double)size ));
5051 if (fsp && fsp->fh->fd != -1) {
5052 /* Handle based call. */
5053 if (vfs_set_filelen(fsp, size) == -1) {
5054 return map_nt_error_from_unix(errno);
5056 trigger_write_time_update_immediate(fsp);
5057 return NT_STATUS_OK;
5060 status = SMB_VFS_CREATE_FILE(
5061 conn, /* conn */
5062 req, /* req */
5063 0, /* root_dir_fid */
5064 fname, /* fname */
5065 0, /* create_file_flags */
5066 FILE_WRITE_ATTRIBUTES, /* access_mask */
5067 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5068 FILE_SHARE_DELETE),
5069 FILE_OPEN, /* create_disposition*/
5070 0, /* create_options */
5071 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5072 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5073 0, /* allocation_size */
5074 NULL, /* sd */
5075 NULL, /* ea_list */
5076 &new_fsp, /* result */
5077 NULL, /* pinfo */
5078 psbuf); /* psbuf */
5080 if (!NT_STATUS_IS_OK(status)) {
5081 /* NB. We check for open_was_deferred in the caller. */
5082 return status;
5085 if (vfs_set_filelen(new_fsp, size) == -1) {
5086 status = map_nt_error_from_unix(errno);
5087 close_file(req, new_fsp,NORMAL_CLOSE);
5088 return status;
5091 trigger_write_time_update_immediate(new_fsp);
5092 close_file(req, new_fsp,NORMAL_CLOSE);
5093 return NT_STATUS_OK;
5096 /****************************************************************************
5097 Deal with SMB_INFO_SET_EA.
5098 ****************************************************************************/
5100 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5101 const char *pdata,
5102 int total_data,
5103 files_struct *fsp,
5104 const char *fname)
5106 struct ea_list *ea_list = NULL;
5107 TALLOC_CTX *ctx = NULL;
5108 NTSTATUS status = NT_STATUS_OK;
5110 if (total_data < 10) {
5112 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5113 length. They seem to have no effect. Bug #3212. JRA */
5115 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5116 /* We're done. We only get EA info in this call. */
5117 return NT_STATUS_OK;
5120 return NT_STATUS_INVALID_PARAMETER;
5123 if (IVAL(pdata,0) > total_data) {
5124 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5125 IVAL(pdata,0), (unsigned int)total_data));
5126 return NT_STATUS_INVALID_PARAMETER;
5129 ctx = talloc_tos();
5130 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5131 if (!ea_list) {
5132 return NT_STATUS_INVALID_PARAMETER;
5134 status = set_ea(conn, fsp, fname, ea_list);
5136 return status;
5139 /****************************************************************************
5140 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5141 ****************************************************************************/
5143 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5144 const char *pdata,
5145 int total_data,
5146 files_struct *fsp,
5147 const char *fname,
5148 SMB_STRUCT_STAT *psbuf)
5150 NTSTATUS status = NT_STATUS_OK;
5151 bool delete_on_close;
5152 uint32 dosmode = 0;
5154 if (total_data < 1) {
5155 return NT_STATUS_INVALID_PARAMETER;
5158 if (fsp == NULL) {
5159 return NT_STATUS_INVALID_HANDLE;
5162 delete_on_close = (CVAL(pdata,0) ? True : False);
5163 dosmode = dos_mode(conn, fname, psbuf);
5165 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5166 "delete_on_close = %u\n",
5167 fsp->fsp_name,
5168 (unsigned int)dosmode,
5169 (unsigned int)delete_on_close ));
5171 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5173 if (!NT_STATUS_IS_OK(status)) {
5174 return status;
5177 /* The set is across all open files on this dev/inode pair. */
5178 if (!set_delete_on_close(fsp, delete_on_close,
5179 &conn->server_info->utok)) {
5180 return NT_STATUS_ACCESS_DENIED;
5182 return NT_STATUS_OK;
5185 /****************************************************************************
5186 Deal with SMB_FILE_POSITION_INFORMATION.
5187 ****************************************************************************/
5189 static NTSTATUS smb_file_position_information(connection_struct *conn,
5190 const char *pdata,
5191 int total_data,
5192 files_struct *fsp)
5194 uint64_t position_information;
5196 if (total_data < 8) {
5197 return NT_STATUS_INVALID_PARAMETER;
5200 if (fsp == NULL) {
5201 /* Ignore on pathname based set. */
5202 return NT_STATUS_OK;
5205 position_information = (uint64_t)IVAL(pdata,0);
5206 #ifdef LARGE_SMB_OFF_T
5207 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5208 #else /* LARGE_SMB_OFF_T */
5209 if (IVAL(pdata,4) != 0) {
5210 /* more than 32 bits? */
5211 return NT_STATUS_INVALID_PARAMETER;
5213 #endif /* LARGE_SMB_OFF_T */
5215 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5216 fsp->fsp_name, (double)position_information ));
5217 fsp->fh->position_information = position_information;
5218 return NT_STATUS_OK;
5221 /****************************************************************************
5222 Deal with SMB_FILE_MODE_INFORMATION.
5223 ****************************************************************************/
5225 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5226 const char *pdata,
5227 int total_data)
5229 uint32 mode;
5231 if (total_data < 4) {
5232 return NT_STATUS_INVALID_PARAMETER;
5234 mode = IVAL(pdata,0);
5235 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5236 return NT_STATUS_INVALID_PARAMETER;
5238 return NT_STATUS_OK;
5241 /****************************************************************************
5242 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5243 ****************************************************************************/
5245 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5246 struct smb_request *req,
5247 const char *pdata,
5248 int total_data,
5249 const char *fname)
5251 char *link_target = NULL;
5252 const char *newname = fname;
5253 NTSTATUS status = NT_STATUS_OK;
5254 TALLOC_CTX *ctx = talloc_tos();
5256 /* Set a symbolic link. */
5257 /* Don't allow this if follow links is false. */
5259 if (total_data == 0) {
5260 return NT_STATUS_INVALID_PARAMETER;
5263 if (!lp_symlinks(SNUM(conn))) {
5264 return NT_STATUS_ACCESS_DENIED;
5267 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5268 total_data, STR_TERMINATE);
5270 if (!link_target) {
5271 return NT_STATUS_INVALID_PARAMETER;
5274 /* !widelinks forces the target path to be within the share. */
5275 /* This means we can interpret the target as a pathname. */
5276 if (!lp_widelinks(SNUM(conn))) {
5277 char *rel_name = NULL;
5278 char *last_dirp = NULL;
5280 if (*link_target == '/') {
5281 /* No absolute paths allowed. */
5282 return NT_STATUS_ACCESS_DENIED;
5284 rel_name = talloc_strdup(ctx,newname);
5285 if (!rel_name) {
5286 return NT_STATUS_NO_MEMORY;
5288 last_dirp = strrchr_m(rel_name, '/');
5289 if (last_dirp) {
5290 last_dirp[1] = '\0';
5291 } else {
5292 rel_name = talloc_strdup(ctx,"./");
5293 if (!rel_name) {
5294 return NT_STATUS_NO_MEMORY;
5297 rel_name = talloc_asprintf_append(rel_name,
5298 "%s",
5299 link_target);
5300 if (!rel_name) {
5301 return NT_STATUS_NO_MEMORY;
5304 status = check_name(conn, rel_name);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 return status;
5310 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5311 newname, link_target ));
5313 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5314 return map_nt_error_from_unix(errno);
5317 return NT_STATUS_OK;
5320 /****************************************************************************
5321 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5322 ****************************************************************************/
5324 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5325 struct smb_request *req,
5326 const char *pdata, int total_data,
5327 const char *fname)
5329 char *oldname = NULL;
5330 TALLOC_CTX *ctx = talloc_tos();
5331 NTSTATUS status = NT_STATUS_OK;
5333 /* Set a hard link. */
5334 if (total_data == 0) {
5335 return NT_STATUS_INVALID_PARAMETER;
5338 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5339 total_data, STR_TERMINATE, &status);
5340 if (!NT_STATUS_IS_OK(status)) {
5341 return status;
5344 status = resolve_dfspath(ctx, conn,
5345 req->flags2 & FLAGS2_DFS_PATHNAMES,
5346 oldname,
5347 &oldname);
5348 if (!NT_STATUS_IS_OK(status)) {
5349 return status;
5352 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5353 fname, oldname));
5355 return hardlink_internals(ctx, conn, oldname, fname);
5358 /****************************************************************************
5359 Deal with SMB_FILE_RENAME_INFORMATION.
5360 ****************************************************************************/
5362 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5363 struct smb_request *req,
5364 const char *pdata,
5365 int total_data,
5366 files_struct *fsp,
5367 const char *fname)
5369 bool overwrite;
5370 uint32 root_fid;
5371 uint32 len;
5372 char *newname = NULL;
5373 char *base_name = NULL;
5374 bool dest_has_wcard = False;
5375 NTSTATUS status = NT_STATUS_OK;
5376 char *p;
5377 TALLOC_CTX *ctx = talloc_tos();
5379 if (total_data < 13) {
5380 return NT_STATUS_INVALID_PARAMETER;
5383 overwrite = (CVAL(pdata,0) ? True : False);
5384 root_fid = IVAL(pdata,4);
5385 len = IVAL(pdata,8);
5387 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5388 return NT_STATUS_INVALID_PARAMETER;
5391 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5392 len, 0, &status,
5393 &dest_has_wcard);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 return status;
5398 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5399 newname));
5401 status = resolve_dfspath_wcard(ctx, conn,
5402 req->flags2 & FLAGS2_DFS_PATHNAMES,
5403 newname,
5404 &newname,
5405 &dest_has_wcard);
5406 if (!NT_STATUS_IS_OK(status)) {
5407 return status;
5410 /* Check the new name has no '/' characters. */
5411 if (strchr_m(newname, '/')) {
5412 return NT_STATUS_NOT_SUPPORTED;
5415 if (fsp && fsp->base_fsp) {
5416 if (newname[0] != ':') {
5417 return NT_STATUS_NOT_SUPPORTED;
5419 base_name = talloc_asprintf(ctx, "%s%s",
5420 fsp->base_fsp->fsp_name,
5421 newname);
5422 if (!base_name) {
5423 return NT_STATUS_NO_MEMORY;
5425 } else {
5426 if (is_ntfs_stream_name(newname)) {
5427 return NT_STATUS_NOT_SUPPORTED;
5430 /* Create the base directory. */
5431 base_name = talloc_strdup(ctx, fname);
5432 if (!base_name) {
5433 return NT_STATUS_NO_MEMORY;
5435 p = strrchr_m(base_name, '/');
5436 if (p) {
5437 p[1] = '\0';
5438 } else {
5439 base_name = talloc_strdup(ctx, "./");
5440 if (!base_name) {
5441 return NT_STATUS_NO_MEMORY;
5444 /* Append the new name. */
5445 base_name = talloc_asprintf_append(base_name,
5446 "%s",
5447 newname);
5448 if (!base_name) {
5449 return NT_STATUS_NO_MEMORY;
5453 if (fsp) {
5454 SMB_STRUCT_STAT sbuf;
5455 char *newname_last_component = NULL;
5457 ZERO_STRUCT(sbuf);
5459 status = unix_convert(ctx, conn, newname, False,
5460 &newname,
5461 &newname_last_component,
5462 &sbuf);
5464 /* If an error we expect this to be
5465 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5467 if (!NT_STATUS_IS_OK(status)
5468 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5469 status)) {
5470 return status;
5473 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5474 fsp->fnum, fsp->fsp_name, base_name ));
5475 status = rename_internals_fsp(conn, fsp, base_name,
5476 newname_last_component, 0,
5477 overwrite);
5478 } else {
5479 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5480 fname, base_name ));
5481 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5482 overwrite, False, dest_has_wcard,
5483 FILE_WRITE_ATTRIBUTES);
5486 return status;
5489 /****************************************************************************
5490 Deal with SMB_SET_POSIX_ACL.
5491 ****************************************************************************/
5493 #if defined(HAVE_POSIX_ACLS)
5494 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5495 const char *pdata,
5496 int total_data,
5497 files_struct *fsp,
5498 const char *fname,
5499 SMB_STRUCT_STAT *psbuf)
5501 uint16 posix_acl_version;
5502 uint16 num_file_acls;
5503 uint16 num_def_acls;
5504 bool valid_file_acls = True;
5505 bool valid_def_acls = True;
5507 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5508 return NT_STATUS_INVALID_PARAMETER;
5510 posix_acl_version = SVAL(pdata,0);
5511 num_file_acls = SVAL(pdata,2);
5512 num_def_acls = SVAL(pdata,4);
5514 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5515 valid_file_acls = False;
5516 num_file_acls = 0;
5519 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5520 valid_def_acls = False;
5521 num_def_acls = 0;
5524 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5525 return NT_STATUS_INVALID_PARAMETER;
5528 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5529 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5530 return NT_STATUS_INVALID_PARAMETER;
5533 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5534 fname ? fname : fsp->fsp_name,
5535 (unsigned int)num_file_acls,
5536 (unsigned int)num_def_acls));
5538 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5539 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5540 return map_nt_error_from_unix(errno);
5543 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5544 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5545 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5546 return map_nt_error_from_unix(errno);
5548 return NT_STATUS_OK;
5550 #endif
5552 /****************************************************************************
5553 Deal with SMB_SET_POSIX_LOCK.
5554 ****************************************************************************/
5556 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5557 struct smb_request *req,
5558 const char *pdata,
5559 int total_data,
5560 files_struct *fsp)
5562 uint64_t count;
5563 uint64_t offset;
5564 uint32 lock_pid;
5565 bool blocking_lock = False;
5566 enum brl_type lock_type;
5568 NTSTATUS status = NT_STATUS_OK;
5570 if (fsp == NULL || fsp->fh->fd == -1) {
5571 return NT_STATUS_INVALID_HANDLE;
5574 if (total_data != POSIX_LOCK_DATA_SIZE) {
5575 return NT_STATUS_INVALID_PARAMETER;
5578 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5579 case POSIX_LOCK_TYPE_READ:
5580 lock_type = READ_LOCK;
5581 break;
5582 case POSIX_LOCK_TYPE_WRITE:
5583 /* Return the right POSIX-mappable error code for files opened read-only. */
5584 if (!fsp->can_write) {
5585 return NT_STATUS_INVALID_HANDLE;
5587 lock_type = WRITE_LOCK;
5588 break;
5589 case POSIX_LOCK_TYPE_UNLOCK:
5590 lock_type = UNLOCK_LOCK;
5591 break;
5592 default:
5593 return NT_STATUS_INVALID_PARAMETER;
5596 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5597 blocking_lock = False;
5598 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5599 blocking_lock = True;
5600 } else {
5601 return NT_STATUS_INVALID_PARAMETER;
5604 if (!lp_blocking_locks(SNUM(conn))) {
5605 blocking_lock = False;
5608 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5609 #if defined(HAVE_LONGLONG)
5610 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5611 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5612 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5613 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5614 #else /* HAVE_LONGLONG */
5615 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5616 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5617 #endif /* HAVE_LONGLONG */
5619 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5620 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5621 fsp->fsp_name,
5622 (unsigned int)lock_type,
5623 (unsigned int)lock_pid,
5624 (double)count,
5625 (double)offset ));
5627 if (lock_type == UNLOCK_LOCK) {
5628 status = do_unlock(smbd_messaging_context(),
5629 fsp,
5630 lock_pid,
5631 count,
5632 offset,
5633 POSIX_LOCK);
5634 } else {
5635 uint32 block_smbpid;
5637 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5638 fsp,
5639 lock_pid,
5640 count,
5641 offset,
5642 lock_type,
5643 POSIX_LOCK,
5644 blocking_lock,
5645 &status,
5646 &block_smbpid);
5648 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5650 * A blocking lock was requested. Package up
5651 * this smb into a queued request and push it
5652 * onto the blocking lock queue.
5654 if(push_blocking_lock_request(br_lck,
5655 req,
5656 fsp,
5657 -1, /* infinite timeout. */
5659 lock_pid,
5660 lock_type,
5661 POSIX_LOCK,
5662 offset,
5663 count,
5664 block_smbpid)) {
5665 TALLOC_FREE(br_lck);
5666 return status;
5669 TALLOC_FREE(br_lck);
5672 return status;
5675 /****************************************************************************
5676 Deal with SMB_INFO_STANDARD.
5677 ****************************************************************************/
5679 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5680 const char *pdata,
5681 int total_data,
5682 files_struct *fsp,
5683 const char *fname,
5684 const SMB_STRUCT_STAT *psbuf)
5686 struct timespec ts[2];
5688 if (total_data < 12) {
5689 return NT_STATUS_INVALID_PARAMETER;
5692 /* access time */
5693 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5694 /* write time */
5695 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5697 DEBUG(10,("smb_set_info_standard: file %s\n",
5698 fname ? fname : fsp->fsp_name ));
5700 return smb_set_file_time(conn,
5701 fsp,
5702 fname,
5703 psbuf,
5705 true);
5708 /****************************************************************************
5709 Deal with SMB_SET_FILE_BASIC_INFO.
5710 ****************************************************************************/
5712 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5713 const char *pdata,
5714 int total_data,
5715 files_struct *fsp,
5716 const char *fname,
5717 SMB_STRUCT_STAT *psbuf)
5719 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5720 struct timespec write_time;
5721 struct timespec changed_time;
5722 uint32 dosmode = 0;
5723 struct timespec ts[2];
5724 NTSTATUS status = NT_STATUS_OK;
5725 bool setting_write_time = true;
5727 if (total_data < 36) {
5728 return NT_STATUS_INVALID_PARAMETER;
5731 /* Set the attributes */
5732 dosmode = IVAL(pdata,32);
5733 status = smb_set_file_dosmode(conn,
5734 fname,
5735 psbuf,
5736 dosmode);
5737 if (!NT_STATUS_IS_OK(status)) {
5738 return status;
5741 /* Ignore create time at offset pdata. */
5743 /* access time */
5744 ts[0] = interpret_long_date(pdata+8);
5746 write_time = interpret_long_date(pdata+16);
5747 changed_time = interpret_long_date(pdata+24);
5749 /* mtime */
5750 ts[1] = timespec_min(&write_time, &changed_time);
5752 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5753 ts[1] = write_time;
5756 /* Prefer a defined time to an undefined one. */
5757 if (null_timespec(ts[1])) {
5758 if (null_timespec(write_time)) {
5759 ts[1] = changed_time;
5760 setting_write_time = false;
5761 } else {
5762 ts[1] = write_time;
5766 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5767 fname ? fname : fsp->fsp_name ));
5769 return smb_set_file_time(conn,
5770 fsp,
5771 fname,
5772 psbuf,
5774 setting_write_time);
5777 /****************************************************************************
5778 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5779 ****************************************************************************/
5781 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5782 struct smb_request *req,
5783 const char *pdata,
5784 int total_data,
5785 files_struct *fsp,
5786 const char *fname,
5787 SMB_STRUCT_STAT *psbuf)
5789 uint64_t allocation_size = 0;
5790 NTSTATUS status = NT_STATUS_OK;
5791 files_struct *new_fsp = NULL;
5793 if (!VALID_STAT(*psbuf)) {
5794 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5797 if (total_data < 8) {
5798 return NT_STATUS_INVALID_PARAMETER;
5801 allocation_size = (uint64_t)IVAL(pdata,0);
5802 #ifdef LARGE_SMB_OFF_T
5803 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5804 #else /* LARGE_SMB_OFF_T */
5805 if (IVAL(pdata,4) != 0) {
5806 /* more than 32 bits? */
5807 return NT_STATUS_INVALID_PARAMETER;
5809 #endif /* LARGE_SMB_OFF_T */
5811 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5812 fname, (double)allocation_size ));
5814 if (allocation_size) {
5815 allocation_size = smb_roundup(conn, allocation_size);
5818 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5819 fname, (double)allocation_size ));
5821 if (fsp && fsp->fh->fd != -1) {
5822 /* Open file handle. */
5823 /* Only change if needed. */
5824 if (allocation_size != get_file_size(*psbuf)) {
5825 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5826 return map_nt_error_from_unix(errno);
5829 /* But always update the time. */
5831 * This is equivalent to a write. Ensure it's seen immediately
5832 * if there are no pending writes.
5834 trigger_write_time_update_immediate(fsp);
5835 return NT_STATUS_OK;
5838 /* Pathname or stat or directory file. */
5840 status = SMB_VFS_CREATE_FILE(
5841 conn, /* conn */
5842 req, /* req */
5843 0, /* root_dir_fid */
5844 fname, /* fname */
5845 0, /* create_file_flags */
5846 FILE_WRITE_DATA, /* access_mask */
5847 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5848 FILE_SHARE_DELETE),
5849 FILE_OPEN, /* create_disposition*/
5850 0, /* create_options */
5851 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5852 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5853 0, /* allocation_size */
5854 NULL, /* sd */
5855 NULL, /* ea_list */
5856 &new_fsp, /* result */
5857 NULL, /* pinfo */
5858 psbuf); /* psbuf */
5860 if (!NT_STATUS_IS_OK(status)) {
5861 /* NB. We check for open_was_deferred in the caller. */
5862 return status;
5865 /* Only change if needed. */
5866 if (allocation_size != get_file_size(*psbuf)) {
5867 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5868 status = map_nt_error_from_unix(errno);
5869 close_file(req, new_fsp, NORMAL_CLOSE);
5870 return status;
5874 /* Changing the allocation size should set the last mod time. */
5876 * This is equivalent to a write. Ensure it's seen immediately
5877 * if there are no pending writes.
5879 trigger_write_time_update_immediate(new_fsp);
5881 close_file(req, new_fsp, NORMAL_CLOSE);
5882 return NT_STATUS_OK;
5885 /****************************************************************************
5886 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5887 ****************************************************************************/
5889 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5890 struct smb_request *req,
5891 const char *pdata,
5892 int total_data,
5893 files_struct *fsp,
5894 const char *fname,
5895 SMB_STRUCT_STAT *psbuf)
5897 SMB_OFF_T size;
5899 if (total_data < 8) {
5900 return NT_STATUS_INVALID_PARAMETER;
5903 size = IVAL(pdata,0);
5904 #ifdef LARGE_SMB_OFF_T
5905 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5906 #else /* LARGE_SMB_OFF_T */
5907 if (IVAL(pdata,4) != 0) {
5908 /* more than 32 bits? */
5909 return NT_STATUS_INVALID_PARAMETER;
5911 #endif /* LARGE_SMB_OFF_T */
5912 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5913 "file %s to %.0f\n", fname, (double)size ));
5915 return smb_set_file_size(conn, req,
5916 fsp,
5917 fname,
5918 psbuf,
5919 size);
5922 /****************************************************************************
5923 Allow a UNIX info mknod.
5924 ****************************************************************************/
5926 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5927 const char *pdata,
5928 int total_data,
5929 const char *fname,
5930 SMB_STRUCT_STAT *psbuf)
5932 uint32 file_type = IVAL(pdata,56);
5933 #if defined(HAVE_MAKEDEV)
5934 uint32 dev_major = IVAL(pdata,60);
5935 uint32 dev_minor = IVAL(pdata,68);
5936 #endif
5937 SMB_DEV_T dev = (SMB_DEV_T)0;
5938 uint32 raw_unixmode = IVAL(pdata,84);
5939 NTSTATUS status;
5940 mode_t unixmode;
5942 if (total_data < 100) {
5943 return NT_STATUS_INVALID_PARAMETER;
5946 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 return status;
5951 #if defined(HAVE_MAKEDEV)
5952 dev = makedev(dev_major, dev_minor);
5953 #endif
5955 switch (file_type) {
5956 #if defined(S_IFIFO)
5957 case UNIX_TYPE_FIFO:
5958 unixmode |= S_IFIFO;
5959 break;
5960 #endif
5961 #if defined(S_IFSOCK)
5962 case UNIX_TYPE_SOCKET:
5963 unixmode |= S_IFSOCK;
5964 break;
5965 #endif
5966 #if defined(S_IFCHR)
5967 case UNIX_TYPE_CHARDEV:
5968 unixmode |= S_IFCHR;
5969 break;
5970 #endif
5971 #if defined(S_IFBLK)
5972 case UNIX_TYPE_BLKDEV:
5973 unixmode |= S_IFBLK;
5974 break;
5975 #endif
5976 default:
5977 return NT_STATUS_INVALID_PARAMETER;
5980 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5981 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5983 /* Ok - do the mknod. */
5984 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5985 return map_nt_error_from_unix(errno);
5988 /* If any of the other "set" calls fail we
5989 * don't want to end up with a half-constructed mknod.
5992 if (lp_inherit_perms(SNUM(conn))) {
5993 inherit_access_posix_acl(
5994 conn, parent_dirname(fname),
5995 fname, unixmode);
5998 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5999 status = map_nt_error_from_unix(errno);
6000 SMB_VFS_UNLINK(conn,fname);
6001 return status;
6003 return NT_STATUS_OK;
6006 /****************************************************************************
6007 Deal with SMB_SET_FILE_UNIX_BASIC.
6008 ****************************************************************************/
6010 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6011 struct smb_request *req,
6012 const char *pdata,
6013 int total_data,
6014 files_struct *fsp,
6015 const char *fname,
6016 SMB_STRUCT_STAT *psbuf)
6018 struct timespec ts[2];
6019 uint32 raw_unixmode;
6020 mode_t unixmode;
6021 SMB_OFF_T size = 0;
6022 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6023 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6024 NTSTATUS status = NT_STATUS_OK;
6025 bool delete_on_fail = False;
6026 enum perm_type ptype;
6028 if (total_data < 100) {
6029 return NT_STATUS_INVALID_PARAMETER;
6032 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6033 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6034 size=IVAL(pdata,0); /* first 8 Bytes are size */
6035 #ifdef LARGE_SMB_OFF_T
6036 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6037 #else /* LARGE_SMB_OFF_T */
6038 if (IVAL(pdata,4) != 0) {
6039 /* more than 32 bits? */
6040 return NT_STATUS_INVALID_PARAMETER;
6042 #endif /* LARGE_SMB_OFF_T */
6045 ts[0] = interpret_long_date(pdata+24); /* access_time */
6046 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6047 set_owner = (uid_t)IVAL(pdata,40);
6048 set_grp = (gid_t)IVAL(pdata,48);
6049 raw_unixmode = IVAL(pdata,84);
6051 if (VALID_STAT(*psbuf)) {
6052 if (S_ISDIR(psbuf->st_mode)) {
6053 ptype = PERM_EXISTING_DIR;
6054 } else {
6055 ptype = PERM_EXISTING_FILE;
6057 } else {
6058 ptype = PERM_NEW_FILE;
6061 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6062 if (!NT_STATUS_IS_OK(status)) {
6063 return status;
6066 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6067 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6068 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6070 if (!VALID_STAT(*psbuf)) {
6072 * The only valid use of this is to create character and block
6073 * devices, and named pipes. This is deprecated (IMHO) and
6074 * a new info level should be used for mknod. JRA.
6077 status = smb_unix_mknod(conn,
6078 pdata,
6079 total_data,
6080 fname,
6081 psbuf);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 return status;
6086 /* Ensure we don't try and change anything else. */
6087 raw_unixmode = SMB_MODE_NO_CHANGE;
6088 size = get_file_size(*psbuf);
6089 ts[0] = get_atimespec(psbuf);
6090 ts[1] = get_mtimespec(psbuf);
6092 * We continue here as we might want to change the
6093 * owner uid/gid.
6095 delete_on_fail = True;
6098 #if 1
6099 /* Horrible backwards compatibility hack as an old server bug
6100 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6101 * */
6103 if (!size) {
6104 size = get_file_size(*psbuf);
6106 #endif
6109 * Deal with the UNIX specific mode set.
6112 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6113 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6114 (unsigned int)unixmode, fname ));
6115 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6116 return map_nt_error_from_unix(errno);
6121 * Deal with the UNIX specific uid set.
6124 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6125 int ret;
6127 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6128 (unsigned int)set_owner, fname ));
6130 if (S_ISLNK(psbuf->st_mode)) {
6131 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6132 } else {
6133 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6136 if (ret != 0) {
6137 status = map_nt_error_from_unix(errno);
6138 if (delete_on_fail) {
6139 SMB_VFS_UNLINK(conn,fname);
6141 return status;
6146 * Deal with the UNIX specific gid set.
6149 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6150 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6151 (unsigned int)set_owner, fname ));
6152 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6153 status = map_nt_error_from_unix(errno);
6154 if (delete_on_fail) {
6155 SMB_VFS_UNLINK(conn,fname);
6157 return status;
6161 /* Deal with any size changes. */
6163 status = smb_set_file_size(conn, req,
6164 fsp,
6165 fname,
6166 psbuf,
6167 size);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 return status;
6172 /* Deal with any time changes. */
6174 return smb_set_file_time(conn,
6175 fsp,
6176 fname,
6177 psbuf,
6179 true);
6182 /****************************************************************************
6183 Deal with SMB_SET_FILE_UNIX_INFO2.
6184 ****************************************************************************/
6186 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6187 struct smb_request *req,
6188 const char *pdata,
6189 int total_data,
6190 files_struct *fsp,
6191 const char *fname,
6192 SMB_STRUCT_STAT *psbuf)
6194 NTSTATUS status;
6195 uint32 smb_fflags;
6196 uint32 smb_fmask;
6198 if (total_data < 116) {
6199 return NT_STATUS_INVALID_PARAMETER;
6202 /* Start by setting all the fields that are common between UNIX_BASIC
6203 * and UNIX_INFO2.
6205 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6206 fsp, fname, psbuf);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 return status;
6211 smb_fflags = IVAL(pdata, 108);
6212 smb_fmask = IVAL(pdata, 112);
6214 /* NB: We should only attempt to alter the file flags if the client
6215 * sends a non-zero mask.
6217 if (smb_fmask != 0) {
6218 int stat_fflags = 0;
6220 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6221 &stat_fflags)) {
6222 /* Client asked to alter a flag we don't understand. */
6223 return NT_STATUS_INVALID_PARAMETER;
6226 if (fsp && fsp->fh->fd != -1) {
6227 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6228 return NT_STATUS_NOT_SUPPORTED;
6229 } else {
6230 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6231 return map_nt_error_from_unix(errno);
6236 /* XXX: need to add support for changing the create_time here. You
6237 * can do this for paths on Darwin with setattrlist(2). The right way
6238 * to hook this up is probably by extending the VFS utimes interface.
6241 return NT_STATUS_OK;
6244 /****************************************************************************
6245 Create a directory with POSIX semantics.
6246 ****************************************************************************/
6248 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6249 struct smb_request *req,
6250 char **ppdata,
6251 int total_data,
6252 const char *fname,
6253 SMB_STRUCT_STAT *psbuf,
6254 int *pdata_return_size)
6256 NTSTATUS status = NT_STATUS_OK;
6257 uint32 raw_unixmode = 0;
6258 uint32 mod_unixmode = 0;
6259 mode_t unixmode = (mode_t)0;
6260 files_struct *fsp = NULL;
6261 uint16 info_level_return = 0;
6262 int info;
6263 char *pdata = *ppdata;
6265 if (total_data < 18) {
6266 return NT_STATUS_INVALID_PARAMETER;
6269 raw_unixmode = IVAL(pdata,8);
6270 /* Next 4 bytes are not yet defined. */
6272 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6273 if (!NT_STATUS_IS_OK(status)) {
6274 return status;
6277 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6279 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6280 fname, (unsigned int)unixmode ));
6282 status = SMB_VFS_CREATE_FILE(
6283 conn, /* conn */
6284 req, /* req */
6285 0, /* root_dir_fid */
6286 fname, /* fname */
6287 0, /* create_file_flags */
6288 FILE_READ_ATTRIBUTES, /* access_mask */
6289 FILE_SHARE_NONE, /* share_access */
6290 FILE_CREATE, /* create_disposition*/
6291 FILE_DIRECTORY_FILE, /* create_options */
6292 mod_unixmode, /* file_attributes */
6293 0, /* oplock_request */
6294 0, /* allocation_size */
6295 NULL, /* sd */
6296 NULL, /* ea_list */
6297 &fsp, /* result */
6298 &info, /* pinfo */
6299 psbuf); /* psbuf */
6301 if (NT_STATUS_IS_OK(status)) {
6302 close_file(req, fsp, NORMAL_CLOSE);
6305 info_level_return = SVAL(pdata,16);
6307 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6308 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6309 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6310 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6311 } else {
6312 *pdata_return_size = 12;
6315 /* Realloc the data size */
6316 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6317 if (*ppdata == NULL) {
6318 *pdata_return_size = 0;
6319 return NT_STATUS_NO_MEMORY;
6321 pdata = *ppdata;
6323 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6324 SSVAL(pdata,2,0); /* No fnum. */
6325 SIVAL(pdata,4,info); /* Was directory created. */
6327 switch (info_level_return) {
6328 case SMB_QUERY_FILE_UNIX_BASIC:
6329 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6330 SSVAL(pdata,10,0); /* Padding. */
6331 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6332 break;
6333 case SMB_QUERY_FILE_UNIX_INFO2:
6334 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6335 SSVAL(pdata,10,0); /* Padding. */
6336 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6337 break;
6338 default:
6339 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6340 SSVAL(pdata,10,0); /* Padding. */
6341 break;
6344 return status;
6347 /****************************************************************************
6348 Open/Create a file with POSIX semantics.
6349 ****************************************************************************/
6351 static NTSTATUS smb_posix_open(connection_struct *conn,
6352 struct smb_request *req,
6353 char **ppdata,
6354 int total_data,
6355 const char *fname,
6356 SMB_STRUCT_STAT *psbuf,
6357 int *pdata_return_size)
6359 bool extended_oplock_granted = False;
6360 char *pdata = *ppdata;
6361 uint32 flags = 0;
6362 uint32 wire_open_mode = 0;
6363 uint32 raw_unixmode = 0;
6364 uint32 mod_unixmode = 0;
6365 uint32 create_disp = 0;
6366 uint32 access_mask = 0;
6367 uint32 create_options = 0;
6368 NTSTATUS status = NT_STATUS_OK;
6369 mode_t unixmode = (mode_t)0;
6370 files_struct *fsp = NULL;
6371 int oplock_request = 0;
6372 int info = 0;
6373 uint16 info_level_return = 0;
6375 if (total_data < 18) {
6376 return NT_STATUS_INVALID_PARAMETER;
6379 flags = IVAL(pdata,0);
6380 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6381 if (oplock_request) {
6382 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6385 wire_open_mode = IVAL(pdata,4);
6387 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6388 return smb_posix_mkdir(conn, req,
6389 ppdata,
6390 total_data,
6391 fname,
6392 psbuf,
6393 pdata_return_size);
6396 switch (wire_open_mode & SMB_ACCMODE) {
6397 case SMB_O_RDONLY:
6398 access_mask = FILE_READ_DATA;
6399 break;
6400 case SMB_O_WRONLY:
6401 access_mask = FILE_WRITE_DATA;
6402 break;
6403 case SMB_O_RDWR:
6404 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6405 break;
6406 default:
6407 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6408 (unsigned int)wire_open_mode ));
6409 return NT_STATUS_INVALID_PARAMETER;
6412 wire_open_mode &= ~SMB_ACCMODE;
6414 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6415 create_disp = FILE_CREATE;
6416 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6417 create_disp = FILE_OVERWRITE_IF;
6418 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6419 create_disp = FILE_OPEN_IF;
6420 } else {
6421 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6422 (unsigned int)wire_open_mode ));
6423 return NT_STATUS_INVALID_PARAMETER;
6426 raw_unixmode = IVAL(pdata,8);
6427 /* Next 4 bytes are not yet defined. */
6429 status = unix_perms_from_wire(conn,
6430 psbuf,
6431 raw_unixmode,
6432 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6433 &unixmode);
6435 if (!NT_STATUS_IS_OK(status)) {
6436 return status;
6439 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6441 if (wire_open_mode & SMB_O_SYNC) {
6442 create_options |= FILE_WRITE_THROUGH;
6444 if (wire_open_mode & SMB_O_APPEND) {
6445 access_mask |= FILE_APPEND_DATA;
6447 if (wire_open_mode & SMB_O_DIRECT) {
6448 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6451 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6452 fname,
6453 (unsigned int)wire_open_mode,
6454 (unsigned int)unixmode ));
6456 status = SMB_VFS_CREATE_FILE(
6457 conn, /* conn */
6458 req, /* req */
6459 0, /* root_dir_fid */
6460 fname, /* fname */
6461 0, /* create_file_flags */
6462 access_mask, /* access_mask */
6463 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6464 FILE_SHARE_DELETE),
6465 create_disp, /* create_disposition*/
6466 0, /* create_options */
6467 mod_unixmode, /* file_attributes */
6468 oplock_request, /* oplock_request */
6469 0, /* allocation_size */
6470 NULL, /* sd */
6471 NULL, /* ea_list */
6472 &fsp, /* result */
6473 &info, /* pinfo */
6474 psbuf); /* psbuf */
6476 if (!NT_STATUS_IS_OK(status)) {
6477 return status;
6480 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6481 extended_oplock_granted = True;
6484 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6485 extended_oplock_granted = True;
6488 info_level_return = SVAL(pdata,16);
6490 /* Allocate the correct return size. */
6492 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6493 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6494 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6495 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6496 } else {
6497 *pdata_return_size = 12;
6500 /* Realloc the data size */
6501 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6502 if (*ppdata == NULL) {
6503 close_file(req, fsp, ERROR_CLOSE);
6504 *pdata_return_size = 0;
6505 return NT_STATUS_NO_MEMORY;
6507 pdata = *ppdata;
6509 if (extended_oplock_granted) {
6510 if (flags & REQUEST_BATCH_OPLOCK) {
6511 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6512 } else {
6513 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6515 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6516 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6517 } else {
6518 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6521 SSVAL(pdata,2,fsp->fnum);
6522 SIVAL(pdata,4,info); /* Was file created etc. */
6524 switch (info_level_return) {
6525 case SMB_QUERY_FILE_UNIX_BASIC:
6526 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6527 SSVAL(pdata,10,0); /* padding. */
6528 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6529 break;
6530 case SMB_QUERY_FILE_UNIX_INFO2:
6531 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6532 SSVAL(pdata,10,0); /* padding. */
6533 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6534 break;
6535 default:
6536 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6537 SSVAL(pdata,10,0); /* padding. */
6538 break;
6540 return NT_STATUS_OK;
6543 /****************************************************************************
6544 Delete a file with POSIX semantics.
6545 ****************************************************************************/
6547 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6548 struct smb_request *req,
6549 const char *pdata,
6550 int total_data,
6551 const char *fname,
6552 SMB_STRUCT_STAT *psbuf)
6554 NTSTATUS status = NT_STATUS_OK;
6555 files_struct *fsp = NULL;
6556 uint16 flags = 0;
6557 char del = 1;
6558 int info = 0;
6559 int create_options = 0;
6560 int i;
6561 struct share_mode_lock *lck = NULL;
6563 if (total_data < 2) {
6564 return NT_STATUS_INVALID_PARAMETER;
6567 flags = SVAL(pdata,0);
6569 if (!VALID_STAT(*psbuf)) {
6570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6573 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6574 !VALID_STAT_OF_DIR(*psbuf)) {
6575 return NT_STATUS_NOT_A_DIRECTORY;
6578 DEBUG(10,("smb_posix_unlink: %s %s\n",
6579 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6580 fname));
6582 if (VALID_STAT_OF_DIR(*psbuf)) {
6583 create_options |= FILE_DIRECTORY_FILE;
6586 status = SMB_VFS_CREATE_FILE(
6587 conn, /* conn */
6588 req, /* req */
6589 0, /* root_dir_fid */
6590 fname, /* fname */
6591 0, /* create_file_flags */
6592 DELETE_ACCESS, /* access_mask */
6593 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6594 FILE_SHARE_DELETE),
6595 FILE_OPEN, /* create_disposition*/
6596 create_options, /* create_options */
6597 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6598 0, /* oplock_request */
6599 0, /* allocation_size */
6600 NULL, /* sd */
6601 NULL, /* ea_list */
6602 &fsp, /* result */
6603 &info, /* pinfo */
6604 psbuf); /* psbuf */
6606 if (!NT_STATUS_IS_OK(status)) {
6607 return status;
6611 * Don't lie to client. If we can't really delete due to
6612 * non-POSIX opens return SHARING_VIOLATION.
6615 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6616 NULL);
6617 if (lck == NULL) {
6618 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6619 "lock for file %s\n", fsp->fsp_name));
6620 close_file(req, fsp, NORMAL_CLOSE);
6621 return NT_STATUS_INVALID_PARAMETER;
6625 * See if others still have the file open. If this is the case, then
6626 * don't delete. If all opens are POSIX delete we can set the delete
6627 * on close disposition.
6629 for (i=0; i<lck->num_share_modes; i++) {
6630 struct share_mode_entry *e = &lck->share_modes[i];
6631 if (is_valid_share_mode_entry(e)) {
6632 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6633 continue;
6635 /* Fail with sharing violation. */
6636 close_file(req, fsp, NORMAL_CLOSE);
6637 TALLOC_FREE(lck);
6638 return NT_STATUS_SHARING_VIOLATION;
6643 * Set the delete on close.
6645 status = smb_set_file_disposition_info(conn,
6646 &del,
6648 fsp,
6649 fname,
6650 psbuf);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 close_file(req, fsp, NORMAL_CLOSE);
6654 TALLOC_FREE(lck);
6655 return status;
6657 TALLOC_FREE(lck);
6658 return close_file(req, fsp, NORMAL_CLOSE);
6661 /****************************************************************************
6662 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6663 ****************************************************************************/
6665 static void call_trans2setfilepathinfo(connection_struct *conn,
6666 struct smb_request *req,
6667 unsigned int tran_call,
6668 char **pparams, int total_params,
6669 char **ppdata, int total_data,
6670 unsigned int max_data_bytes)
6672 char *params = *pparams;
6673 char *pdata = *ppdata;
6674 uint16 info_level;
6675 SMB_STRUCT_STAT sbuf;
6676 char *fname = NULL;
6677 files_struct *fsp = NULL;
6678 NTSTATUS status = NT_STATUS_OK;
6679 int data_return_size = 0;
6680 TALLOC_CTX *ctx = talloc_tos();
6682 if (!params) {
6683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6684 return;
6687 ZERO_STRUCT(sbuf);
6689 if (tran_call == TRANSACT2_SETFILEINFO) {
6690 if (total_params < 4) {
6691 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6692 return;
6695 fsp = file_fsp(req, SVAL(params,0));
6696 /* Basic check for non-null fsp. */
6697 if (!check_fsp_open(conn, req, fsp)) {
6698 return;
6700 info_level = SVAL(params,2);
6702 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6703 if (!fname) {
6704 reply_nterror(req, NT_STATUS_NO_MEMORY);
6705 return;
6708 if(fsp->is_directory || fsp->fh->fd == -1) {
6710 * This is actually a SETFILEINFO on a directory
6711 * handle (returned from an NT SMB). NT5.0 seems
6712 * to do this call. JRA.
6714 if (INFO_LEVEL_IS_UNIX(info_level)) {
6715 /* Always do lstat for UNIX calls. */
6716 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6717 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6718 reply_unixerror(req,ERRDOS,ERRbadpath);
6719 return;
6721 } else {
6722 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6723 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6724 reply_unixerror(req,ERRDOS,ERRbadpath);
6725 return;
6728 } else if (fsp->print_file) {
6730 * Doing a DELETE_ON_CLOSE should cancel a print job.
6732 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6733 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6735 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6737 SSVAL(params,0,0);
6738 send_trans2_replies(conn, req, params, 2,
6739 *ppdata, 0,
6740 max_data_bytes);
6741 return;
6742 } else {
6743 reply_unixerror(req, ERRDOS, ERRbadpath);
6744 return;
6746 } else {
6748 * Original code - this is an open file.
6750 if (!check_fsp(conn, req, fsp)) {
6751 return;
6754 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6755 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6756 reply_unixerror(req, ERRDOS, ERRbadfid);
6757 return;
6760 } else {
6761 /* set path info */
6762 if (total_params < 7) {
6763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6764 return;
6767 info_level = SVAL(params,0);
6768 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6769 total_params - 6, STR_TERMINATE,
6770 &status);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 reply_nterror(req, status);
6773 return;
6776 status = resolve_dfspath(ctx, conn,
6777 req->flags2 & FLAGS2_DFS_PATHNAMES,
6778 fname,
6779 &fname);
6780 if (!NT_STATUS_IS_OK(status)) {
6781 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6782 reply_botherror(req,
6783 NT_STATUS_PATH_NOT_COVERED,
6784 ERRSRV, ERRbadpath);
6785 return;
6787 reply_nterror(req, status);
6788 return;
6791 status = unix_convert(ctx, conn, fname, False,
6792 &fname, NULL, &sbuf);
6793 if (!NT_STATUS_IS_OK(status)) {
6794 reply_nterror(req, status);
6795 return;
6798 status = check_name(conn, fname);
6799 if (!NT_STATUS_IS_OK(status)) {
6800 reply_nterror(req, status);
6801 return;
6804 if (INFO_LEVEL_IS_UNIX(info_level)) {
6806 * For CIFS UNIX extensions the target name may not exist.
6809 /* Always do lstat for UNIX calls. */
6810 SMB_VFS_LSTAT(conn,fname,&sbuf);
6812 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6813 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6814 reply_unixerror(req, ERRDOS, ERRbadpath);
6815 return;
6819 if (!CAN_WRITE(conn)) {
6820 reply_doserror(req, ERRSRV, ERRaccess);
6821 return;
6824 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6825 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6826 return;
6829 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6830 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6832 /* Realloc the parameter size */
6833 *pparams = (char *)SMB_REALLOC(*pparams,2);
6834 if (*pparams == NULL) {
6835 reply_nterror(req, NT_STATUS_NO_MEMORY);
6836 return;
6838 params = *pparams;
6840 SSVAL(params,0,0);
6842 switch (info_level) {
6844 case SMB_INFO_STANDARD:
6846 status = smb_set_info_standard(conn,
6847 pdata,
6848 total_data,
6849 fsp,
6850 fname,
6851 &sbuf);
6852 break;
6855 case SMB_INFO_SET_EA:
6857 status = smb_info_set_ea(conn,
6858 pdata,
6859 total_data,
6860 fsp,
6861 fname);
6862 break;
6865 case SMB_SET_FILE_BASIC_INFO:
6866 case SMB_FILE_BASIC_INFORMATION:
6868 status = smb_set_file_basic_info(conn,
6869 pdata,
6870 total_data,
6871 fsp,
6872 fname,
6873 &sbuf);
6874 break;
6877 case SMB_FILE_ALLOCATION_INFORMATION:
6878 case SMB_SET_FILE_ALLOCATION_INFO:
6880 status = smb_set_file_allocation_info(conn, req,
6881 pdata,
6882 total_data,
6883 fsp,
6884 fname,
6885 &sbuf);
6886 break;
6889 case SMB_FILE_END_OF_FILE_INFORMATION:
6890 case SMB_SET_FILE_END_OF_FILE_INFO:
6892 status = smb_set_file_end_of_file_info(conn, req,
6893 pdata,
6894 total_data,
6895 fsp,
6896 fname,
6897 &sbuf);
6898 break;
6901 case SMB_FILE_DISPOSITION_INFORMATION:
6902 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6904 #if 0
6905 /* JRA - We used to just ignore this on a path ?
6906 * Shouldn't this be invalid level on a pathname
6907 * based call ?
6909 if (tran_call != TRANSACT2_SETFILEINFO) {
6910 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6912 #endif
6913 status = smb_set_file_disposition_info(conn,
6914 pdata,
6915 total_data,
6916 fsp,
6917 fname,
6918 &sbuf);
6919 break;
6922 case SMB_FILE_POSITION_INFORMATION:
6924 status = smb_file_position_information(conn,
6925 pdata,
6926 total_data,
6927 fsp);
6928 break;
6931 /* From tridge Samba4 :
6932 * MODE_INFORMATION in setfileinfo (I have no
6933 * idea what "mode information" on a file is - it takes a value of 0,
6934 * 2, 4 or 6. What could it be?).
6937 case SMB_FILE_MODE_INFORMATION:
6939 status = smb_file_mode_information(conn,
6940 pdata,
6941 total_data);
6942 break;
6946 * CIFS UNIX extensions.
6949 case SMB_SET_FILE_UNIX_BASIC:
6951 status = smb_set_file_unix_basic(conn, req,
6952 pdata,
6953 total_data,
6954 fsp,
6955 fname,
6956 &sbuf);
6957 break;
6960 case SMB_SET_FILE_UNIX_INFO2:
6962 status = smb_set_file_unix_info2(conn, req,
6963 pdata,
6964 total_data,
6965 fsp,
6966 fname,
6967 &sbuf);
6968 break;
6971 case SMB_SET_FILE_UNIX_LINK:
6973 if (tran_call != TRANSACT2_SETPATHINFO) {
6974 /* We must have a pathname for this. */
6975 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6976 return;
6978 status = smb_set_file_unix_link(conn, req, pdata,
6979 total_data, fname);
6980 break;
6983 case SMB_SET_FILE_UNIX_HLINK:
6985 if (tran_call != TRANSACT2_SETPATHINFO) {
6986 /* We must have a pathname for this. */
6987 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6988 return;
6990 status = smb_set_file_unix_hlink(conn, req,
6991 pdata, total_data,
6992 fname);
6993 break;
6996 case SMB_FILE_RENAME_INFORMATION:
6998 status = smb_file_rename_information(conn, req,
6999 pdata, total_data,
7000 fsp, fname);
7001 break;
7004 #if defined(HAVE_POSIX_ACLS)
7005 case SMB_SET_POSIX_ACL:
7007 status = smb_set_posix_acl(conn,
7008 pdata,
7009 total_data,
7010 fsp,
7011 fname,
7012 &sbuf);
7013 break;
7015 #endif
7017 case SMB_SET_POSIX_LOCK:
7019 if (tran_call != TRANSACT2_SETFILEINFO) {
7020 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7021 return;
7023 status = smb_set_posix_lock(conn, req,
7024 pdata, total_data, fsp);
7025 break;
7028 case SMB_POSIX_PATH_OPEN:
7030 if (tran_call != TRANSACT2_SETPATHINFO) {
7031 /* We must have a pathname for this. */
7032 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7033 return;
7036 status = smb_posix_open(conn, req,
7037 ppdata,
7038 total_data,
7039 fname,
7040 &sbuf,
7041 &data_return_size);
7042 break;
7045 case SMB_POSIX_PATH_UNLINK:
7047 if (tran_call != TRANSACT2_SETPATHINFO) {
7048 /* We must have a pathname for this. */
7049 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7050 return;
7053 status = smb_posix_unlink(conn, req,
7054 pdata,
7055 total_data,
7056 fname,
7057 &sbuf);
7058 break;
7061 default:
7062 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7063 return;
7067 if (!NT_STATUS_IS_OK(status)) {
7068 if (open_was_deferred(req->mid)) {
7069 /* We have re-scheduled this call. */
7070 return;
7072 if (blocking_lock_was_deferred(req->mid)) {
7073 /* We have re-scheduled this call. */
7074 return;
7076 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7077 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7078 ERRSRV, ERRbadpath);
7079 return;
7081 if (info_level == SMB_POSIX_PATH_OPEN) {
7082 reply_openerror(req, status);
7083 return;
7086 reply_nterror(req, status);
7087 return;
7090 SSVAL(params,0,0);
7091 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7092 max_data_bytes);
7094 return;
7097 /****************************************************************************
7098 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7099 ****************************************************************************/
7101 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7102 char **pparams, int total_params,
7103 char **ppdata, int total_data,
7104 unsigned int max_data_bytes)
7106 char *params = *pparams;
7107 char *pdata = *ppdata;
7108 char *directory = NULL;
7109 SMB_STRUCT_STAT sbuf;
7110 NTSTATUS status = NT_STATUS_OK;
7111 struct ea_list *ea_list = NULL;
7112 TALLOC_CTX *ctx = talloc_tos();
7114 if (!CAN_WRITE(conn)) {
7115 reply_doserror(req, ERRSRV, ERRaccess);
7116 return;
7119 if (total_params < 5) {
7120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7121 return;
7124 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7125 total_params - 4, STR_TERMINATE,
7126 &status);
7127 if (!NT_STATUS_IS_OK(status)) {
7128 reply_nterror(req, status);
7129 return;
7132 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7134 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7135 if (!NT_STATUS_IS_OK(status)) {
7136 reply_nterror(req, status);
7137 return;
7140 status = check_name(conn, directory);
7141 if (!NT_STATUS_IS_OK(status)) {
7142 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7143 reply_nterror(req, status);
7144 return;
7147 /* Any data in this call is an EA list. */
7148 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7149 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7150 return;
7154 * OS/2 workplace shell seems to send SET_EA requests of "null"
7155 * length (4 bytes containing IVAL 4).
7156 * They seem to have no effect. Bug #3212. JRA.
7159 if (total_data != 4) {
7160 if (total_data < 10) {
7161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7162 return;
7165 if (IVAL(pdata,0) > total_data) {
7166 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7167 IVAL(pdata,0), (unsigned int)total_data));
7168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7169 return;
7172 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7173 total_data - 4);
7174 if (!ea_list) {
7175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7176 return;
7179 /* If total_data == 4 Windows doesn't care what values
7180 * are placed in that field, it just ignores them.
7181 * The System i QNTC IBM SMB client puts bad values here,
7182 * so ignore them. */
7184 status = create_directory(conn, req, directory);
7186 if (!NT_STATUS_IS_OK(status)) {
7187 reply_nterror(req, status);
7188 return;
7191 /* Try and set any given EA. */
7192 if (ea_list) {
7193 status = set_ea(conn, NULL, directory, ea_list);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 reply_nterror(req, status);
7196 return;
7200 /* Realloc the parameter and data sizes */
7201 *pparams = (char *)SMB_REALLOC(*pparams,2);
7202 if(*pparams == NULL) {
7203 reply_nterror(req, NT_STATUS_NO_MEMORY);
7204 return;
7206 params = *pparams;
7208 SSVAL(params,0,0);
7210 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7212 return;
7215 /****************************************************************************
7216 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7217 We don't actually do this - we just send a null response.
7218 ****************************************************************************/
7220 static void call_trans2findnotifyfirst(connection_struct *conn,
7221 struct smb_request *req,
7222 char **pparams, int total_params,
7223 char **ppdata, int total_data,
7224 unsigned int max_data_bytes)
7226 static uint16 fnf_handle = 257;
7227 char *params = *pparams;
7228 uint16 info_level;
7230 if (total_params < 6) {
7231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7232 return;
7235 info_level = SVAL(params,4);
7236 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7238 switch (info_level) {
7239 case 1:
7240 case 2:
7241 break;
7242 default:
7243 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7244 return;
7247 /* Realloc the parameter and data sizes */
7248 *pparams = (char *)SMB_REALLOC(*pparams,6);
7249 if (*pparams == NULL) {
7250 reply_nterror(req, NT_STATUS_NO_MEMORY);
7251 return;
7253 params = *pparams;
7255 SSVAL(params,0,fnf_handle);
7256 SSVAL(params,2,0); /* No changes */
7257 SSVAL(params,4,0); /* No EA errors */
7259 fnf_handle++;
7261 if(fnf_handle == 0)
7262 fnf_handle = 257;
7264 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7266 return;
7269 /****************************************************************************
7270 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7271 changes). Currently this does nothing.
7272 ****************************************************************************/
7274 static void call_trans2findnotifynext(connection_struct *conn,
7275 struct smb_request *req,
7276 char **pparams, int total_params,
7277 char **ppdata, int total_data,
7278 unsigned int max_data_bytes)
7280 char *params = *pparams;
7282 DEBUG(3,("call_trans2findnotifynext\n"));
7284 /* Realloc the parameter and data sizes */
7285 *pparams = (char *)SMB_REALLOC(*pparams,4);
7286 if (*pparams == NULL) {
7287 reply_nterror(req, NT_STATUS_NO_MEMORY);
7288 return;
7290 params = *pparams;
7292 SSVAL(params,0,0); /* No changes */
7293 SSVAL(params,2,0); /* No EA errors */
7295 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7297 return;
7300 /****************************************************************************
7301 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7302 ****************************************************************************/
7304 static void call_trans2getdfsreferral(connection_struct *conn,
7305 struct smb_request *req,
7306 char **pparams, int total_params,
7307 char **ppdata, int total_data,
7308 unsigned int max_data_bytes)
7310 char *params = *pparams;
7311 char *pathname = NULL;
7312 int reply_size = 0;
7313 int max_referral_level;
7314 NTSTATUS status = NT_STATUS_OK;
7315 TALLOC_CTX *ctx = talloc_tos();
7317 DEBUG(10,("call_trans2getdfsreferral\n"));
7319 if (total_params < 3) {
7320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7321 return;
7324 max_referral_level = SVAL(params,0);
7326 if(!lp_host_msdfs()) {
7327 reply_doserror(req, ERRDOS, ERRbadfunc);
7328 return;
7331 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7332 total_params - 2, STR_TERMINATE);
7333 if (!pathname) {
7334 reply_nterror(req, NT_STATUS_NOT_FOUND);
7335 return;
7337 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7338 ppdata,&status)) < 0) {
7339 reply_nterror(req, status);
7340 return;
7343 SSVAL(req->inbuf, smb_flg2,
7344 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7345 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7347 return;
7350 #define LMCAT_SPL 0x53
7351 #define LMFUNC_GETJOBID 0x60
7353 /****************************************************************************
7354 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7355 ****************************************************************************/
7357 static void call_trans2ioctl(connection_struct *conn,
7358 struct smb_request *req,
7359 char **pparams, int total_params,
7360 char **ppdata, int total_data,
7361 unsigned int max_data_bytes)
7363 char *pdata = *ppdata;
7364 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7366 /* check for an invalid fid before proceeding */
7368 if (!fsp) {
7369 reply_doserror(req, ERRDOS, ERRbadfid);
7370 return;
7373 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7374 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7375 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7376 if (*ppdata == NULL) {
7377 reply_nterror(req, NT_STATUS_NO_MEMORY);
7378 return;
7380 pdata = *ppdata;
7382 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7383 CAN ACCEPT THIS IN UNICODE. JRA. */
7385 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7386 srvstr_push(pdata, req->flags2, pdata + 2,
7387 global_myname(), 15,
7388 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7389 srvstr_push(pdata, req->flags2, pdata+18,
7390 lp_servicename(SNUM(conn)), 13,
7391 STR_ASCII|STR_TERMINATE); /* Service name */
7392 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7393 max_data_bytes);
7394 return;
7397 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7398 reply_doserror(req, ERRSRV, ERRerror);
7401 /****************************************************************************
7402 Reply to a SMBfindclose (stop trans2 directory search).
7403 ****************************************************************************/
7405 void reply_findclose(struct smb_request *req)
7407 int dptr_num;
7409 START_PROFILE(SMBfindclose);
7411 if (req->wct < 1) {
7412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7413 END_PROFILE(SMBfindclose);
7414 return;
7417 dptr_num = SVALS(req->vwv+0, 0);
7419 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7421 dptr_close(&dptr_num);
7423 reply_outbuf(req, 0, 0);
7425 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7427 END_PROFILE(SMBfindclose);
7428 return;
7431 /****************************************************************************
7432 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7433 ****************************************************************************/
7435 void reply_findnclose(struct smb_request *req)
7437 int dptr_num;
7439 START_PROFILE(SMBfindnclose);
7441 if (req->wct < 1) {
7442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7443 END_PROFILE(SMBfindnclose);
7444 return;
7447 dptr_num = SVAL(req->vwv+0, 0);
7449 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7451 /* We never give out valid handles for a
7452 findnotifyfirst - so any dptr_num is ok here.
7453 Just ignore it. */
7455 reply_outbuf(req, 0, 0);
7457 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7459 END_PROFILE(SMBfindnclose);
7460 return;
7463 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7464 struct trans_state *state)
7466 if (Protocol >= PROTOCOL_NT1) {
7467 req->flags2 |= 0x40; /* IS_LONG_NAME */
7468 SSVAL(req->inbuf,smb_flg2,req->flags2);
7471 if (conn->encrypt_level == Required && !req->encrypted) {
7472 if (state->call != TRANSACT2_QFSINFO &&
7473 state->call != TRANSACT2_SETFSINFO) {
7474 DEBUG(0,("handle_trans2: encryption required "
7475 "with call 0x%x\n",
7476 (unsigned int)state->call));
7477 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7478 return;
7482 /* Now we must call the relevant TRANS2 function */
7483 switch(state->call) {
7484 case TRANSACT2_OPEN:
7486 START_PROFILE(Trans2_open);
7487 call_trans2open(conn, req,
7488 &state->param, state->total_param,
7489 &state->data, state->total_data,
7490 state->max_data_return);
7491 END_PROFILE(Trans2_open);
7492 break;
7495 case TRANSACT2_FINDFIRST:
7497 START_PROFILE(Trans2_findfirst);
7498 call_trans2findfirst(conn, req,
7499 &state->param, state->total_param,
7500 &state->data, state->total_data,
7501 state->max_data_return);
7502 END_PROFILE(Trans2_findfirst);
7503 break;
7506 case TRANSACT2_FINDNEXT:
7508 START_PROFILE(Trans2_findnext);
7509 call_trans2findnext(conn, req,
7510 &state->param, state->total_param,
7511 &state->data, state->total_data,
7512 state->max_data_return);
7513 END_PROFILE(Trans2_findnext);
7514 break;
7517 case TRANSACT2_QFSINFO:
7519 START_PROFILE(Trans2_qfsinfo);
7520 call_trans2qfsinfo(conn, req,
7521 &state->param, state->total_param,
7522 &state->data, state->total_data,
7523 state->max_data_return);
7524 END_PROFILE(Trans2_qfsinfo);
7525 break;
7528 case TRANSACT2_SETFSINFO:
7530 START_PROFILE(Trans2_setfsinfo);
7531 call_trans2setfsinfo(conn, req,
7532 &state->param, state->total_param,
7533 &state->data, state->total_data,
7534 state->max_data_return);
7535 END_PROFILE(Trans2_setfsinfo);
7536 break;
7539 case TRANSACT2_QPATHINFO:
7540 case TRANSACT2_QFILEINFO:
7542 START_PROFILE(Trans2_qpathinfo);
7543 call_trans2qfilepathinfo(conn, req, state->call,
7544 &state->param, state->total_param,
7545 &state->data, state->total_data,
7546 state->max_data_return);
7547 END_PROFILE(Trans2_qpathinfo);
7548 break;
7551 case TRANSACT2_SETPATHINFO:
7552 case TRANSACT2_SETFILEINFO:
7554 START_PROFILE(Trans2_setpathinfo);
7555 call_trans2setfilepathinfo(conn, req, state->call,
7556 &state->param, state->total_param,
7557 &state->data, state->total_data,
7558 state->max_data_return);
7559 END_PROFILE(Trans2_setpathinfo);
7560 break;
7563 case TRANSACT2_FINDNOTIFYFIRST:
7565 START_PROFILE(Trans2_findnotifyfirst);
7566 call_trans2findnotifyfirst(conn, req,
7567 &state->param, state->total_param,
7568 &state->data, state->total_data,
7569 state->max_data_return);
7570 END_PROFILE(Trans2_findnotifyfirst);
7571 break;
7574 case TRANSACT2_FINDNOTIFYNEXT:
7576 START_PROFILE(Trans2_findnotifynext);
7577 call_trans2findnotifynext(conn, req,
7578 &state->param, state->total_param,
7579 &state->data, state->total_data,
7580 state->max_data_return);
7581 END_PROFILE(Trans2_findnotifynext);
7582 break;
7585 case TRANSACT2_MKDIR:
7587 START_PROFILE(Trans2_mkdir);
7588 call_trans2mkdir(conn, req,
7589 &state->param, state->total_param,
7590 &state->data, state->total_data,
7591 state->max_data_return);
7592 END_PROFILE(Trans2_mkdir);
7593 break;
7596 case TRANSACT2_GET_DFS_REFERRAL:
7598 START_PROFILE(Trans2_get_dfs_referral);
7599 call_trans2getdfsreferral(conn, req,
7600 &state->param, state->total_param,
7601 &state->data, state->total_data,
7602 state->max_data_return);
7603 END_PROFILE(Trans2_get_dfs_referral);
7604 break;
7607 case TRANSACT2_IOCTL:
7609 START_PROFILE(Trans2_ioctl);
7610 call_trans2ioctl(conn, req,
7611 &state->param, state->total_param,
7612 &state->data, state->total_data,
7613 state->max_data_return);
7614 END_PROFILE(Trans2_ioctl);
7615 break;
7618 default:
7619 /* Error in request */
7620 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7621 reply_doserror(req, ERRSRV,ERRerror);
7625 /****************************************************************************
7626 Reply to a SMBtrans2.
7627 ****************************************************************************/
7629 void reply_trans2(struct smb_request *req)
7631 connection_struct *conn = req->conn;
7632 unsigned int dsoff;
7633 unsigned int dscnt;
7634 unsigned int psoff;
7635 unsigned int pscnt;
7636 unsigned int tran_call;
7637 struct trans_state *state;
7638 NTSTATUS result;
7640 START_PROFILE(SMBtrans2);
7642 if (req->wct < 14) {
7643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7644 END_PROFILE(SMBtrans2);
7645 return;
7648 dsoff = SVAL(req->vwv+12, 0);
7649 dscnt = SVAL(req->vwv+11, 0);
7650 psoff = SVAL(req->vwv+10, 0);
7651 pscnt = SVAL(req->vwv+9, 0);
7652 tran_call = SVAL(req->vwv+14, 0);
7654 result = allow_new_trans(conn->pending_trans, req->mid);
7655 if (!NT_STATUS_IS_OK(result)) {
7656 DEBUG(2, ("Got invalid trans2 request: %s\n",
7657 nt_errstr(result)));
7658 reply_nterror(req, result);
7659 END_PROFILE(SMBtrans2);
7660 return;
7663 if (IS_IPC(conn)) {
7664 switch (tran_call) {
7665 /* List the allowed trans2 calls on IPC$ */
7666 case TRANSACT2_OPEN:
7667 case TRANSACT2_GET_DFS_REFERRAL:
7668 case TRANSACT2_QFILEINFO:
7669 case TRANSACT2_QFSINFO:
7670 case TRANSACT2_SETFSINFO:
7671 break;
7672 default:
7673 reply_doserror(req, ERRSRV, ERRaccess);
7674 END_PROFILE(SMBtrans2);
7675 return;
7679 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7680 DEBUG(0, ("talloc failed\n"));
7681 reply_nterror(req, NT_STATUS_NO_MEMORY);
7682 END_PROFILE(SMBtrans2);
7683 return;
7686 state->cmd = SMBtrans2;
7688 state->mid = req->mid;
7689 state->vuid = req->vuid;
7690 state->setup_count = SVAL(req->vwv+13, 0);
7691 state->setup = NULL;
7692 state->total_param = SVAL(req->vwv+0, 0);
7693 state->param = NULL;
7694 state->total_data = SVAL(req->vwv+1, 0);
7695 state->data = NULL;
7696 state->max_param_return = SVAL(req->vwv+2, 0);
7697 state->max_data_return = SVAL(req->vwv+3, 0);
7698 state->max_setup_return = SVAL(req->vwv+4, 0);
7699 state->close_on_completion = BITSETW(req->vwv+5, 0);
7700 state->one_way = BITSETW(req->vwv+5, 1);
7702 state->call = tran_call;
7704 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7705 is so as a sanity check */
7706 if (state->setup_count != 1) {
7708 * Need to have rc=0 for ioctl to get job id for OS/2.
7709 * Network printing will fail if function is not successful.
7710 * Similar function in reply.c will be used if protocol
7711 * is LANMAN1.0 instead of LM1.2X002.
7712 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7713 * outbuf doesn't have to be set(only job id is used).
7715 if ( (state->setup_count == 4)
7716 && (tran_call == TRANSACT2_IOCTL)
7717 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7718 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7719 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7720 } else {
7721 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7722 DEBUG(2,("Transaction is %d\n",tran_call));
7723 TALLOC_FREE(state);
7724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7725 END_PROFILE(SMBtrans2);
7726 return;
7730 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7731 goto bad_param;
7733 if (state->total_data) {
7735 if (trans_oob(state->total_data, 0, dscnt)
7736 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7737 goto bad_param;
7740 /* Can't use talloc here, the core routines do realloc on the
7741 * params and data. */
7742 state->data = (char *)SMB_MALLOC(state->total_data);
7743 if (state->data == NULL) {
7744 DEBUG(0,("reply_trans2: data malloc fail for %u "
7745 "bytes !\n", (unsigned int)state->total_data));
7746 TALLOC_FREE(state);
7747 reply_nterror(req, NT_STATUS_NO_MEMORY);
7748 END_PROFILE(SMBtrans2);
7749 return;
7752 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7755 if (state->total_param) {
7757 if (trans_oob(state->total_param, 0, pscnt)
7758 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7759 goto bad_param;
7762 /* Can't use talloc here, the core routines do realloc on the
7763 * params and data. */
7764 state->param = (char *)SMB_MALLOC(state->total_param);
7765 if (state->param == NULL) {
7766 DEBUG(0,("reply_trans: param malloc fail for %u "
7767 "bytes !\n", (unsigned int)state->total_param));
7768 SAFE_FREE(state->data);
7769 TALLOC_FREE(state);
7770 reply_nterror(req, NT_STATUS_NO_MEMORY);
7771 END_PROFILE(SMBtrans2);
7772 return;
7775 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7778 state->received_data = dscnt;
7779 state->received_param = pscnt;
7781 if ((state->received_param == state->total_param) &&
7782 (state->received_data == state->total_data)) {
7784 handle_trans2(conn, req, state);
7786 SAFE_FREE(state->data);
7787 SAFE_FREE(state->param);
7788 TALLOC_FREE(state);
7789 END_PROFILE(SMBtrans2);
7790 return;
7793 DLIST_ADD(conn->pending_trans, state);
7795 /* We need to send an interim response then receive the rest
7796 of the parameter/data bytes */
7797 reply_outbuf(req, 0, 0);
7798 show_msg((char *)req->outbuf);
7799 END_PROFILE(SMBtrans2);
7800 return;
7802 bad_param:
7804 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7805 SAFE_FREE(state->data);
7806 SAFE_FREE(state->param);
7807 TALLOC_FREE(state);
7808 END_PROFILE(SMBtrans2);
7809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7813 /****************************************************************************
7814 Reply to a SMBtranss2
7815 ****************************************************************************/
7817 void reply_transs2(struct smb_request *req)
7819 connection_struct *conn = req->conn;
7820 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7821 struct trans_state *state;
7823 START_PROFILE(SMBtranss2);
7825 show_msg((char *)req->inbuf);
7827 if (req->wct < 8) {
7828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7829 END_PROFILE(SMBtranss2);
7830 return;
7833 for (state = conn->pending_trans; state != NULL;
7834 state = state->next) {
7835 if (state->mid == req->mid) {
7836 break;
7840 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7841 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7842 END_PROFILE(SMBtranss2);
7843 return;
7846 /* Revise state->total_param and state->total_data in case they have
7847 changed downwards */
7849 if (SVAL(req->vwv+0, 0) < state->total_param)
7850 state->total_param = SVAL(req->vwv+0, 0);
7851 if (SVAL(req->vwv+1, 0) < state->total_data)
7852 state->total_data = SVAL(req->vwv+1, 0);
7854 pcnt = SVAL(req->vwv+2, 0);
7855 poff = SVAL(req->vwv+3, 0);
7856 pdisp = SVAL(req->vwv+4, 0);
7858 dcnt = SVAL(req->vwv+5, 0);
7859 doff = SVAL(req->vwv+6, 0);
7860 ddisp = SVAL(req->vwv+7, 0);
7862 state->received_param += pcnt;
7863 state->received_data += dcnt;
7865 if ((state->received_data > state->total_data) ||
7866 (state->received_param > state->total_param))
7867 goto bad_param;
7869 if (pcnt) {
7870 if (trans_oob(state->total_param, pdisp, pcnt)
7871 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7872 goto bad_param;
7874 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7877 if (dcnt) {
7878 if (trans_oob(state->total_data, ddisp, dcnt)
7879 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7880 goto bad_param;
7882 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7885 if ((state->received_param < state->total_param) ||
7886 (state->received_data < state->total_data)) {
7887 END_PROFILE(SMBtranss2);
7888 return;
7891 handle_trans2(conn, req, state);
7893 DLIST_REMOVE(conn->pending_trans, state);
7894 SAFE_FREE(state->data);
7895 SAFE_FREE(state->param);
7896 TALLOC_FREE(state);
7898 END_PROFILE(SMBtranss2);
7899 return;
7901 bad_param:
7903 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7904 DLIST_REMOVE(conn->pending_trans, state);
7905 SAFE_FREE(state->data);
7906 SAFE_FREE(state->param);
7907 TALLOC_FREE(state);
7908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7909 END_PROFILE(SMBtranss2);
7910 return;