Make test for open modes more robust against other bits.
[Samba/bb.git] / source / smbd / trans2.c
blob1b3dff218aedff68f6a49bbbbbb52ba0c1dfdfe8
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
52 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
64 account sparse files.
65 ********************************************************************/
67 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
69 SMB_BIG_UINT ret;
71 if(S_ISDIR(sbuf->st_mode)) {
72 return 0;
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
77 #else
78 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
79 #endif
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char *prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 NULL
103 int i;
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
107 return true;
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 return true;
113 return false;
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
126 char *val = NULL;
127 ssize_t sizeret;
129 again:
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (!val) {
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 } else {
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 attr_size = 65536;
144 goto again;
147 if (sizeret == -1) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
154 pea->flags = 0;
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 } else {
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
161 TALLOC_FREE(val);
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
166 return NT_STATUS_OK;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
177 char *p;
178 char **names, **tmp;
179 size_t num_names;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
183 *pnames = NULL;
184 *pnum_names = 0;
185 return NT_STATUS_OK;
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
193 if (names == NULL) {
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
204 TALLOC_FREE(names);
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
210 ea_namelist_size);
211 } else {
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
213 ea_namelist_size);
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
219 else {
220 break;
224 if (sizeret == -1) {
225 TALLOC_FREE(names);
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
232 if (sizeret == 0) {
233 TALLOC_FREE(names);
234 *pnames = NULL;
235 *pnum_names = 0;
236 return NT_STATUS_OK;
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
244 TALLOC_FREE(names);
245 return NT_STATUS_INTERNAL_ERROR;
249 * count the names
251 num_names = 0;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
254 num_names += 1;
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 if (tmp == NULL) {
259 DEBUG(0, ("talloc failed\n"));
260 TALLOC_FREE(names);
261 return NT_STATUS_NO_MEMORY;
264 names = tmp;
265 num_names = 0;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
271 *pnames = names;
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
401 return 0;
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
405 return total_ea_len;
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
414 size_t total_ea_len;
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
423 break;
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
439 int ret;
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
460 } else {
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
465 #ifdef ENOATTR
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
469 unix_ea_name));
470 ret = 0;
472 #endif
473 } else {
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
479 } else {
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
487 if (ret == -1) {
488 #ifdef ENOTSUP
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
492 #endif
493 return map_nt_error_from_unix(errno);
497 return NT_STATUS_OK;
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
518 break;
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
522 return NULL;
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
525 &converted_size)) {
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
529 if (!eal->ea.name) {
530 return NULL;
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 return ea_list_head;
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
548 uint16 val_len;
549 unsigned int namelen;
550 size_t converted_size;
552 if (!eal) {
553 return NULL;
556 if (data_size < 6) {
557 return NULL;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
565 return NULL;
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
570 return NULL;
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
574 strerror(errno)));
576 if (!eal->ea.name) {
577 return NULL;
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
582 return NULL;
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
592 if (pbytes_used) {
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
599 return eal;
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
609 size_t offset = 0;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
615 if (!eal) {
616 return NULL;
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
623 return ea_list_head;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
632 fstring dos_ea_name;
633 struct ea_list *listp;
634 size_t ret = 0;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
641 if (ret) {
642 ret += 4;
645 return ret;
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
661 break;
665 if (flistp) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
669 } else {
670 /* Null entry. */
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
677 return name_list;
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
689 const char *params,
690 int paramsize,
691 const char *pdata,
692 int datasize,
693 int max_data_bytes)
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
703 int useable_space;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
714 for OS/2. */
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
720 overflow = True;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
728 return;
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
743 + 2 * 10 /* wct */
744 + alignment_offset
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
771 /* Set total params and data to be sent */
772 SSVAL(req->outbuf,smb_tprcnt,paramsize);
773 SSVAL(req->outbuf,smb_tdrcnt,datasize);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime = MIN(params_to_send,useable_space);
780 data_sent_thistime = useable_space - params_sent_thistime;
781 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
783 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req->outbuf,smb_proff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf)));
794 if(params_sent_thistime == 0)
795 SSVAL(req->outbuf,smb_prdisp,0);
796 else
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req->outbuf,smb_prdisp,pp - params);
800 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
801 if(data_sent_thistime == 0) {
802 SSVAL(req->outbuf,smb_droff,0);
803 SSVAL(req->outbuf,smb_drdisp, 0);
804 } else {
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req->outbuf, smb_droff,
808 ((smb_buf(req->outbuf)+alignment_offset)
809 - smb_base(req->outbuf))
810 + params_sent_thistime + data_alignment_offset);
811 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
814 /* Initialize the padding for alignment */
816 if (alignment_offset != 0) {
817 memset(smb_buf(req->outbuf), 0, alignment_offset);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime) {
823 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
824 params_sent_thistime);
827 /* Copy in the data bytes */
828 if(data_sent_thistime) {
829 if (data_alignment_offset != 0) {
830 memset((smb_buf(req->outbuf)+alignment_offset+
831 params_sent_thistime), 0,
832 data_alignment_offset);
834 memcpy(smb_buf(req->outbuf)+alignment_offset
835 +params_sent_thistime+data_alignment_offset,
836 pd,data_sent_thistime);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime, data_sent_thistime, useable_space));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send, data_to_send, paramsize, datasize));
844 if (overflow) {
845 error_packet_set((char *)req->outbuf,
846 ERRDOS,ERRbufferoverflow,
847 STATUS_BUFFER_OVERFLOW,
848 __LINE__,__FILE__);
851 /* Send the packet */
852 show_msg((char *)req->outbuf);
853 if (!srv_send_smb(smbd_server_fd(),
854 (char *)req->outbuf,
855 IS_CONN_ENCRYPTED(conn)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req->outbuf);
860 pp += params_sent_thistime;
861 pd += data_sent_thistime;
863 params_to_send -= params_sent_thistime;
864 data_to_send -= data_sent_thistime;
866 /* Sanity check */
867 if(params_to_send < 0 || data_to_send < 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send, data_to_send));
870 return;
874 return;
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct *conn,
882 struct smb_request *req,
883 char **pparams, int total_params,
884 char **ppdata, int total_data,
885 unsigned int max_data_bytes)
887 char *params = *pparams;
888 char *pdata = *ppdata;
889 int deny_mode;
890 int32 open_attr;
891 bool oplock_request;
892 #if 0
893 bool return_additional_info;
894 int16 open_sattr;
895 time_t open_time;
896 #endif
897 int open_ofun;
898 uint32 open_size;
899 char *pname;
900 char *fname = NULL;
901 SMB_OFF_T size=0;
902 int fattr=0,mtime=0;
903 SMB_INO_T inode = 0;
904 SMB_STRUCT_STAT sbuf;
905 int smb_action = 0;
906 files_struct *fsp;
907 struct ea_list *ea_list = NULL;
908 uint16 flags = 0;
909 NTSTATUS status;
910 uint32 access_mask;
911 uint32 share_mode;
912 uint32 create_disposition;
913 uint32 create_options = 0;
914 TALLOC_CTX *ctx = talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params < 29) {
921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
922 return;
925 flags = SVAL(params, 0);
926 deny_mode = SVAL(params, 2);
927 open_attr = SVAL(params,6);
928 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
929 if (oplock_request) {
930 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
933 #if 0
934 return_additional_info = BITSETW(params,0);
935 open_sattr = SVAL(params, 4);
936 open_time = make_unix_date3(params+8);
937 #endif
938 open_ofun = SVAL(params,12);
939 open_size = IVAL(params,14);
940 pname = &params[28];
942 if (IS_IPC(conn)) {
943 reply_doserror(req, ERRSRV, ERRaccess);
944 return;
947 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
948 total_params - 28, STR_TERMINATE,
949 &status);
950 if (!NT_STATUS_IS_OK(status)) {
951 reply_nterror(req, status);
952 return;
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
957 (unsigned int)open_ofun, open_size));
959 if (open_ofun == 0) {
960 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
961 return;
964 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
965 &access_mask,
966 &share_mode,
967 &create_disposition,
968 &create_options)) {
969 reply_doserror(req, ERRDOS, ERRbadaccess);
970 return;
973 /* Any data in this call is an EA list. */
974 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
975 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
976 return;
979 if (total_data != 4) {
980 if (total_data < 10) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 return;
985 if (IVAL(pdata,0) > total_data) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata,0), (unsigned int)total_data));
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 return;
992 ea_list = read_ea_list(talloc_tos(), pdata + 4,
993 total_data - 4);
994 if (!ea_list) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 return;
998 } else if (IVAL(pdata,0) != 4) {
999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1000 return;
1003 status = create_file(conn, /* conn */
1004 req, /* req */
1005 0, /* root_dir_fid */
1006 fname, /* fname */
1007 access_mask, /* access_mask */
1008 share_mode, /* share_access */
1009 create_disposition, /* create_disposition*/
1010 create_options, /* create_options */
1011 open_attr, /* file_attributes */
1012 oplock_request, /* oplock_request */
1013 open_size, /* allocation_size */
1014 NULL, /* sd */
1015 ea_list, /* ea_list */
1016 &fsp, /* result */
1017 &smb_action, /* pinfo */
1018 &sbuf); /* psbuf */
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (open_was_deferred(req->mid)) {
1022 /* We have re-scheduled this call. */
1023 return;
1025 reply_openerror(req, status);
1026 return;
1029 size = get_file_size(sbuf);
1030 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1031 mtime = sbuf.st_mtime;
1032 inode = sbuf.st_ino;
1033 if (fattr & aDIR) {
1034 close_file(fsp,ERROR_CLOSE);
1035 reply_doserror(req, ERRDOS,ERRnoaccess);
1036 return;
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1041 if(*pparams == NULL ) {
1042 reply_nterror(req, NT_STATUS_NO_MEMORY);
1043 return;
1045 params = *pparams;
1047 SSVAL(params,0,fsp->fnum);
1048 SSVAL(params,2,fattr);
1049 srv_put_dos_date2(params,4, mtime);
1050 SIVAL(params,8, (uint32)size);
1051 SSVAL(params,12,deny_mode);
1052 SSVAL(params,14,0); /* open_type - file or directory. */
1053 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1059 SSVAL(params,18,smb_action);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params,20,inode);
1065 SSVAL(params,24,0); /* Padding. */
1066 if (flags & 8) {
1067 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1068 SIVAL(params, 26, ea_size);
1069 } else {
1070 SIVAL(params, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct *conn,
1085 const char *str,
1086 const char *mask)
1088 if (mask[0] == '.' && mask[1] == 0)
1089 return False;
1090 if (dptr_has_wild(conn->dirptr)) {
1091 return False;
1093 if (conn->case_sensitive)
1094 return strcmp(str,mask)==0;
1095 else
1096 return StrCaseCmp(str,mask) == 0;
1099 /****************************************************************************
1100 Return the filetype for UNIX extensions.
1101 ****************************************************************************/
1103 static uint32 unix_filetype(mode_t mode)
1105 if(S_ISREG(mode))
1106 return UNIX_TYPE_FILE;
1107 else if(S_ISDIR(mode))
1108 return UNIX_TYPE_DIR;
1109 #ifdef S_ISLNK
1110 else if(S_ISLNK(mode))
1111 return UNIX_TYPE_SYMLINK;
1112 #endif
1113 #ifdef S_ISCHR
1114 else if(S_ISCHR(mode))
1115 return UNIX_TYPE_CHARDEV;
1116 #endif
1117 #ifdef S_ISBLK
1118 else if(S_ISBLK(mode))
1119 return UNIX_TYPE_BLKDEV;
1120 #endif
1121 #ifdef S_ISFIFO
1122 else if(S_ISFIFO(mode))
1123 return UNIX_TYPE_FIFO;
1124 #endif
1125 #ifdef S_ISSOCK
1126 else if(S_ISSOCK(mode))
1127 return UNIX_TYPE_SOCKET;
1128 #endif
1130 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1131 return UNIX_TYPE_UNKNOWN;
1134 /****************************************************************************
1135 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1136 ****************************************************************************/
1138 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1140 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1141 SMB_STRUCT_STAT *psbuf,
1142 uint32 perms,
1143 enum perm_type ptype,
1144 mode_t *ret_perms)
1146 mode_t ret = 0;
1148 if (perms == SMB_MODE_NO_CHANGE) {
1149 if (!VALID_STAT(*psbuf)) {
1150 return NT_STATUS_INVALID_PARAMETER;
1151 } else {
1152 *ret_perms = psbuf->st_mode;
1153 return NT_STATUS_OK;
1157 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1158 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1159 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1160 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1161 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1162 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1163 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1164 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1165 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1166 #ifdef S_ISVTX
1167 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1168 #endif
1169 #ifdef S_ISGID
1170 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1171 #endif
1172 #ifdef S_ISUID
1173 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1174 #endif
1176 switch (ptype) {
1177 case PERM_NEW_FILE:
1178 /* Apply mode mask */
1179 ret &= lp_create_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_create_mode(SNUM(conn));
1182 break;
1183 case PERM_NEW_DIR:
1184 ret &= lp_dir_mask(SNUM(conn));
1185 /* Add in force bits */
1186 ret |= lp_force_dir_mode(SNUM(conn));
1187 break;
1188 case PERM_EXISTING_FILE:
1189 /* Apply mode mask */
1190 ret &= lp_security_mask(SNUM(conn));
1191 /* Add in force bits */
1192 ret |= lp_force_security_mode(SNUM(conn));
1193 break;
1194 case PERM_EXISTING_DIR:
1195 /* Apply mode mask */
1196 ret &= lp_dir_security_mask(SNUM(conn));
1197 /* Add in force bits */
1198 ret |= lp_force_dir_security_mode(SNUM(conn));
1199 break;
1202 *ret_perms = ret;
1203 return NT_STATUS_OK;
1206 /****************************************************************************
1207 Needed to show the msdfs symlinks as directories. Modifies psbuf
1208 to be a directory if it's a msdfs link.
1209 ****************************************************************************/
1211 static bool check_msdfs_link(connection_struct *conn,
1212 const char *pathname,
1213 SMB_STRUCT_STAT *psbuf)
1215 int saved_errno = errno;
1216 if(lp_host_msdfs() &&
1217 lp_msdfs_root(SNUM(conn)) &&
1218 is_msdfs_link(conn, pathname, psbuf)) {
1220 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1221 "as a directory\n",
1222 pathname));
1223 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1224 errno = saved_errno;
1225 return true;
1227 errno = saved_errno;
1228 return false;
1232 /****************************************************************************
1233 Get a level dependent lanman2 dir entry.
1234 ****************************************************************************/
1236 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1237 connection_struct *conn,
1238 uint16 flags2,
1239 const char *path_mask,
1240 uint32 dirtype,
1241 int info_level,
1242 int requires_resume_key,
1243 bool dont_descend,
1244 bool ask_sharemode,
1245 char **ppdata,
1246 char *base_data,
1247 char *end_data,
1248 int space_remaining,
1249 bool *out_of_space,
1250 bool *got_exact_match,
1251 int *last_entry_off,
1252 struct ea_list *name_list)
1254 const char *dname;
1255 bool found = False;
1256 SMB_STRUCT_STAT sbuf;
1257 const char *mask = NULL;
1258 char *pathreal = NULL;
1259 const char *fname = NULL;
1260 char *p, *q, *pdata = *ppdata;
1261 uint32 reskey=0;
1262 long prev_dirpos=0;
1263 uint32 mode=0;
1264 SMB_OFF_T file_size = 0;
1265 SMB_BIG_UINT allocation_size = 0;
1266 uint32 len;
1267 struct timespec mdate_ts, adate_ts, create_date_ts;
1268 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1269 char *nameptr;
1270 char *last_entry_ptr;
1271 bool was_8_3;
1272 uint32 nt_extmode; /* Used for NT connections instead of mode */
1273 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1274 bool check_mangled_names = lp_manglednames(conn->params);
1275 char mangled_name[13]; /* mangled 8.3 name. */
1277 *out_of_space = False;
1278 *got_exact_match = False;
1280 ZERO_STRUCT(mdate_ts);
1281 ZERO_STRUCT(adate_ts);
1282 ZERO_STRUCT(create_date_ts);
1284 if (!conn->dirptr) {
1285 return(False);
1288 p = strrchr_m(path_mask,'/');
1289 if(p != NULL) {
1290 if(p[1] == '\0') {
1291 mask = talloc_strdup(ctx,"*.*");
1292 } else {
1293 mask = p+1;
1295 } else {
1296 mask = path_mask;
1299 while (!found) {
1300 bool got_match;
1301 bool ms_dfs_link = False;
1303 /* Needed if we run out of space */
1304 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1305 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1308 * Due to bugs in NT client redirectors we are not using
1309 * resume keys any more - set them to zero.
1310 * Check out the related comments in findfirst/findnext.
1311 * JRA.
1314 reskey = 0;
1316 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1317 (long)conn->dirptr,curr_dirpos));
1319 if (!dname) {
1320 return(False);
1324 * fname may get mangled, dname is never mangled.
1325 * Whenever we're accessing the filesystem we use
1326 * pathreal which is composed from dname.
1329 pathreal = NULL;
1330 fname = dname;
1332 /* Mangle fname if it's an illegal name. */
1333 if (mangle_must_mangle(dname,conn->params)) {
1334 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1335 continue; /* Error - couldn't mangle. */
1337 fname = mangled_name;
1340 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1341 got_match = mask_match(fname, mask, conn->case_sensitive);
1344 if(!got_match && check_mangled_names &&
1345 !mangle_is_8_3(fname, False, conn->params)) {
1347 * It turns out that NT matches wildcards against
1348 * both long *and* short names. This may explain some
1349 * of the wildcard wierdness from old DOS clients
1350 * that some people have been seeing.... JRA.
1352 /* Force the mangling into 8.3. */
1353 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1354 continue; /* Error - couldn't mangle. */
1357 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1358 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1362 if (got_match) {
1363 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1365 if (dont_descend && !isdots) {
1366 continue;
1369 if (needslash) {
1370 pathreal = NULL;
1371 pathreal = talloc_asprintf(ctx,
1372 "%s/%s",
1373 conn->dirpath,
1374 dname);
1375 } else {
1376 pathreal = talloc_asprintf(ctx,
1377 "%s%s",
1378 conn->dirpath,
1379 dname);
1382 if (!pathreal) {
1383 return False;
1386 if (INFO_LEVEL_IS_UNIX(info_level)) {
1387 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1388 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1389 pathreal,strerror(errno)));
1390 TALLOC_FREE(pathreal);
1391 continue;
1393 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1394 /* Needed to show the msdfs symlinks as
1395 * directories */
1397 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1398 if (!ms_dfs_link) {
1399 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1400 pathreal,strerror(errno)));
1401 TALLOC_FREE(pathreal);
1402 continue;
1406 if (ms_dfs_link) {
1407 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1408 } else {
1409 mode = dos_mode(conn,pathreal,&sbuf);
1412 if (!dir_check_ftype(conn,mode,dirtype)) {
1413 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1414 TALLOC_FREE(pathreal);
1415 continue;
1418 if (!(mode & aDIR)) {
1419 file_size = get_file_size(sbuf);
1421 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1423 mdate_ts = get_mtimespec(&sbuf);
1424 adate_ts = get_atimespec(&sbuf);
1425 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1427 if (ask_sharemode) {
1428 struct timespec write_time_ts;
1429 struct file_id fileid;
1431 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1432 get_file_infos(fileid, NULL, &write_time_ts);
1433 if (!null_timespec(write_time_ts)) {
1434 mdate_ts = write_time_ts;
1438 if (lp_dos_filetime_resolution(SNUM(conn))) {
1439 dos_filetime_timespec(&create_date_ts);
1440 dos_filetime_timespec(&mdate_ts);
1441 dos_filetime_timespec(&adate_ts);
1444 create_date = convert_timespec_to_time_t(create_date_ts);
1445 mdate = convert_timespec_to_time_t(mdate_ts);
1446 adate = convert_timespec_to_time_t(adate_ts);
1448 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1450 found = True;
1452 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1456 p = pdata;
1457 last_entry_ptr = p;
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1465 SIVAL(p,0,reskey);
1466 p += 4;
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1473 SSVAL(p,20,mode);
1474 p += 23;
1475 nameptr = p;
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1481 STR_TERMINATE);
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483 if (len > 2) {
1484 SCVAL(nameptr, -1, len - 2);
1485 } else {
1486 SCVAL(nameptr, -1, 0);
1488 } else {
1489 if (len > 1) {
1490 SCVAL(nameptr, -1, len - 1);
1491 } else {
1492 SCVAL(nameptr, -1, 0);
1495 p += len;
1496 break;
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1501 SIVAL(p,0,reskey);
1502 p += 4;
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1509 SSVAL(p,20,mode);
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1514 p += 27;
1515 nameptr = p - 1;
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 if (len > 2) {
1521 len -= 2;
1522 } else {
1523 len = 0;
1525 } else {
1526 if (len > 1) {
1527 len -= 1;
1528 } else {
1529 len = 0;
1532 SCVAL(nameptr,0,len);
1533 p += len;
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535 break;
1537 case SMB_FIND_EA_LIST:
1539 struct ea_list *file_list = NULL;
1540 size_t ea_len = 0;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if (!name_list) {
1544 return False;
1546 if(requires_resume_key) {
1547 SIVAL(p,0,reskey);
1548 p += 4;
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1555 SSVAL(p,20,mode);
1556 p += 22; /* p now points to the EA area. */
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573 nameptr = p;
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 if (len > 2) {
1579 len -= 2;
1580 } else {
1581 len = 0;
1583 } else {
1584 if (len > 1) {
1585 len -= 1;
1586 } else {
1587 len = 0;
1590 SCVAL(nameptr,0,len);
1591 p += len + 1;
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 break;
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599 p += 4;
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(p,create_date_ts); p += 8;
1602 put_long_date_timespec(p,adate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1612 p += 4;
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1620 conn->params)) {
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1628 if (len < 24) {
1629 memset(p + 2 + len,'\0',24 - len);
1631 SSVAL(p, 0, len);
1632 } else {
1633 memset(p,'\0',26);
1635 p += 2 + 24;
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1639 SIVAL(q,0,len);
1640 p += len;
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1644 SIVAL(pdata,0,len);
1645 p = pdata + len;
1646 break;
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650 p += 4;
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(p,create_date_ts); p += 8;
1653 put_long_date_timespec(p,adate_ts); p += 8;
1654 put_long_date_timespec(p,mdate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,len);
1663 p += 4 + len;
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1667 SIVAL(pdata,0,len);
1668 p = pdata + len;
1669 break;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673 p += 4;
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(p,create_date_ts); p += 8;
1676 put_long_date_timespec(p,adate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1686 p +=4;
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1691 SIVAL(q, 0, len);
1692 p += len;
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len);
1698 p = pdata + len;
1699 break;
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703 p += 4;
1704 SIVAL(p,0,reskey); p += 4;
1705 p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1711 SIVAL(p, -4, len);
1712 p += len;
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len);
1717 p = pdata + len;
1718 break;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722 p += 4;
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(p,create_date_ts); p += 8;
1725 put_long_date_timespec(p,adate_ts); p += 8;
1726 put_long_date_timespec(p,mdate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p +=4;
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q, 0, len);
1744 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(p,create_date_ts); p += 8;
1758 put_long_date_timespec(p,adate_ts); p += 8;
1759 put_long_date_timespec(p,mdate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p +=4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 SSVAL(p, 0, len);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 26;
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(q,0,len);
1800 p += len;
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1804 SIVAL(pdata,0,len);
1805 p = pdata + len;
1806 break;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1812 p+= 4;
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1820 NULL, &sbuf);
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE);
1824 } else {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1827 NULL, &sbuf);
1828 nameptr = p;
1829 p += 4;
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1835 p += len;
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1841 p = pdata + len;
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1844 break;
1846 default:
1847 return(False);
1851 if (PTR_DIFF(p,pdata) > space_remaining) {
1852 /* Move the dirptr back to prev_dirpos */
1853 dptr_SeekDir(conn->dirptr, prev_dirpos);
1854 *out_of_space = True;
1855 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1856 return False; /* Not finished - just out of space */
1859 /* Setup the last entry pointer, as an offset from base_data */
1860 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1861 /* Advance the data pointer to the next slot */
1862 *ppdata = p;
1864 return(found);
1867 /****************************************************************************
1868 Reply to a TRANS2_FINDFIRST.
1869 ****************************************************************************/
1871 static void call_trans2findfirst(connection_struct *conn,
1872 struct smb_request *req,
1873 char **pparams, int total_params,
1874 char **ppdata, int total_data,
1875 unsigned int max_data_bytes)
1877 /* We must be careful here that we don't return more than the
1878 allowed number of data bytes. If this means returning fewer than
1879 maxentries then so be it. We assume that the redirector has
1880 enough room for the fixed number of parameter bytes it has
1881 requested. */
1882 char *params = *pparams;
1883 char *pdata = *ppdata;
1884 char *data_end;
1885 uint32 dirtype;
1886 int maxentries;
1887 uint16 findfirst_flags;
1888 bool close_after_first;
1889 bool close_if_end;
1890 bool requires_resume_key;
1891 int info_level;
1892 char *directory = NULL;
1893 char *mask = NULL;
1894 char *p;
1895 int last_entry_off=0;
1896 int dptr_num = -1;
1897 int numentries = 0;
1898 int i;
1899 bool finished = False;
1900 bool dont_descend = False;
1901 bool out_of_space = False;
1902 int space_remaining;
1903 bool mask_contains_wcard = False;
1904 SMB_STRUCT_STAT sbuf;
1905 struct ea_list *ea_list = NULL;
1906 NTSTATUS ntstatus = NT_STATUS_OK;
1907 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1908 TALLOC_CTX *ctx = talloc_tos();
1910 if (total_params < 13) {
1911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1912 return;
1915 dirtype = SVAL(params,0);
1916 maxentries = SVAL(params,2);
1917 findfirst_flags = SVAL(params,4);
1918 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1919 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1920 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1921 info_level = SVAL(params,6);
1923 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1924 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1925 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1926 info_level, max_data_bytes));
1928 if (!maxentries) {
1929 /* W2K3 seems to treat zero as 1. */
1930 maxentries = 1;
1933 switch (info_level) {
1934 case SMB_FIND_INFO_STANDARD:
1935 case SMB_FIND_EA_SIZE:
1936 case SMB_FIND_EA_LIST:
1937 case SMB_FIND_FILE_DIRECTORY_INFO:
1938 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_NAMES_INFO:
1940 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1941 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1942 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1943 break;
1944 case SMB_FIND_FILE_UNIX:
1945 case SMB_FIND_FILE_UNIX_INFO2:
1946 /* Always use filesystem for UNIX mtime query. */
1947 ask_sharemode = false;
1948 if (!lp_unix_extensions()) {
1949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1950 return;
1952 break;
1953 default:
1954 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1955 return;
1958 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1959 params+12, total_params - 12,
1960 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1961 if (!NT_STATUS_IS_OK(ntstatus)) {
1962 reply_nterror(req, ntstatus);
1963 return;
1966 ntstatus = resolve_dfspath_wcard(ctx, conn,
1967 req->flags2 & FLAGS2_DFS_PATHNAMES,
1968 directory,
1969 &directory,
1970 &mask_contains_wcard);
1971 if (!NT_STATUS_IS_OK(ntstatus)) {
1972 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1973 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1974 ERRSRV, ERRbadpath);
1975 return;
1977 reply_nterror(req, ntstatus);
1978 return;
1981 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1982 if (!NT_STATUS_IS_OK(ntstatus)) {
1983 reply_nterror(req, ntstatus);
1984 return;
1987 ntstatus = check_name(conn, directory);
1988 if (!NT_STATUS_IS_OK(ntstatus)) {
1989 reply_nterror(req, ntstatus);
1990 return;
1993 p = strrchr_m(directory,'/');
1994 if(p == NULL) {
1995 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1996 if((directory[0] == '.') && (directory[1] == '\0')) {
1997 mask = talloc_strdup(ctx,"*");
1998 if (!mask) {
1999 reply_nterror(req, NT_STATUS_NO_MEMORY);
2000 return;
2002 mask_contains_wcard = True;
2004 directory = talloc_strdup(talloc_tos(), "./");
2005 if (!directory) {
2006 reply_nterror(req, NT_STATUS_NO_MEMORY);
2007 return;
2009 } else {
2010 *p = 0;
2013 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2015 if (info_level == SMB_FIND_EA_LIST) {
2016 uint32 ea_size;
2018 if (total_data < 4) {
2019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2020 return;
2023 ea_size = IVAL(pdata,0);
2024 if (ea_size != total_data) {
2025 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2026 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 return;
2031 if (!lp_ea_support(SNUM(conn))) {
2032 reply_doserror(req, ERRDOS, ERReasnotsupported);
2033 return;
2036 /* Pull out the list of names. */
2037 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2038 if (!ea_list) {
2039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 return;
2044 *ppdata = (char *)SMB_REALLOC(
2045 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2046 if(*ppdata == NULL ) {
2047 reply_nterror(req, NT_STATUS_NO_MEMORY);
2048 return;
2050 pdata = *ppdata;
2051 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2053 /* Realloc the params space */
2054 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2055 if (*pparams == NULL) {
2056 reply_nterror(req, NT_STATUS_NO_MEMORY);
2057 return;
2059 params = *pparams;
2061 /* Save the wildcard match and attribs we are using on this directory -
2062 needed as lanman2 assumes these are being saved between calls */
2064 ntstatus = dptr_create(conn,
2065 directory,
2066 False,
2067 True,
2068 req->smbpid,
2069 mask,
2070 mask_contains_wcard,
2071 dirtype,
2072 &conn->dirptr);
2074 if (!NT_STATUS_IS_OK(ntstatus)) {
2075 reply_nterror(req, ntstatus);
2076 return;
2079 dptr_num = dptr_dnum(conn->dirptr);
2080 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2082 /* We don't need to check for VOL here as this is returned by
2083 a different TRANS2 call. */
2085 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2086 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2087 dont_descend = True;
2089 p = pdata;
2090 space_remaining = max_data_bytes;
2091 out_of_space = False;
2093 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2094 bool got_exact_match = False;
2096 /* this is a heuristic to avoid seeking the dirptr except when
2097 absolutely necessary. It allows for a filename of about 40 chars */
2098 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2099 out_of_space = True;
2100 finished = False;
2101 } else {
2102 finished = !get_lanman2_dir_entry(ctx,
2103 conn,
2104 req->flags2,
2105 mask,dirtype,info_level,
2106 requires_resume_key,dont_descend,
2107 ask_sharemode,
2108 &p,pdata,data_end,
2109 space_remaining, &out_of_space,
2110 &got_exact_match,
2111 &last_entry_off, ea_list);
2114 if (finished && out_of_space)
2115 finished = False;
2117 if (!finished && !out_of_space)
2118 numentries++;
2121 * As an optimisation if we know we aren't looking
2122 * for a wildcard name (ie. the name matches the wildcard exactly)
2123 * then we can finish on any (first) match.
2124 * This speeds up large directory searches. JRA.
2127 if(got_exact_match)
2128 finished = True;
2130 /* Ensure space_remaining never goes -ve. */
2131 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2132 space_remaining = 0;
2133 out_of_space = true;
2134 } else {
2135 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2139 /* Check if we can close the dirptr */
2140 if(close_after_first || (finished && close_if_end)) {
2141 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2142 dptr_close(&dptr_num);
2146 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2147 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2148 * the protocol level is less than NT1. Tested with smbclient. JRA.
2149 * This should fix the OS/2 client bug #2335.
2152 if(numentries == 0) {
2153 dptr_close(&dptr_num);
2154 if (Protocol < PROTOCOL_NT1) {
2155 reply_doserror(req, ERRDOS, ERRnofiles);
2156 return;
2157 } else {
2158 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2159 ERRDOS, ERRbadfile);
2160 return;
2164 /* At this point pdata points to numentries directory entries. */
2166 /* Set up the return parameter block */
2167 SSVAL(params,0,dptr_num);
2168 SSVAL(params,2,numentries);
2169 SSVAL(params,4,finished);
2170 SSVAL(params,6,0); /* Never an EA error */
2171 SSVAL(params,8,last_entry_off);
2173 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2174 max_data_bytes);
2176 if ((! *directory) && dptr_path(dptr_num)) {
2177 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2178 if (!directory) {
2179 reply_nterror(req, NT_STATUS_NO_MEMORY);
2183 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2184 smb_fn_name(CVAL(req->inbuf,smb_com)),
2185 mask, directory, dirtype, numentries ) );
2188 * Force a name mangle here to ensure that the
2189 * mask as an 8.3 name is top of the mangled cache.
2190 * The reasons for this are subtle. Don't remove
2191 * this code unless you know what you are doing
2192 * (see PR#13758). JRA.
2195 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2196 char mangled_name[13];
2197 name_to_8_3(mask, mangled_name, True, conn->params);
2200 return;
2203 /****************************************************************************
2204 Reply to a TRANS2_FINDNEXT.
2205 ****************************************************************************/
2207 static void call_trans2findnext(connection_struct *conn,
2208 struct smb_request *req,
2209 char **pparams, int total_params,
2210 char **ppdata, int total_data,
2211 unsigned int max_data_bytes)
2213 /* We must be careful here that we don't return more than the
2214 allowed number of data bytes. If this means returning fewer than
2215 maxentries then so be it. We assume that the redirector has
2216 enough room for the fixed number of parameter bytes it has
2217 requested. */
2218 char *params = *pparams;
2219 char *pdata = *ppdata;
2220 char *data_end;
2221 int dptr_num;
2222 int maxentries;
2223 uint16 info_level;
2224 uint32 resume_key;
2225 uint16 findnext_flags;
2226 bool close_after_request;
2227 bool close_if_end;
2228 bool requires_resume_key;
2229 bool continue_bit;
2230 bool mask_contains_wcard = False;
2231 char *resume_name = NULL;
2232 const char *mask = NULL;
2233 const char *directory = NULL;
2234 char *p = NULL;
2235 uint16 dirtype;
2236 int numentries = 0;
2237 int i, last_entry_off=0;
2238 bool finished = False;
2239 bool dont_descend = False;
2240 bool out_of_space = False;
2241 int space_remaining;
2242 struct ea_list *ea_list = NULL;
2243 NTSTATUS ntstatus = NT_STATUS_OK;
2244 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2245 TALLOC_CTX *ctx = talloc_tos();
2247 if (total_params < 13) {
2248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2249 return;
2252 dptr_num = SVAL(params,0);
2253 maxentries = SVAL(params,2);
2254 info_level = SVAL(params,4);
2255 resume_key = IVAL(params,6);
2256 findnext_flags = SVAL(params,10);
2257 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2258 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2259 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2260 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2262 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2263 params+12,
2264 total_params - 12, STR_TERMINATE, &ntstatus,
2265 &mask_contains_wcard);
2266 if (!NT_STATUS_IS_OK(ntstatus)) {
2267 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2268 complain (it thinks we're asking for the directory above the shared
2269 path or an invalid name). Catch this as the resume name is only compared, never used in
2270 a file access. JRA. */
2271 srvstr_pull_talloc(ctx, params, req->flags2,
2272 &resume_name, params+12,
2273 total_params - 12,
2274 STR_TERMINATE);
2276 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2277 reply_nterror(req, ntstatus);
2278 return;
2282 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2283 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2284 resume_key = %d resume name = %s continue=%d level = %d\n",
2285 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2286 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2288 if (!maxentries) {
2289 /* W2K3 seems to treat zero as 1. */
2290 maxentries = 1;
2293 switch (info_level) {
2294 case SMB_FIND_INFO_STANDARD:
2295 case SMB_FIND_EA_SIZE:
2296 case SMB_FIND_EA_LIST:
2297 case SMB_FIND_FILE_DIRECTORY_INFO:
2298 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_NAMES_INFO:
2300 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2301 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2302 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2303 break;
2304 case SMB_FIND_FILE_UNIX:
2305 case SMB_FIND_FILE_UNIX_INFO2:
2306 /* Always use filesystem for UNIX mtime query. */
2307 ask_sharemode = false;
2308 if (!lp_unix_extensions()) {
2309 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2310 return;
2312 break;
2313 default:
2314 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 return;
2318 if (info_level == SMB_FIND_EA_LIST) {
2319 uint32 ea_size;
2321 if (total_data < 4) {
2322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2323 return;
2326 ea_size = IVAL(pdata,0);
2327 if (ea_size != total_data) {
2328 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2329 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 return;
2334 if (!lp_ea_support(SNUM(conn))) {
2335 reply_doserror(req, ERRDOS, ERReasnotsupported);
2336 return;
2339 /* Pull out the list of names. */
2340 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2341 if (!ea_list) {
2342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2343 return;
2347 *ppdata = (char *)SMB_REALLOC(
2348 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2349 if(*ppdata == NULL) {
2350 reply_nterror(req, NT_STATUS_NO_MEMORY);
2351 return;
2354 pdata = *ppdata;
2355 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2357 /* Realloc the params space */
2358 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2359 if(*pparams == NULL ) {
2360 reply_nterror(req, NT_STATUS_NO_MEMORY);
2361 return;
2364 params = *pparams;
2366 /* Check that the dptr is valid */
2367 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2368 reply_doserror(req, ERRDOS, ERRnofiles);
2369 return;
2372 string_set(&conn->dirpath,dptr_path(dptr_num));
2374 /* Get the wildcard mask from the dptr */
2375 if((p = dptr_wcard(dptr_num))== NULL) {
2376 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2377 reply_doserror(req, ERRDOS, ERRnofiles);
2378 return;
2381 mask = p;
2382 directory = conn->dirpath;
2384 /* Get the attr mask from the dptr */
2385 dirtype = dptr_attr(dptr_num);
2387 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2388 dptr_num, mask, dirtype,
2389 (long)conn->dirptr,
2390 dptr_TellDir(conn->dirptr)));
2392 /* We don't need to check for VOL here as this is returned by
2393 a different TRANS2 call. */
2395 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2396 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2397 dont_descend = True;
2399 p = pdata;
2400 space_remaining = max_data_bytes;
2401 out_of_space = False;
2404 * Seek to the correct position. We no longer use the resume key but
2405 * depend on the last file name instead.
2408 if(*resume_name && !continue_bit) {
2409 SMB_STRUCT_STAT st;
2411 long current_pos = 0;
2413 * Remember, name_to_8_3 is called by
2414 * get_lanman2_dir_entry(), so the resume name
2415 * could be mangled. Ensure we check the unmangled name.
2418 if (mangle_is_mangled(resume_name, conn->params)) {
2419 char *new_resume_name = NULL;
2420 mangle_lookup_name_from_8_3(ctx,
2421 resume_name,
2422 &new_resume_name,
2423 conn->params);
2424 if (new_resume_name) {
2425 resume_name = new_resume_name;
2430 * Fix for NT redirector problem triggered by resume key indexes
2431 * changing between directory scans. We now return a resume key of 0
2432 * and instead look for the filename to continue from (also given
2433 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2434 * findfirst/findnext (as is usual) then the directory pointer
2435 * should already be at the correct place.
2438 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2439 } /* end if resume_name && !continue_bit */
2441 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2442 bool got_exact_match = False;
2444 /* this is a heuristic to avoid seeking the dirptr except when
2445 absolutely necessary. It allows for a filename of about 40 chars */
2446 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2447 out_of_space = True;
2448 finished = False;
2449 } else {
2450 finished = !get_lanman2_dir_entry(ctx,
2451 conn,
2452 req->flags2,
2453 mask,dirtype,info_level,
2454 requires_resume_key,dont_descend,
2455 ask_sharemode,
2456 &p,pdata,data_end,
2457 space_remaining, &out_of_space,
2458 &got_exact_match,
2459 &last_entry_off, ea_list);
2462 if (finished && out_of_space)
2463 finished = False;
2465 if (!finished && !out_of_space)
2466 numentries++;
2469 * As an optimisation if we know we aren't looking
2470 * for a wildcard name (ie. the name matches the wildcard exactly)
2471 * then we can finish on any (first) match.
2472 * This speeds up large directory searches. JRA.
2475 if(got_exact_match)
2476 finished = True;
2478 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2481 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2482 smb_fn_name(CVAL(req->inbuf,smb_com)),
2483 mask, directory, dirtype, numentries ) );
2485 /* Check if we can close the dirptr */
2486 if(close_after_request || (finished && close_if_end)) {
2487 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2488 dptr_close(&dptr_num); /* This frees up the saved mask */
2491 /* Set up the return parameter block */
2492 SSVAL(params,0,numentries);
2493 SSVAL(params,2,finished);
2494 SSVAL(params,4,0); /* Never an EA error */
2495 SSVAL(params,6,last_entry_off);
2497 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2498 max_data_bytes);
2500 return;
2503 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2505 E_md4hash(lp_servicename(SNUM(conn)),objid);
2506 return objid;
2509 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2511 SMB_ASSERT(extended_info != NULL);
2513 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2514 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2515 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2516 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2517 #ifdef SAMBA_VERSION_REVISION
2518 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2519 #endif
2520 extended_info->samba_subversion = 0;
2521 #ifdef SAMBA_VERSION_RC_RELEASE
2522 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2523 #else
2524 #ifdef SAMBA_VERSION_PRE_RELEASE
2525 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2526 #endif
2527 #endif
2528 #ifdef SAMBA_VERSION_VENDOR_PATCH
2529 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2530 #endif
2531 extended_info->samba_gitcommitdate = 0;
2532 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2533 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2534 #endif
2536 memset(extended_info->samba_version_string, 0,
2537 sizeof(extended_info->samba_version_string));
2539 snprintf (extended_info->samba_version_string,
2540 sizeof(extended_info->samba_version_string),
2541 "%s", samba_version_string());
2544 /****************************************************************************
2545 Reply to a TRANS2_QFSINFO (query filesystem info).
2546 ****************************************************************************/
2548 static void call_trans2qfsinfo(connection_struct *conn,
2549 struct smb_request *req,
2550 char **pparams, int total_params,
2551 char **ppdata, int total_data,
2552 unsigned int max_data_bytes)
2554 char *pdata, *end_data;
2555 char *params = *pparams;
2556 uint16 info_level;
2557 int data_len, len;
2558 SMB_STRUCT_STAT st;
2559 const char *vname = volume_label(SNUM(conn));
2560 int snum = SNUM(conn);
2561 char *fstype = lp_fstype(SNUM(conn));
2562 uint32 additional_flags = 0;
2564 if (total_params < 2) {
2565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2566 return;
2569 info_level = SVAL(params,0);
2571 if (IS_IPC(conn)) {
2572 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2573 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2574 "info level (0x%x) on IPC$.\n",
2575 (unsigned int)info_level));
2576 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2577 return;
2581 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2582 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2583 DEBUG(0,("call_trans2qfsinfo: encryption required "
2584 "and info level 0x%x sent.\n",
2585 (unsigned int)info_level));
2586 exit_server_cleanly("encryption required "
2587 "on connection");
2588 return;
2592 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2594 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2595 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2596 reply_doserror(req, ERRSRV, ERRinvdevice);
2597 return;
2600 *ppdata = (char *)SMB_REALLOC(
2601 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2602 if (*ppdata == NULL ) {
2603 reply_nterror(req, NT_STATUS_NO_MEMORY);
2604 return;
2607 pdata = *ppdata;
2608 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2609 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2611 switch (info_level) {
2612 case SMB_INFO_ALLOCATION:
2614 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2615 data_len = 18;
2616 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2617 reply_unixerror(req, ERRHRD, ERRgeneral);
2618 return;
2621 block_size = lp_block_size(snum);
2622 if (bsize < block_size) {
2623 SMB_BIG_UINT factor = block_size/bsize;
2624 bsize = block_size;
2625 dsize /= factor;
2626 dfree /= factor;
2628 if (bsize > block_size) {
2629 SMB_BIG_UINT factor = bsize/block_size;
2630 bsize = block_size;
2631 dsize *= factor;
2632 dfree *= factor;
2634 bytes_per_sector = 512;
2635 sectors_per_unit = bsize/bytes_per_sector;
2637 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2638 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2639 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2641 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2642 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2643 SIVAL(pdata,l1_cUnit,dsize);
2644 SIVAL(pdata,l1_cUnitAvail,dfree);
2645 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2646 break;
2649 case SMB_INFO_VOLUME:
2650 /* Return volume name */
2652 * Add volume serial number - hash of a combination of
2653 * the called hostname and the service name.
2655 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2657 * Win2k3 and previous mess this up by sending a name length
2658 * one byte short. I believe only older clients (OS/2 Win9x) use
2659 * this call so try fixing this by adding a terminating null to
2660 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2662 len = srvstr_push(
2663 pdata, req->flags2,
2664 pdata+l2_vol_szVolLabel, vname,
2665 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2666 STR_NOALIGN|STR_TERMINATE);
2667 SCVAL(pdata,l2_vol_cch,len);
2668 data_len = l2_vol_szVolLabel + len;
2669 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2670 (unsigned)st.st_ctime, len, vname));
2671 break;
2673 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2674 case SMB_FS_ATTRIBUTE_INFORMATION:
2676 additional_flags = 0;
2677 #if defined(HAVE_SYS_QUOTAS)
2678 additional_flags |= FILE_VOLUME_QUOTAS;
2679 #endif
2681 if(lp_nt_acl_support(SNUM(conn))) {
2682 additional_flags |= FILE_PERSISTENT_ACLS;
2685 /* Capabilities are filled in at connection time through STATVFS call */
2686 additional_flags |= conn->fs_capabilities;
2688 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2689 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2690 additional_flags); /* FS ATTRIBUTES */
2692 SIVAL(pdata,4,255); /* Max filename component length */
2693 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2694 and will think we can't do long filenames */
2695 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2696 PTR_DIFF(end_data, pdata+12),
2697 STR_UNICODE);
2698 SIVAL(pdata,8,len);
2699 data_len = 12 + len;
2700 break;
2702 case SMB_QUERY_FS_LABEL_INFO:
2703 case SMB_FS_LABEL_INFORMATION:
2704 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2705 PTR_DIFF(end_data, pdata+4), 0);
2706 data_len = 4 + len;
2707 SIVAL(pdata,0,len);
2708 break;
2710 case SMB_QUERY_FS_VOLUME_INFO:
2711 case SMB_FS_VOLUME_INFORMATION:
2714 * Add volume serial number - hash of a combination of
2715 * the called hostname and the service name.
2717 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2718 (str_checksum(get_local_machine_name())<<16));
2720 /* Max label len is 32 characters. */
2721 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2722 PTR_DIFF(end_data, pdata+18),
2723 STR_UNICODE);
2724 SIVAL(pdata,12,len);
2725 data_len = 18+len;
2727 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2728 (int)strlen(vname),vname, lp_servicename(snum)));
2729 break;
2731 case SMB_QUERY_FS_SIZE_INFO:
2732 case SMB_FS_SIZE_INFORMATION:
2734 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2735 data_len = 24;
2736 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2737 reply_unixerror(req, ERRHRD, ERRgeneral);
2738 return;
2740 block_size = lp_block_size(snum);
2741 if (bsize < block_size) {
2742 SMB_BIG_UINT factor = block_size/bsize;
2743 bsize = block_size;
2744 dsize /= factor;
2745 dfree /= factor;
2747 if (bsize > block_size) {
2748 SMB_BIG_UINT factor = bsize/block_size;
2749 bsize = block_size;
2750 dsize *= factor;
2751 dfree *= factor;
2753 bytes_per_sector = 512;
2754 sectors_per_unit = bsize/bytes_per_sector;
2755 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2756 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2757 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2758 SBIG_UINT(pdata,0,dsize);
2759 SBIG_UINT(pdata,8,dfree);
2760 SIVAL(pdata,16,sectors_per_unit);
2761 SIVAL(pdata,20,bytes_per_sector);
2762 break;
2765 case SMB_FS_FULL_SIZE_INFORMATION:
2767 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2768 data_len = 32;
2769 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2770 reply_unixerror(req, ERRHRD, ERRgeneral);
2771 return;
2773 block_size = lp_block_size(snum);
2774 if (bsize < block_size) {
2775 SMB_BIG_UINT factor = block_size/bsize;
2776 bsize = block_size;
2777 dsize /= factor;
2778 dfree /= factor;
2780 if (bsize > block_size) {
2781 SMB_BIG_UINT factor = bsize/block_size;
2782 bsize = block_size;
2783 dsize *= factor;
2784 dfree *= factor;
2786 bytes_per_sector = 512;
2787 sectors_per_unit = bsize/bytes_per_sector;
2788 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2789 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2790 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2791 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2792 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2793 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2794 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2795 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2796 break;
2799 case SMB_QUERY_FS_DEVICE_INFO:
2800 case SMB_FS_DEVICE_INFORMATION:
2801 data_len = 8;
2802 SIVAL(pdata,0,0); /* dev type */
2803 SIVAL(pdata,4,0); /* characteristics */
2804 break;
2806 #ifdef HAVE_SYS_QUOTAS
2807 case SMB_FS_QUOTA_INFORMATION:
2809 * what we have to send --metze:
2811 * Unknown1: 24 NULL bytes
2812 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2813 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2814 * Quota Flags: 2 byte :
2815 * Unknown3: 6 NULL bytes
2817 * 48 bytes total
2819 * details for Quota Flags:
2821 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2822 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2823 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2824 * 0x0001 Enable Quotas: enable quota for this fs
2828 /* we need to fake up a fsp here,
2829 * because its not send in this call
2831 files_struct fsp;
2832 SMB_NTQUOTA_STRUCT quotas;
2834 ZERO_STRUCT(fsp);
2835 ZERO_STRUCT(quotas);
2837 fsp.conn = conn;
2838 fsp.fnum = -1;
2840 /* access check */
2841 if (conn->server_info->utok.uid != 0) {
2842 DEBUG(0,("set_user_quota: access_denied "
2843 "service [%s] user [%s]\n",
2844 lp_servicename(SNUM(conn)),
2845 conn->server_info->unix_name));
2846 reply_doserror(req, ERRDOS, ERRnoaccess);
2847 return;
2850 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2851 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2852 reply_doserror(req, ERRSRV, ERRerror);
2853 return;
2856 data_len = 48;
2858 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2860 /* Unknown1 24 NULL bytes*/
2861 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2862 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2863 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2865 /* Default Soft Quota 8 bytes */
2866 SBIG_UINT(pdata,24,quotas.softlim);
2868 /* Default Hard Quota 8 bytes */
2869 SBIG_UINT(pdata,32,quotas.hardlim);
2871 /* Quota flag 2 bytes */
2872 SSVAL(pdata,40,quotas.qflags);
2874 /* Unknown3 6 NULL bytes */
2875 SSVAL(pdata,42,0);
2876 SIVAL(pdata,44,0);
2878 break;
2880 #endif /* HAVE_SYS_QUOTAS */
2881 case SMB_FS_OBJECTID_INFORMATION:
2883 unsigned char objid[16];
2884 struct smb_extended_info extended_info;
2885 memcpy(pdata,create_volume_objectid(conn, objid),16);
2886 samba_extended_info_version (&extended_info);
2887 SIVAL(pdata,16,extended_info.samba_magic);
2888 SIVAL(pdata,20,extended_info.samba_version);
2889 SIVAL(pdata,24,extended_info.samba_subversion);
2890 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2891 memcpy(pdata+36,extended_info.samba_version_string,28);
2892 data_len = 64;
2893 break;
2897 * Query the version and capabilities of the CIFS UNIX extensions
2898 * in use.
2901 case SMB_QUERY_CIFS_UNIX_INFO:
2903 bool large_write = lp_min_receive_file_size() &&
2904 !srv_is_signing_active();
2905 bool large_read = !srv_is_signing_active();
2906 int encrypt_caps = 0;
2908 if (!lp_unix_extensions()) {
2909 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2910 return;
2913 switch (conn->encrypt_level) {
2914 case 0:
2915 encrypt_caps = 0;
2916 break;
2917 case 1:
2918 case Auto:
2919 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2920 break;
2921 case Required:
2922 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2923 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2924 large_write = false;
2925 large_read = false;
2926 break;
2929 data_len = 12;
2930 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2931 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2933 /* We have POSIX ACLs, pathname, encryption,
2934 * large read/write, and locking capability. */
2936 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2937 CIFS_UNIX_POSIX_ACLS_CAP|
2938 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2939 CIFS_UNIX_FCNTL_LOCKS_CAP|
2940 CIFS_UNIX_EXTATTR_CAP|
2941 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2942 encrypt_caps|
2943 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2944 (large_write ?
2945 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2946 break;
2949 case SMB_QUERY_POSIX_FS_INFO:
2951 int rc;
2952 vfs_statvfs_struct svfs;
2954 if (!lp_unix_extensions()) {
2955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2956 return;
2959 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2961 if (!rc) {
2962 data_len = 56;
2963 SIVAL(pdata,0,svfs.OptimalTransferSize);
2964 SIVAL(pdata,4,svfs.BlockSize);
2965 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2966 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2967 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2968 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2969 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2970 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2971 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2972 #ifdef EOPNOTSUPP
2973 } else if (rc == EOPNOTSUPP) {
2974 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2975 return;
2976 #endif /* EOPNOTSUPP */
2977 } else {
2978 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2979 reply_doserror(req, ERRSRV, ERRerror);
2980 return;
2982 break;
2985 case SMB_QUERY_POSIX_WHOAMI:
2987 uint32_t flags = 0;
2988 uint32_t sid_bytes;
2989 int i;
2991 if (!lp_unix_extensions()) {
2992 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2993 return;
2996 if (max_data_bytes < 40) {
2997 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2998 return;
3001 /* We ARE guest if global_sid_Builtin_Guests is
3002 * in our list of SIDs.
3004 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3005 conn->server_info->ptok)) {
3006 flags |= SMB_WHOAMI_GUEST;
3009 /* We are NOT guest if global_sid_Authenticated_Users
3010 * is in our list of SIDs.
3012 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3013 conn->server_info->ptok)) {
3014 flags &= ~SMB_WHOAMI_GUEST;
3017 /* NOTE: 8 bytes for UID/GID, irrespective of native
3018 * platform size. This matches
3019 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3021 data_len = 4 /* flags */
3022 + 4 /* flag mask */
3023 + 8 /* uid */
3024 + 8 /* gid */
3025 + 4 /* ngroups */
3026 + 4 /* num_sids */
3027 + 4 /* SID bytes */
3028 + 4 /* pad/reserved */
3029 + (conn->server_info->utok.ngroups * 8)
3030 /* groups list */
3031 + (conn->server_info->ptok->num_sids *
3032 SID_MAX_SIZE)
3033 /* SID list */;
3035 SIVAL(pdata, 0, flags);
3036 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3037 SBIG_UINT(pdata, 8,
3038 (SMB_BIG_UINT)conn->server_info->utok.uid);
3039 SBIG_UINT(pdata, 16,
3040 (SMB_BIG_UINT)conn->server_info->utok.gid);
3043 if (data_len >= max_data_bytes) {
3044 /* Potential overflow, skip the GIDs and SIDs. */
3046 SIVAL(pdata, 24, 0); /* num_groups */
3047 SIVAL(pdata, 28, 0); /* num_sids */
3048 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3049 SIVAL(pdata, 36, 0); /* reserved */
3051 data_len = 40;
3052 break;
3055 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3056 SIVAL(pdata, 28, conn->server_info->num_sids);
3058 /* We walk the SID list twice, but this call is fairly
3059 * infrequent, and I don't expect that it's performance
3060 * sensitive -- jpeach
3062 for (i = 0, sid_bytes = 0;
3063 i < conn->server_info->ptok->num_sids; ++i) {
3064 sid_bytes += ndr_size_dom_sid(
3065 &conn->server_info->ptok->user_sids[i],
3069 /* SID list byte count */
3070 SIVAL(pdata, 32, sid_bytes);
3072 /* 4 bytes pad/reserved - must be zero */
3073 SIVAL(pdata, 36, 0);
3074 data_len = 40;
3076 /* GID list */
3077 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3078 SBIG_UINT(pdata, data_len,
3079 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3080 data_len += 8;
3083 /* SID list */
3084 for (i = 0;
3085 i < conn->server_info->ptok->num_sids; ++i) {
3086 int sid_len = ndr_size_dom_sid(
3087 &conn->server_info->ptok->user_sids[i],
3090 sid_linearize(pdata + data_len, sid_len,
3091 &conn->server_info->ptok->user_sids[i]);
3092 data_len += sid_len;
3095 break;
3098 case SMB_MAC_QUERY_FS_INFO:
3100 * Thursby MAC extension... ONLY on NTFS filesystems
3101 * once we do streams then we don't need this
3103 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3104 data_len = 88;
3105 SIVAL(pdata,84,0x100); /* Don't support mac... */
3106 break;
3108 /* drop through */
3109 default:
3110 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3111 return;
3115 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3116 max_data_bytes);
3118 DEBUG( 4, ( "%s info_level = %d\n",
3119 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3121 return;
3124 /****************************************************************************
3125 Reply to a TRANS2_SETFSINFO (set filesystem info).
3126 ****************************************************************************/
3128 static void call_trans2setfsinfo(connection_struct *conn,
3129 struct smb_request *req,
3130 char **pparams, int total_params,
3131 char **ppdata, int total_data,
3132 unsigned int max_data_bytes)
3134 char *pdata = *ppdata;
3135 char *params = *pparams;
3136 uint16 info_level;
3138 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3140 /* */
3141 if (total_params < 4) {
3142 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3143 total_params));
3144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3145 return;
3148 info_level = SVAL(params,2);
3150 if (IS_IPC(conn)) {
3151 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3152 info_level != SMB_SET_CIFS_UNIX_INFO) {
3153 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3154 "info level (0x%x) on IPC$.\n",
3155 (unsigned int)info_level));
3156 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3157 return;
3161 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3162 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3163 DEBUG(0,("call_trans2setfsinfo: encryption required "
3164 "and info level 0x%x sent.\n",
3165 (unsigned int)info_level));
3166 exit_server_cleanly("encryption required "
3167 "on connection");
3168 return;
3172 switch(info_level) {
3173 case SMB_SET_CIFS_UNIX_INFO:
3175 uint16 client_unix_major;
3176 uint16 client_unix_minor;
3177 uint32 client_unix_cap_low;
3178 uint32 client_unix_cap_high;
3180 if (!lp_unix_extensions()) {
3181 reply_nterror(req,
3182 NT_STATUS_INVALID_LEVEL);
3183 return;
3186 /* There should be 12 bytes of capabilities set. */
3187 if (total_data < 8) {
3188 reply_nterror(
3189 req,
3190 NT_STATUS_INVALID_PARAMETER);
3191 return;
3193 client_unix_major = SVAL(pdata,0);
3194 client_unix_minor = SVAL(pdata,2);
3195 client_unix_cap_low = IVAL(pdata,4);
3196 client_unix_cap_high = IVAL(pdata,8);
3197 /* Just print these values for now. */
3198 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3199 cap_low = 0x%x, cap_high = 0x%x\n",
3200 (unsigned int)client_unix_major,
3201 (unsigned int)client_unix_minor,
3202 (unsigned int)client_unix_cap_low,
3203 (unsigned int)client_unix_cap_high ));
3205 /* Here is where we must switch to posix pathname processing... */
3206 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3207 lp_set_posix_pathnames();
3208 mangle_change_to_posix();
3211 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3212 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3213 /* Client that knows how to do posix locks,
3214 * but not posix open/mkdir operations. Set a
3215 * default type for read/write checks. */
3217 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3220 break;
3223 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3225 NTSTATUS status;
3226 size_t param_len = 0;
3227 size_t data_len = total_data;
3229 if (!lp_unix_extensions()) {
3230 reply_nterror(
3231 req,
3232 NT_STATUS_INVALID_LEVEL);
3233 return;
3236 if (lp_smb_encrypt(SNUM(conn)) == false) {
3237 reply_nterror(
3238 req,
3239 NT_STATUS_NOT_SUPPORTED);
3240 return;
3243 DEBUG( 4,("call_trans2setfsinfo: "
3244 "request transport encryption.\n"));
3246 status = srv_request_encryption_setup(conn,
3247 (unsigned char **)ppdata,
3248 &data_len,
3249 (unsigned char **)pparams,
3250 &param_len);
3252 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3253 !NT_STATUS_IS_OK(status)) {
3254 reply_nterror(req, status);
3255 return;
3258 send_trans2_replies(conn, req,
3259 *pparams,
3260 param_len,
3261 *ppdata,
3262 data_len,
3263 max_data_bytes);
3265 if (NT_STATUS_IS_OK(status)) {
3266 /* Server-side transport
3267 * encryption is now *on*. */
3268 status = srv_encryption_start(conn);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 exit_server_cleanly(
3271 "Failure in setting "
3272 "up encrypted transport");
3275 return;
3278 case SMB_FS_QUOTA_INFORMATION:
3280 files_struct *fsp = NULL;
3281 SMB_NTQUOTA_STRUCT quotas;
3283 ZERO_STRUCT(quotas);
3285 /* access check */
3286 if ((conn->server_info->utok.uid != 0)
3287 ||!CAN_WRITE(conn)) {
3288 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3289 lp_servicename(SNUM(conn)),
3290 conn->server_info->unix_name));
3291 reply_doserror(req, ERRSRV, ERRaccess);
3292 return;
3295 /* note: normaly there're 48 bytes,
3296 * but we didn't use the last 6 bytes for now
3297 * --metze
3299 fsp = file_fsp(SVAL(params,0));
3301 if (!check_fsp_ntquota_handle(conn, req,
3302 fsp)) {
3303 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3304 reply_nterror(
3305 req, NT_STATUS_INVALID_HANDLE);
3306 return;
3309 if (total_data < 42) {
3310 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3311 total_data));
3312 reply_nterror(
3313 req,
3314 NT_STATUS_INVALID_PARAMETER);
3315 return;
3318 /* unknown_1 24 NULL bytes in pdata*/
3320 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3321 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3322 #ifdef LARGE_SMB_OFF_T
3323 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3324 #else /* LARGE_SMB_OFF_T */
3325 if ((IVAL(pdata,28) != 0)&&
3326 ((quotas.softlim != 0xFFFFFFFF)||
3327 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3328 /* more than 32 bits? */
3329 reply_nterror(
3330 req,
3331 NT_STATUS_INVALID_PARAMETER);
3332 return;
3334 #endif /* LARGE_SMB_OFF_T */
3336 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3337 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3338 #ifdef LARGE_SMB_OFF_T
3339 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3340 #else /* LARGE_SMB_OFF_T */
3341 if ((IVAL(pdata,36) != 0)&&
3342 ((quotas.hardlim != 0xFFFFFFFF)||
3343 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3344 /* more than 32 bits? */
3345 reply_nterror(
3346 req,
3347 NT_STATUS_INVALID_PARAMETER);
3348 return;
3350 #endif /* LARGE_SMB_OFF_T */
3352 /* quota_flags 2 bytes **/
3353 quotas.qflags = SVAL(pdata,40);
3355 /* unknown_2 6 NULL bytes follow*/
3357 /* now set the quotas */
3358 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3359 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3360 reply_doserror(req, ERRSRV, ERRerror);
3361 return;
3364 break;
3366 default:
3367 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3368 info_level));
3369 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3370 return;
3371 break;
3375 * sending this reply works fine,
3376 * but I'm not sure it's the same
3377 * like windows do...
3378 * --metze
3380 reply_outbuf(req, 10, 0);
3383 #if defined(HAVE_POSIX_ACLS)
3384 /****************************************************************************
3385 Utility function to count the number of entries in a POSIX acl.
3386 ****************************************************************************/
3388 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3390 unsigned int ace_count = 0;
3391 int entry_id = SMB_ACL_FIRST_ENTRY;
3392 SMB_ACL_ENTRY_T entry;
3394 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3395 /* get_next... */
3396 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3397 entry_id = SMB_ACL_NEXT_ENTRY;
3399 ace_count++;
3401 return ace_count;
3404 /****************************************************************************
3405 Utility function to marshall a POSIX acl into wire format.
3406 ****************************************************************************/
3408 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3410 int entry_id = SMB_ACL_FIRST_ENTRY;
3411 SMB_ACL_ENTRY_T entry;
3413 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3414 SMB_ACL_TAG_T tagtype;
3415 SMB_ACL_PERMSET_T permset;
3416 unsigned char perms = 0;
3417 unsigned int own_grp;
3419 /* get_next... */
3420 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3421 entry_id = SMB_ACL_NEXT_ENTRY;
3424 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3425 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3426 return False;
3429 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3430 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3431 return False;
3434 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3435 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3436 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3438 SCVAL(pdata,1,perms);
3440 switch (tagtype) {
3441 case SMB_ACL_USER_OBJ:
3442 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3443 own_grp = (unsigned int)pst->st_uid;
3444 SIVAL(pdata,2,own_grp);
3445 SIVAL(pdata,6,0);
3446 break;
3447 case SMB_ACL_USER:
3449 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3450 if (!puid) {
3451 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3452 return False;
3454 own_grp = (unsigned int)*puid;
3455 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3456 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3457 SIVAL(pdata,2,own_grp);
3458 SIVAL(pdata,6,0);
3459 break;
3461 case SMB_ACL_GROUP_OBJ:
3462 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3463 own_grp = (unsigned int)pst->st_gid;
3464 SIVAL(pdata,2,own_grp);
3465 SIVAL(pdata,6,0);
3466 break;
3467 case SMB_ACL_GROUP:
3469 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3470 if (!pgid) {
3471 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3472 return False;
3474 own_grp = (unsigned int)*pgid;
3475 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3476 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3477 SIVAL(pdata,2,own_grp);
3478 SIVAL(pdata,6,0);
3479 break;
3481 case SMB_ACL_MASK:
3482 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3483 SIVAL(pdata,2,0xFFFFFFFF);
3484 SIVAL(pdata,6,0xFFFFFFFF);
3485 break;
3486 case SMB_ACL_OTHER:
3487 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3488 SIVAL(pdata,2,0xFFFFFFFF);
3489 SIVAL(pdata,6,0xFFFFFFFF);
3490 break;
3491 default:
3492 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3493 return False;
3495 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3498 return True;
3500 #endif
3502 /****************************************************************************
3503 Store the FILE_UNIX_BASIC info.
3504 ****************************************************************************/
3506 static char *store_file_unix_basic(connection_struct *conn,
3507 char *pdata,
3508 files_struct *fsp,
3509 const SMB_STRUCT_STAT *psbuf)
3511 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3512 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3514 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3515 pdata += 8;
3517 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3518 pdata += 8;
3520 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3521 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3522 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3523 pdata += 24;
3525 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3526 SIVAL(pdata,4,0);
3527 pdata += 8;
3529 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3530 SIVAL(pdata,4,0);
3531 pdata += 8;
3533 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3534 pdata += 4;
3536 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3537 SIVAL(pdata,4,0);
3538 pdata += 8;
3540 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3541 SIVAL(pdata,4,0);
3542 pdata += 8;
3544 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3545 pdata += 8;
3547 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3548 SIVAL(pdata,4,0);
3549 pdata += 8;
3551 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3552 SIVAL(pdata,4,0);
3553 pdata += 8;
3555 return pdata;
3558 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3559 * the chflags(2) (or equivalent) flags.
3561 * XXX: this really should be behind the VFS interface. To do this, we would
3562 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3563 * Each VFS module could then implement its own mapping as appropriate for the
3564 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3566 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3567 info2_flags_map[] =
3569 #ifdef UF_NODUMP
3570 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3571 #endif
3573 #ifdef UF_IMMUTABLE
3574 { UF_IMMUTABLE, EXT_IMMUTABLE },
3575 #endif
3577 #ifdef UF_APPEND
3578 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3579 #endif
3581 #ifdef UF_HIDDEN
3582 { UF_HIDDEN, EXT_HIDDEN },
3583 #endif
3585 /* Do not remove. We need to guarantee that this array has at least one
3586 * entry to build on HP-UX.
3588 { 0, 0 }
3592 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3593 uint32 *smb_fflags, uint32 *smb_fmask)
3595 #ifdef HAVE_STAT_ST_FLAGS
3596 int i;
3598 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3599 *smb_fmask |= info2_flags_map[i].smb_fflag;
3600 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3601 *smb_fflags |= info2_flags_map[i].smb_fflag;
3604 #endif /* HAVE_STAT_ST_FLAGS */
3607 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3608 const uint32 smb_fflags,
3609 const uint32 smb_fmask,
3610 int *stat_fflags)
3612 #ifdef HAVE_STAT_ST_FLAGS
3613 uint32 max_fmask = 0;
3614 int i;
3616 *stat_fflags = psbuf->st_flags;
3618 /* For each flags requested in smb_fmask, check the state of the
3619 * corresponding flag in smb_fflags and set or clear the matching
3620 * stat flag.
3623 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3624 max_fmask |= info2_flags_map[i].smb_fflag;
3625 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3626 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3627 *stat_fflags |= info2_flags_map[i].stat_fflag;
3628 } else {
3629 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3634 /* If smb_fmask is asking to set any bits that are not supported by
3635 * our flag mappings, we should fail.
3637 if ((smb_fmask & max_fmask) != smb_fmask) {
3638 return False;
3641 return True;
3642 #else
3643 return False;
3644 #endif /* HAVE_STAT_ST_FLAGS */
3648 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3649 * of file flags and birth (create) time.
3651 static char *store_file_unix_basic_info2(connection_struct *conn,
3652 char *pdata,
3653 files_struct *fsp,
3654 const SMB_STRUCT_STAT *psbuf)
3656 uint32 file_flags = 0;
3657 uint32 flags_mask = 0;
3659 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3661 /* Create (birth) time 64 bit */
3662 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3663 pdata += 8;
3665 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3666 SIVAL(pdata, 0, file_flags); /* flags */
3667 SIVAL(pdata, 4, flags_mask); /* mask */
3668 pdata += 8;
3670 return pdata;
3673 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3674 const struct stream_struct *streams,
3675 char *data,
3676 unsigned int max_data_bytes,
3677 unsigned int *data_size)
3679 unsigned int i;
3680 unsigned int ofs = 0;
3682 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3683 unsigned int next_offset;
3684 size_t namelen;
3685 smb_ucs2_t *namebuf;
3687 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3688 streams[i].name, &namelen) ||
3689 namelen <= 2)
3691 return NT_STATUS_INVALID_PARAMETER;
3695 * name_buf is now null-terminated, we need to marshall as not
3696 * terminated
3699 namelen -= 2;
3701 SIVAL(data, ofs+4, namelen);
3702 SOFF_T(data, ofs+8, streams[i].size);
3703 SOFF_T(data, ofs+16, streams[i].alloc_size);
3704 memcpy(data+ofs+24, namebuf, namelen);
3705 TALLOC_FREE(namebuf);
3707 next_offset = ofs + 24 + namelen;
3709 if (i == num_streams-1) {
3710 SIVAL(data, ofs, 0);
3712 else {
3713 unsigned int align = ndr_align_size(next_offset, 8);
3715 memset(data+next_offset, 0, align);
3716 next_offset += align;
3718 SIVAL(data, ofs, next_offset - ofs);
3719 ofs = next_offset;
3722 ofs = next_offset;
3725 *data_size = ofs;
3727 return NT_STATUS_OK;
3730 /****************************************************************************
3731 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3732 ****************************************************************************/
3734 static void call_trans2qpipeinfo(connection_struct *conn,
3735 struct smb_request *req,
3736 unsigned int tran_call,
3737 char **pparams, int total_params,
3738 char **ppdata, int total_data,
3739 unsigned int max_data_bytes)
3741 char *params = *pparams;
3742 char *pdata = *ppdata;
3743 unsigned int data_size = 0;
3744 unsigned int param_size = 2;
3745 uint16 info_level;
3746 smb_np_struct *p_pipe = NULL;
3748 if (!params) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750 return;
3753 if (total_params < 4) {
3754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3755 return;
3758 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3759 if (p_pipe == NULL) {
3760 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3761 return;
3764 info_level = SVAL(params,2);
3766 *pparams = (char *)SMB_REALLOC(*pparams,2);
3767 if (*pparams == NULL) {
3768 reply_nterror(req, NT_STATUS_NO_MEMORY);
3769 return;
3771 params = *pparams;
3772 SSVAL(params,0,0);
3773 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3774 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3775 if (*ppdata == NULL ) {
3776 reply_nterror(req, NT_STATUS_NO_MEMORY);
3777 return;
3779 pdata = *ppdata;
3781 switch (info_level) {
3782 case SMB_FILE_STANDARD_INFORMATION:
3783 memset(pdata,0,24);
3784 SOFF_T(pdata,0,4096LL);
3785 SIVAL(pdata,16,1);
3786 SIVAL(pdata,20,1);
3787 data_size = 24;
3788 break;
3790 default:
3791 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3792 return;
3795 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3796 max_data_bytes);
3798 return;
3801 /****************************************************************************
3802 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3803 file name or file id).
3804 ****************************************************************************/
3806 static void call_trans2qfilepathinfo(connection_struct *conn,
3807 struct smb_request *req,
3808 unsigned int tran_call,
3809 char **pparams, int total_params,
3810 char **ppdata, int total_data,
3811 unsigned int max_data_bytes)
3813 char *params = *pparams;
3814 char *pdata = *ppdata;
3815 char *dstart, *dend;
3816 uint16 info_level;
3817 int mode=0;
3818 int nlink;
3819 SMB_OFF_T file_size=0;
3820 SMB_BIG_UINT allocation_size=0;
3821 unsigned int data_size = 0;
3822 unsigned int param_size = 2;
3823 SMB_STRUCT_STAT sbuf;
3824 char *dos_fname = NULL;
3825 char *fname = NULL;
3826 char *fullpathname;
3827 char *base_name;
3828 char *p;
3829 SMB_OFF_T pos = 0;
3830 bool delete_pending = False;
3831 int len;
3832 time_t create_time, mtime, atime;
3833 struct timespec create_time_ts, mtime_ts, atime_ts;
3834 struct timespec write_time_ts;
3835 files_struct *fsp = NULL;
3836 struct file_id fileid;
3837 struct ea_list *ea_list = NULL;
3838 char *lock_data = NULL;
3839 bool ms_dfs_link = false;
3840 TALLOC_CTX *ctx = talloc_tos();
3842 if (!params) {
3843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3844 return;
3847 ZERO_STRUCT(sbuf);
3848 ZERO_STRUCT(write_time_ts);
3850 if (tran_call == TRANSACT2_QFILEINFO) {
3851 if (total_params < 4) {
3852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3853 return;
3856 if (IS_IPC(conn)) {
3857 call_trans2qpipeinfo(conn, req, tran_call,
3858 pparams, total_params,
3859 ppdata, total_data,
3860 max_data_bytes);
3861 return;
3864 fsp = file_fsp(SVAL(params,0));
3865 info_level = SVAL(params,2);
3867 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3869 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3870 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3871 return;
3874 /* Initial check for valid fsp ptr. */
3875 if (!check_fsp_open(conn, req, fsp)) {
3876 return;
3879 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3880 if (!fname) {
3881 reply_nterror(req, NT_STATUS_NO_MEMORY);
3882 return;
3885 if(fsp->fake_file_handle) {
3887 * This is actually for the QUOTA_FAKE_FILE --metze
3890 /* We know this name is ok, it's already passed the checks. */
3892 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3894 * This is actually a QFILEINFO on a directory
3895 * handle (returned from an NT SMB). NT5.0 seems
3896 * to do this call. JRA.
3899 if (INFO_LEVEL_IS_UNIX(info_level)) {
3900 /* Always do lstat for UNIX calls. */
3901 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3902 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3903 reply_unixerror(req,ERRDOS,ERRbadpath);
3904 return;
3906 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3907 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3908 reply_unixerror(req, ERRDOS, ERRbadpath);
3909 return;
3912 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3913 get_file_infos(fileid, &delete_pending, &write_time_ts);
3914 } else {
3916 * Original code - this is an open file.
3918 if (!check_fsp(conn, req, fsp)) {
3919 return;
3922 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3923 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3924 reply_unixerror(req, ERRDOS, ERRbadfid);
3925 return;
3927 pos = fsp->fh->position_information;
3928 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3929 get_file_infos(fileid, &delete_pending, &write_time_ts);
3932 } else {
3933 NTSTATUS status = NT_STATUS_OK;
3935 /* qpathinfo */
3936 if (total_params < 7) {
3937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3938 return;
3941 info_level = SVAL(params,0);
3943 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3945 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3947 return;
3950 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3951 total_params - 6,
3952 STR_TERMINATE, &status);
3953 if (!NT_STATUS_IS_OK(status)) {
3954 reply_nterror(req, status);
3955 return;
3958 status = resolve_dfspath(ctx,
3959 conn,
3960 req->flags2 & FLAGS2_DFS_PATHNAMES,
3961 fname,
3962 &fname);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3965 reply_botherror(req,
3966 NT_STATUS_PATH_NOT_COVERED,
3967 ERRSRV, ERRbadpath);
3969 reply_nterror(req, status);
3970 return;
3973 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 reply_nterror(req, status);
3976 return;
3978 status = check_name(conn, fname);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3981 reply_nterror(req, status);
3982 return;
3985 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3986 && is_ntfs_stream_name(fname)) {
3987 char *base;
3988 SMB_STRUCT_STAT bsbuf;
3990 status = split_ntfs_stream_name(talloc_tos(), fname,
3991 &base, NULL);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 DEBUG(10, ("create_file_unixpath: "
3994 "split_ntfs_stream_name failed: %s\n",
3995 nt_errstr(status)));
3996 reply_nterror(req, status);
3997 return;
4000 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4002 if (INFO_LEVEL_IS_UNIX(info_level)) {
4003 /* Always do lstat for UNIX calls. */
4004 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4005 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4006 reply_unixerror(req,ERRDOS,ERRbadpath);
4007 return;
4009 } else {
4010 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4011 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4012 reply_unixerror(req,ERRDOS,ERRbadpath);
4013 return;
4017 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4018 get_file_infos(fileid, &delete_pending, NULL);
4019 if (delete_pending) {
4020 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4021 return;
4025 if (INFO_LEVEL_IS_UNIX(info_level)) {
4026 /* Always do lstat for UNIX calls. */
4027 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4028 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4029 reply_unixerror(req, ERRDOS, ERRbadpath);
4030 return;
4033 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4034 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4036 if (!ms_dfs_link) {
4037 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4038 reply_unixerror(req, ERRDOS, ERRbadpath);
4039 return;
4043 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4044 get_file_infos(fileid, &delete_pending, &write_time_ts);
4045 if (delete_pending) {
4046 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4047 return;
4051 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4052 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4053 return;
4056 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4057 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4059 p = strrchr_m(fname,'/');
4060 if (!p)
4061 base_name = fname;
4062 else
4063 base_name = p+1;
4065 if (ms_dfs_link) {
4066 mode = dos_mode_msdfs(conn,fname,&sbuf);
4067 } else {
4068 mode = dos_mode(conn,fname,&sbuf);
4070 if (!mode)
4071 mode = FILE_ATTRIBUTE_NORMAL;
4073 nlink = sbuf.st_nlink;
4075 if (nlink && (mode&aDIR)) {
4076 nlink = 1;
4079 if ((nlink > 0) && delete_pending) {
4080 nlink -= 1;
4083 fullpathname = fname;
4084 if (!(mode & aDIR))
4085 file_size = get_file_size(sbuf);
4087 /* Pull out any data sent here before we realloc. */
4088 switch (info_level) {
4089 case SMB_INFO_QUERY_EAS_FROM_LIST:
4091 /* Pull any EA list from the data portion. */
4092 uint32 ea_size;
4094 if (total_data < 4) {
4095 reply_nterror(
4096 req, NT_STATUS_INVALID_PARAMETER);
4097 return;
4099 ea_size = IVAL(pdata,0);
4101 if (total_data > 0 && ea_size != total_data) {
4102 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4103 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4104 reply_nterror(
4105 req, NT_STATUS_INVALID_PARAMETER);
4106 return;
4109 if (!lp_ea_support(SNUM(conn))) {
4110 reply_doserror(req, ERRDOS,
4111 ERReasnotsupported);
4112 return;
4115 /* Pull out the list of names. */
4116 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4117 if (!ea_list) {
4118 reply_nterror(
4119 req, NT_STATUS_INVALID_PARAMETER);
4120 return;
4122 break;
4125 case SMB_QUERY_POSIX_LOCK:
4127 if (fsp == NULL || fsp->fh->fd == -1) {
4128 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4129 return;
4132 if (total_data != POSIX_LOCK_DATA_SIZE) {
4133 reply_nterror(
4134 req, NT_STATUS_INVALID_PARAMETER);
4135 return;
4138 /* Copy the lock range data. */
4139 lock_data = (char *)TALLOC_MEMDUP(
4140 ctx, pdata, total_data);
4141 if (!lock_data) {
4142 reply_nterror(req, NT_STATUS_NO_MEMORY);
4143 return;
4146 default:
4147 break;
4150 *pparams = (char *)SMB_REALLOC(*pparams,2);
4151 if (*pparams == NULL) {
4152 reply_nterror(req, NT_STATUS_NO_MEMORY);
4153 return;
4155 params = *pparams;
4156 SSVAL(params,0,0);
4157 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4158 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4159 if (*ppdata == NULL ) {
4160 reply_nterror(req, NT_STATUS_NO_MEMORY);
4161 return;
4163 pdata = *ppdata;
4164 dstart = pdata;
4165 dend = dstart + data_size - 1;
4167 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4168 mtime_ts = get_mtimespec(&sbuf);
4169 atime_ts = get_atimespec(&sbuf);
4171 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4173 if (!fsp) {
4174 /* Do we have this path open ? */
4175 files_struct *fsp1;
4176 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4177 fsp1 = file_find_di_first(fileid);
4178 if (fsp1 && fsp1->initial_allocation_size) {
4179 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4183 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4184 mtime_ts = write_time_ts;
4187 if (lp_dos_filetime_resolution(SNUM(conn))) {
4188 dos_filetime_timespec(&create_time_ts);
4189 dos_filetime_timespec(&mtime_ts);
4190 dos_filetime_timespec(&atime_ts);
4193 create_time = convert_timespec_to_time_t(create_time_ts);
4194 mtime = convert_timespec_to_time_t(mtime_ts);
4195 atime = convert_timespec_to_time_t(atime_ts);
4197 /* NT expects the name to be in an exact form of the *full*
4198 filename. See the trans2 torture test */
4199 if (ISDOT(base_name)) {
4200 dos_fname = talloc_strdup(ctx, "\\");
4201 if (!dos_fname) {
4202 reply_nterror(req, NT_STATUS_NO_MEMORY);
4203 return;
4205 } else {
4206 dos_fname = talloc_asprintf(ctx,
4207 "\\%s",
4208 fname);
4209 if (!dos_fname) {
4210 reply_nterror(req, NT_STATUS_NO_MEMORY);
4211 return;
4213 string_replace(dos_fname, '/', '\\');
4216 switch (info_level) {
4217 case SMB_INFO_STANDARD:
4218 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4219 data_size = 22;
4220 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4221 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4222 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4223 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4224 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4225 SSVAL(pdata,l1_attrFile,mode);
4226 break;
4228 case SMB_INFO_QUERY_EA_SIZE:
4230 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4231 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4232 data_size = 26;
4233 srv_put_dos_date2(pdata,0,create_time);
4234 srv_put_dos_date2(pdata,4,atime);
4235 srv_put_dos_date2(pdata,8,mtime); /* write time */
4236 SIVAL(pdata,12,(uint32)file_size);
4237 SIVAL(pdata,16,(uint32)allocation_size);
4238 SSVAL(pdata,20,mode);
4239 SIVAL(pdata,22,ea_size);
4240 break;
4243 case SMB_INFO_IS_NAME_VALID:
4244 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4245 if (tran_call == TRANSACT2_QFILEINFO) {
4246 /* os/2 needs this ? really ?*/
4247 reply_doserror(req, ERRDOS, ERRbadfunc);
4248 return;
4250 data_size = 0;
4251 param_size = 0;
4252 break;
4254 case SMB_INFO_QUERY_EAS_FROM_LIST:
4256 size_t total_ea_len = 0;
4257 struct ea_list *ea_file_list = NULL;
4259 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4261 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4262 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4264 if (!ea_list || (total_ea_len > data_size)) {
4265 data_size = 4;
4266 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4267 break;
4270 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4271 break;
4274 case SMB_INFO_QUERY_ALL_EAS:
4276 /* We have data_size bytes to put EA's into. */
4277 size_t total_ea_len = 0;
4279 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4281 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4282 if (!ea_list || (total_ea_len > data_size)) {
4283 data_size = 4;
4284 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4285 break;
4288 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4289 break;
4292 case SMB_FILE_BASIC_INFORMATION:
4293 case SMB_QUERY_FILE_BASIC_INFO:
4295 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4296 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4297 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4298 } else {
4299 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4300 data_size = 40;
4301 SIVAL(pdata,36,0);
4303 put_long_date_timespec(pdata,create_time_ts);
4304 put_long_date_timespec(pdata+8,atime_ts);
4305 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4306 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4307 SIVAL(pdata,32,mode);
4309 DEBUG(5,("SMB_QFBI - "));
4310 DEBUG(5,("create: %s ", ctime(&create_time)));
4311 DEBUG(5,("access: %s ", ctime(&atime)));
4312 DEBUG(5,("write: %s ", ctime(&mtime)));
4313 DEBUG(5,("change: %s ", ctime(&mtime)));
4314 DEBUG(5,("mode: %x\n", mode));
4315 break;
4317 case SMB_FILE_STANDARD_INFORMATION:
4318 case SMB_QUERY_FILE_STANDARD_INFO:
4320 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4321 data_size = 24;
4322 SOFF_T(pdata,0,allocation_size);
4323 SOFF_T(pdata,8,file_size);
4324 SIVAL(pdata,16,nlink);
4325 SCVAL(pdata,20,delete_pending?1:0);
4326 SCVAL(pdata,21,(mode&aDIR)?1:0);
4327 SSVAL(pdata,22,0); /* Padding. */
4328 break;
4330 case SMB_FILE_EA_INFORMATION:
4331 case SMB_QUERY_FILE_EA_INFO:
4333 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4334 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4335 data_size = 4;
4336 SIVAL(pdata,0,ea_size);
4337 break;
4340 /* Get the 8.3 name - used if NT SMB was negotiated. */
4341 case SMB_QUERY_FILE_ALT_NAME_INFO:
4342 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4344 char mangled_name[13];
4345 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4346 if (!name_to_8_3(base_name,mangled_name,
4347 True,conn->params)) {
4348 reply_nterror(
4349 req,
4350 NT_STATUS_NO_MEMORY);
4352 len = srvstr_push(dstart, req->flags2,
4353 pdata+4, mangled_name,
4354 PTR_DIFF(dend, pdata+4),
4355 STR_UNICODE);
4356 data_size = 4 + len;
4357 SIVAL(pdata,0,len);
4358 break;
4361 case SMB_QUERY_FILE_NAME_INFO:
4363 this must be *exactly* right for ACLs on mapped drives to work
4365 len = srvstr_push(dstart, req->flags2,
4366 pdata+4, dos_fname,
4367 PTR_DIFF(dend, pdata+4),
4368 STR_UNICODE);
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4370 data_size = 4 + len;
4371 SIVAL(pdata,0,len);
4372 break;
4374 case SMB_FILE_ALLOCATION_INFORMATION:
4375 case SMB_QUERY_FILE_ALLOCATION_INFO:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4377 data_size = 8;
4378 SOFF_T(pdata,0,allocation_size);
4379 break;
4381 case SMB_FILE_END_OF_FILE_INFORMATION:
4382 case SMB_QUERY_FILE_END_OF_FILEINFO:
4383 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4384 data_size = 8;
4385 SOFF_T(pdata,0,file_size);
4386 break;
4388 case SMB_QUERY_FILE_ALL_INFO:
4389 case SMB_FILE_ALL_INFORMATION:
4391 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4393 put_long_date_timespec(pdata,create_time_ts);
4394 put_long_date_timespec(pdata+8,atime_ts);
4395 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4396 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4397 SIVAL(pdata,32,mode);
4398 SIVAL(pdata,36,0); /* padding. */
4399 pdata += 40;
4400 SOFF_T(pdata,0,allocation_size);
4401 SOFF_T(pdata,8,file_size);
4402 SIVAL(pdata,16,nlink);
4403 SCVAL(pdata,20,delete_pending);
4404 SCVAL(pdata,21,(mode&aDIR)?1:0);
4405 SSVAL(pdata,22,0);
4406 pdata += 24;
4407 SIVAL(pdata,0,ea_size);
4408 pdata += 4; /* EA info */
4409 len = srvstr_push(dstart, req->flags2,
4410 pdata+4, dos_fname,
4411 PTR_DIFF(dend, pdata+4),
4412 STR_UNICODE);
4413 SIVAL(pdata,0,len);
4414 pdata += 4 + len;
4415 data_size = PTR_DIFF(pdata,(*ppdata));
4416 break;
4418 case SMB_FILE_INTERNAL_INFORMATION:
4419 /* This should be an index number - looks like
4420 dev/ino to me :-)
4422 I think this causes us to fail the IFSKIT
4423 BasicFileInformationTest. -tpot */
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4426 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4427 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4428 data_size = 8;
4429 break;
4431 case SMB_FILE_ACCESS_INFORMATION:
4432 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4433 if (fsp) {
4434 SIVAL(pdata,0,fsp->access_mask);
4435 } else {
4436 /* GENERIC_EXECUTE mapping from Windows */
4437 SIVAL(pdata,0,0x12019F);
4439 data_size = 4;
4440 break;
4442 case SMB_FILE_NAME_INFORMATION:
4443 /* Pathname with leading '\'. */
4445 size_t byte_len;
4446 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4447 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4448 SIVAL(pdata,0,byte_len);
4449 data_size = 4 + byte_len;
4450 break;
4453 case SMB_FILE_DISPOSITION_INFORMATION:
4454 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4455 data_size = 1;
4456 SCVAL(pdata,0,delete_pending);
4457 break;
4459 case SMB_FILE_POSITION_INFORMATION:
4460 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4461 data_size = 8;
4462 SOFF_T(pdata,0,pos);
4463 break;
4465 case SMB_FILE_MODE_INFORMATION:
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4467 SIVAL(pdata,0,mode);
4468 data_size = 4;
4469 break;
4471 case SMB_FILE_ALIGNMENT_INFORMATION:
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4473 SIVAL(pdata,0,0); /* No alignment needed. */
4474 data_size = 4;
4475 break;
4478 * NT4 server just returns "invalid query" to this - if we try
4479 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4480 * want this. JRA.
4482 /* The first statement above is false - verified using Thursby
4483 * client against NT4 -- gcolley.
4485 case SMB_QUERY_FILE_STREAM_INFO:
4486 case SMB_FILE_STREAM_INFORMATION: {
4487 unsigned int num_streams;
4488 struct stream_struct *streams;
4489 NTSTATUS status;
4491 DEBUG(10,("call_trans2qfilepathinfo: "
4492 "SMB_FILE_STREAM_INFORMATION\n"));
4494 status = SMB_VFS_STREAMINFO(
4495 conn, fsp, fname, talloc_tos(),
4496 &num_streams, &streams);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 DEBUG(10, ("could not get stream info: %s\n",
4500 nt_errstr(status)));
4501 reply_nterror(req, status);
4502 return;
4505 status = marshall_stream_info(num_streams, streams,
4506 pdata, max_data_bytes,
4507 &data_size);
4509 if (!NT_STATUS_IS_OK(status)) {
4510 DEBUG(10, ("marshall_stream_info failed: %s\n",
4511 nt_errstr(status)));
4512 reply_nterror(req, status);
4513 return;
4516 TALLOC_FREE(streams);
4518 break;
4520 case SMB_QUERY_COMPRESSION_INFO:
4521 case SMB_FILE_COMPRESSION_INFORMATION:
4522 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4523 SOFF_T(pdata,0,file_size);
4524 SIVAL(pdata,8,0); /* ??? */
4525 SIVAL(pdata,12,0); /* ??? */
4526 data_size = 16;
4527 break;
4529 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4530 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4531 put_long_date_timespec(pdata,create_time_ts);
4532 put_long_date_timespec(pdata+8,atime_ts);
4533 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4534 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4535 SOFF_T(pdata,32,allocation_size);
4536 SOFF_T(pdata,40,file_size);
4537 SIVAL(pdata,48,mode);
4538 SIVAL(pdata,52,0); /* ??? */
4539 data_size = 56;
4540 break;
4542 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4543 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4544 SIVAL(pdata,0,mode);
4545 SIVAL(pdata,4,0);
4546 data_size = 8;
4547 break;
4550 * CIFS UNIX Extensions.
4553 case SMB_QUERY_FILE_UNIX_BASIC:
4555 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4556 data_size = PTR_DIFF(pdata,(*ppdata));
4559 int i;
4560 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4562 for (i=0; i<100; i++)
4563 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4564 DEBUG(4,("\n"));
4567 break;
4569 case SMB_QUERY_FILE_UNIX_INFO2:
4571 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4572 data_size = PTR_DIFF(pdata,(*ppdata));
4575 int i;
4576 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4578 for (i=0; i<100; i++)
4579 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4580 DEBUG(4,("\n"));
4583 break;
4585 case SMB_QUERY_FILE_UNIX_LINK:
4587 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4589 if (!buffer) {
4590 reply_nterror(req, NT_STATUS_NO_MEMORY);
4591 return;
4594 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4595 #ifdef S_ISLNK
4596 if(!S_ISLNK(sbuf.st_mode)) {
4597 reply_unixerror(req, ERRSRV,
4598 ERRbadlink);
4599 return;
4601 #else
4602 reply_unixerror(req, ERRDOS, ERRbadlink);
4603 return;
4604 #endif
4605 len = SMB_VFS_READLINK(conn,fullpathname,
4606 buffer, PATH_MAX);
4607 if (len == -1) {
4608 reply_unixerror(req, ERRDOS,
4609 ERRnoaccess);
4610 return;
4612 buffer[len] = 0;
4613 len = srvstr_push(dstart, req->flags2,
4614 pdata, buffer,
4615 PTR_DIFF(dend, pdata),
4616 STR_TERMINATE);
4617 pdata += len;
4618 data_size = PTR_DIFF(pdata,(*ppdata));
4620 break;
4623 #if defined(HAVE_POSIX_ACLS)
4624 case SMB_QUERY_POSIX_ACL:
4626 SMB_ACL_T file_acl = NULL;
4627 SMB_ACL_T def_acl = NULL;
4628 uint16 num_file_acls = 0;
4629 uint16 num_def_acls = 0;
4631 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4632 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4633 } else {
4634 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4637 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4638 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4639 fname ));
4640 reply_nterror(
4641 req,
4642 NT_STATUS_NOT_IMPLEMENTED);
4643 return;
4646 if (S_ISDIR(sbuf.st_mode)) {
4647 if (fsp && fsp->is_directory) {
4648 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4649 } else {
4650 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4652 def_acl = free_empty_sys_acl(conn, def_acl);
4655 num_file_acls = count_acl_entries(conn, file_acl);
4656 num_def_acls = count_acl_entries(conn, def_acl);
4658 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4659 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4660 data_size,
4661 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4662 SMB_POSIX_ACL_HEADER_SIZE) ));
4663 if (file_acl) {
4664 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4666 if (def_acl) {
4667 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4669 reply_nterror(
4670 req,
4671 NT_STATUS_BUFFER_TOO_SMALL);
4672 return;
4675 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4676 SSVAL(pdata,2,num_file_acls);
4677 SSVAL(pdata,4,num_def_acls);
4678 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4679 if (file_acl) {
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4682 if (def_acl) {
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4685 reply_nterror(
4686 req, NT_STATUS_INTERNAL_ERROR);
4687 return;
4689 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4690 if (file_acl) {
4691 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4693 if (def_acl) {
4694 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4696 reply_nterror(
4697 req,
4698 NT_STATUS_INTERNAL_ERROR);
4699 return;
4702 if (file_acl) {
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4705 if (def_acl) {
4706 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4708 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4709 break;
4711 #endif
4714 case SMB_QUERY_POSIX_LOCK:
4716 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4717 SMB_BIG_UINT count;
4718 SMB_BIG_UINT offset;
4719 uint32 lock_pid;
4720 enum brl_type lock_type;
4722 if (total_data != POSIX_LOCK_DATA_SIZE) {
4723 reply_nterror(
4724 req, NT_STATUS_INVALID_PARAMETER);
4725 return;
4728 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4729 case POSIX_LOCK_TYPE_READ:
4730 lock_type = READ_LOCK;
4731 break;
4732 case POSIX_LOCK_TYPE_WRITE:
4733 lock_type = WRITE_LOCK;
4734 break;
4735 case POSIX_LOCK_TYPE_UNLOCK:
4736 default:
4737 /* There's no point in asking for an unlock... */
4738 reply_nterror(
4739 req,
4740 NT_STATUS_INVALID_PARAMETER);
4741 return;
4744 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4745 #if defined(HAVE_LONGLONG)
4746 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4747 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4748 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4749 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4750 #else /* HAVE_LONGLONG */
4751 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4752 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4753 #endif /* HAVE_LONGLONG */
4755 status = query_lock(fsp,
4756 &lock_pid,
4757 &count,
4758 &offset,
4759 &lock_type,
4760 POSIX_LOCK);
4762 if (ERROR_WAS_LOCK_DENIED(status)) {
4763 /* Here we need to report who has it locked... */
4764 data_size = POSIX_LOCK_DATA_SIZE;
4766 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4767 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4768 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4769 #if defined(HAVE_LONGLONG)
4770 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4771 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4772 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4773 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4774 #else /* HAVE_LONGLONG */
4775 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4776 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4777 #endif /* HAVE_LONGLONG */
4779 } else if (NT_STATUS_IS_OK(status)) {
4780 /* For success we just return a copy of what we sent
4781 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4782 data_size = POSIX_LOCK_DATA_SIZE;
4783 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4784 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4785 } else {
4786 reply_nterror(req, status);
4787 return;
4789 break;
4792 default:
4793 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4794 return;
4797 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4798 max_data_bytes);
4800 return;
4803 /****************************************************************************
4804 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4805 code.
4806 ****************************************************************************/
4808 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4809 connection_struct *conn,
4810 const char *oldname_in,
4811 const char *newname_in)
4813 SMB_STRUCT_STAT sbuf1, sbuf2;
4814 char *last_component_oldname = NULL;
4815 char *last_component_newname = NULL;
4816 char *oldname = NULL;
4817 char *newname = NULL;
4818 NTSTATUS status = NT_STATUS_OK;
4820 ZERO_STRUCT(sbuf1);
4821 ZERO_STRUCT(sbuf2);
4823 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4824 &last_component_oldname, &sbuf1);
4825 if (!NT_STATUS_IS_OK(status)) {
4826 return status;
4829 status = check_name(conn, oldname);
4830 if (!NT_STATUS_IS_OK(status)) {
4831 return status;
4834 /* source must already exist. */
4835 if (!VALID_STAT(sbuf1)) {
4836 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4839 status = unix_convert(ctx, conn, newname_in, False, &newname,
4840 &last_component_newname, &sbuf2);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 return status;
4845 status = check_name(conn, newname);
4846 if (!NT_STATUS_IS_OK(status)) {
4847 return status;
4850 /* Disallow if newname already exists. */
4851 if (VALID_STAT(sbuf2)) {
4852 return NT_STATUS_OBJECT_NAME_COLLISION;
4855 /* No links from a directory. */
4856 if (S_ISDIR(sbuf1.st_mode)) {
4857 return NT_STATUS_FILE_IS_A_DIRECTORY;
4860 /* Ensure this is within the share. */
4861 status = check_reduced_name(conn, oldname);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 return status;
4866 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4868 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4869 status = map_nt_error_from_unix(errno);
4870 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4871 nt_errstr(status), newname, oldname));
4874 return status;
4877 /****************************************************************************
4878 Deal with setting the time from any of the setfilepathinfo functions.
4879 ****************************************************************************/
4881 NTSTATUS smb_set_file_time(connection_struct *conn,
4882 files_struct *fsp,
4883 const char *fname,
4884 const SMB_STRUCT_STAT *psbuf,
4885 struct timespec ts[2],
4886 bool setting_write_time)
4888 uint32 action =
4889 FILE_NOTIFY_CHANGE_LAST_ACCESS
4890 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4892 if (!VALID_STAT(*psbuf)) {
4893 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4896 /* get some defaults (no modifications) if any info is zero or -1. */
4897 if (null_timespec(ts[0])) {
4898 ts[0] = get_atimespec(psbuf);
4899 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4902 if (null_timespec(ts[1])) {
4903 ts[1] = get_mtimespec(psbuf);
4904 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4907 if (!setting_write_time) {
4908 /* ts[1] comes from change time, not write time. */
4909 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4912 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4913 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4916 * Try and set the times of this file if
4917 * they are different from the current values.
4921 struct timespec mts = get_mtimespec(psbuf);
4922 struct timespec ats = get_atimespec(psbuf);
4923 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4924 return NT_STATUS_OK;
4928 if (setting_write_time) {
4930 * This was a setfileinfo on an open file.
4931 * NT does this a lot. We also need to
4932 * set the time here, as it can be read by
4933 * FindFirst/FindNext and with the patch for bug #2045
4934 * in smbd/fileio.c it ensures that this timestamp is
4935 * kept sticky even after a write. We save the request
4936 * away and will set it on file close and after a write. JRA.
4939 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4940 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4942 if (fsp != NULL) {
4943 if (fsp->base_fsp) {
4944 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4945 } else {
4946 set_sticky_write_time_fsp(fsp, ts[1]);
4948 } else {
4949 set_sticky_write_time_path(conn, fname,
4950 vfs_file_id_from_sbuf(conn, psbuf),
4951 ts[1]);
4955 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4957 if (fsp && fsp->base_fsp) {
4958 fname = fsp->base_fsp->fsp_name;
4961 if(file_ntimes(conn, fname, ts)!=0) {
4962 return map_nt_error_from_unix(errno);
4964 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4966 return NT_STATUS_OK;
4969 /****************************************************************************
4970 Deal with setting the dosmode from any of the setfilepathinfo functions.
4971 ****************************************************************************/
4973 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4974 files_struct *fsp,
4975 const char *fname,
4976 SMB_STRUCT_STAT *psbuf,
4977 uint32 dosmode)
4979 if (!VALID_STAT(*psbuf)) {
4980 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4983 if (fsp) {
4984 if (fsp->base_fsp) {
4985 fname = fsp->base_fsp->fsp_name;
4986 } else {
4987 fname = fsp->fsp_name;
4991 if (dosmode) {
4992 if (S_ISDIR(psbuf->st_mode)) {
4993 dosmode |= aDIR;
4994 } else {
4995 dosmode &= ~aDIR;
4999 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5001 /* check the mode isn't different, before changing it */
5002 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5004 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5005 fname, (unsigned int)dosmode ));
5007 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5008 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5009 fname, strerror(errno)));
5010 return map_nt_error_from_unix(errno);
5013 return NT_STATUS_OK;
5016 /****************************************************************************
5017 Deal with setting the size from any of the setfilepathinfo functions.
5018 ****************************************************************************/
5020 static NTSTATUS smb_set_file_size(connection_struct *conn,
5021 struct smb_request *req,
5022 files_struct *fsp,
5023 const char *fname,
5024 SMB_STRUCT_STAT *psbuf,
5025 SMB_OFF_T size)
5027 NTSTATUS status = NT_STATUS_OK;
5028 files_struct *new_fsp = NULL;
5030 if (!VALID_STAT(*psbuf)) {
5031 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5034 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5036 if (size == get_file_size(*psbuf)) {
5037 return NT_STATUS_OK;
5040 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5041 fname, (double)size ));
5043 if (fsp && fsp->fh->fd != -1) {
5044 /* Handle based call. */
5045 if (vfs_set_filelen(fsp, size) == -1) {
5046 return map_nt_error_from_unix(errno);
5048 trigger_write_time_update_immediate(fsp);
5049 return NT_STATUS_OK;
5052 status = open_file_ntcreate(conn, req, fname, psbuf,
5053 FILE_WRITE_ATTRIBUTES,
5054 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5055 FILE_OPEN,
5057 FILE_ATTRIBUTE_NORMAL,
5058 FORCE_OPLOCK_BREAK_TO_NONE,
5059 NULL, &new_fsp);
5061 if (!NT_STATUS_IS_OK(status)) {
5062 /* NB. We check for open_was_deferred in the caller. */
5063 return status;
5066 if (vfs_set_filelen(new_fsp, size) == -1) {
5067 status = map_nt_error_from_unix(errno);
5068 close_file(new_fsp,NORMAL_CLOSE);
5069 return status;
5072 trigger_write_time_update_immediate(new_fsp);
5073 close_file(new_fsp,NORMAL_CLOSE);
5074 return NT_STATUS_OK;
5077 /****************************************************************************
5078 Deal with SMB_INFO_SET_EA.
5079 ****************************************************************************/
5081 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5082 const char *pdata,
5083 int total_data,
5084 files_struct *fsp,
5085 const char *fname)
5087 struct ea_list *ea_list = NULL;
5088 TALLOC_CTX *ctx = NULL;
5089 NTSTATUS status = NT_STATUS_OK;
5091 if (total_data < 10) {
5093 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5094 length. They seem to have no effect. Bug #3212. JRA */
5096 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5097 /* We're done. We only get EA info in this call. */
5098 return NT_STATUS_OK;
5101 return NT_STATUS_INVALID_PARAMETER;
5104 if (IVAL(pdata,0) > total_data) {
5105 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5106 IVAL(pdata,0), (unsigned int)total_data));
5107 return NT_STATUS_INVALID_PARAMETER;
5110 ctx = talloc_tos();
5111 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5112 if (!ea_list) {
5113 return NT_STATUS_INVALID_PARAMETER;
5115 status = set_ea(conn, fsp, fname, ea_list);
5117 return status;
5120 /****************************************************************************
5121 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5122 ****************************************************************************/
5124 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5125 const char *pdata,
5126 int total_data,
5127 files_struct *fsp,
5128 const char *fname,
5129 SMB_STRUCT_STAT *psbuf)
5131 NTSTATUS status = NT_STATUS_OK;
5132 bool delete_on_close;
5133 uint32 dosmode = 0;
5135 if (total_data < 1) {
5136 return NT_STATUS_INVALID_PARAMETER;
5139 if (fsp == NULL) {
5140 return NT_STATUS_INVALID_HANDLE;
5143 delete_on_close = (CVAL(pdata,0) ? True : False);
5144 dosmode = dos_mode(conn, fname, psbuf);
5146 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5147 "delete_on_close = %u\n",
5148 fsp->fsp_name,
5149 (unsigned int)dosmode,
5150 (unsigned int)delete_on_close ));
5152 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 return status;
5158 /* The set is across all open files on this dev/inode pair. */
5159 if (!set_delete_on_close(fsp, delete_on_close,
5160 &conn->server_info->utok)) {
5161 return NT_STATUS_ACCESS_DENIED;
5163 return NT_STATUS_OK;
5166 /****************************************************************************
5167 Deal with SMB_FILE_POSITION_INFORMATION.
5168 ****************************************************************************/
5170 static NTSTATUS smb_file_position_information(connection_struct *conn,
5171 const char *pdata,
5172 int total_data,
5173 files_struct *fsp)
5175 SMB_BIG_UINT position_information;
5177 if (total_data < 8) {
5178 return NT_STATUS_INVALID_PARAMETER;
5181 if (fsp == NULL) {
5182 /* Ignore on pathname based set. */
5183 return NT_STATUS_OK;
5186 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5187 #ifdef LARGE_SMB_OFF_T
5188 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5189 #else /* LARGE_SMB_OFF_T */
5190 if (IVAL(pdata,4) != 0) {
5191 /* more than 32 bits? */
5192 return NT_STATUS_INVALID_PARAMETER;
5194 #endif /* LARGE_SMB_OFF_T */
5196 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5197 fsp->fsp_name, (double)position_information ));
5198 fsp->fh->position_information = position_information;
5199 return NT_STATUS_OK;
5202 /****************************************************************************
5203 Deal with SMB_FILE_MODE_INFORMATION.
5204 ****************************************************************************/
5206 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5207 const char *pdata,
5208 int total_data)
5210 uint32 mode;
5212 if (total_data < 4) {
5213 return NT_STATUS_INVALID_PARAMETER;
5215 mode = IVAL(pdata,0);
5216 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5217 return NT_STATUS_INVALID_PARAMETER;
5219 return NT_STATUS_OK;
5222 /****************************************************************************
5223 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5224 ****************************************************************************/
5226 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5227 struct smb_request *req,
5228 const char *pdata,
5229 int total_data,
5230 const char *fname)
5232 char *link_target = NULL;
5233 const char *newname = fname;
5234 NTSTATUS status = NT_STATUS_OK;
5235 TALLOC_CTX *ctx = talloc_tos();
5237 /* Set a symbolic link. */
5238 /* Don't allow this if follow links is false. */
5240 if (total_data == 0) {
5241 return NT_STATUS_INVALID_PARAMETER;
5244 if (!lp_symlinks(SNUM(conn))) {
5245 return NT_STATUS_ACCESS_DENIED;
5248 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5249 total_data, STR_TERMINATE);
5251 if (!link_target) {
5252 return NT_STATUS_INVALID_PARAMETER;
5255 /* !widelinks forces the target path to be within the share. */
5256 /* This means we can interpret the target as a pathname. */
5257 if (!lp_widelinks(SNUM(conn))) {
5258 char *rel_name = NULL;
5259 char *last_dirp = NULL;
5261 if (*link_target == '/') {
5262 /* No absolute paths allowed. */
5263 return NT_STATUS_ACCESS_DENIED;
5265 rel_name = talloc_strdup(ctx,newname);
5266 if (!rel_name) {
5267 return NT_STATUS_NO_MEMORY;
5269 last_dirp = strrchr_m(rel_name, '/');
5270 if (last_dirp) {
5271 last_dirp[1] = '\0';
5272 } else {
5273 rel_name = talloc_strdup(ctx,"./");
5274 if (!rel_name) {
5275 return NT_STATUS_NO_MEMORY;
5278 rel_name = talloc_asprintf_append(rel_name,
5279 "%s",
5280 link_target);
5281 if (!rel_name) {
5282 return NT_STATUS_NO_MEMORY;
5285 status = check_name(conn, rel_name);
5286 if (!NT_STATUS_IS_OK(status)) {
5287 return status;
5291 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5292 newname, link_target ));
5294 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5295 return map_nt_error_from_unix(errno);
5298 return NT_STATUS_OK;
5301 /****************************************************************************
5302 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5303 ****************************************************************************/
5305 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5306 struct smb_request *req,
5307 const char *pdata, int total_data,
5308 const char *fname)
5310 char *oldname = NULL;
5311 TALLOC_CTX *ctx = talloc_tos();
5312 NTSTATUS status = NT_STATUS_OK;
5314 /* Set a hard link. */
5315 if (total_data == 0) {
5316 return NT_STATUS_INVALID_PARAMETER;
5319 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5320 total_data, STR_TERMINATE, &status);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 return status;
5325 status = resolve_dfspath(ctx, conn,
5326 req->flags2 & FLAGS2_DFS_PATHNAMES,
5327 oldname,
5328 &oldname);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 return status;
5333 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5334 fname, oldname));
5336 return hardlink_internals(ctx, conn, oldname, fname);
5339 /****************************************************************************
5340 Deal with SMB_FILE_RENAME_INFORMATION.
5341 ****************************************************************************/
5343 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5344 struct smb_request *req,
5345 const char *pdata,
5346 int total_data,
5347 files_struct *fsp,
5348 const char *fname)
5350 bool overwrite;
5351 uint32 root_fid;
5352 uint32 len;
5353 char *newname = NULL;
5354 char *base_name = NULL;
5355 bool dest_has_wcard = False;
5356 SMB_STRUCT_STAT sbuf;
5357 char *newname_last_component = NULL;
5358 NTSTATUS status = NT_STATUS_OK;
5359 char *p;
5360 TALLOC_CTX *ctx = talloc_tos();
5362 if (total_data < 13) {
5363 return NT_STATUS_INVALID_PARAMETER;
5366 ZERO_STRUCT(sbuf);
5368 overwrite = (CVAL(pdata,0) ? True : False);
5369 root_fid = IVAL(pdata,4);
5370 len = IVAL(pdata,8);
5372 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5373 return NT_STATUS_INVALID_PARAMETER;
5376 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5377 len, 0, &status,
5378 &dest_has_wcard);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 return status;
5383 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5384 newname));
5386 status = resolve_dfspath_wcard(ctx, conn,
5387 req->flags2 & FLAGS2_DFS_PATHNAMES,
5388 newname,
5389 &newname,
5390 &dest_has_wcard);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 return status;
5395 /* Check the new name has no '/' characters. */
5396 if (strchr_m(newname, '/')) {
5397 return NT_STATUS_NOT_SUPPORTED;
5400 if (fsp && fsp->base_fsp) {
5401 /* newname must be a stream name. */
5402 if (newname[0] != ':') {
5403 return NT_STATUS_NOT_SUPPORTED;
5405 base_name = talloc_asprintf(ctx, "%s%s",
5406 fsp->base_fsp->fsp_name,
5407 newname);
5408 if (!base_name) {
5409 return NT_STATUS_NO_MEMORY;
5411 } else {
5412 /* newname must *not* be a stream name. */
5413 if (is_ntfs_stream_name(newname)) {
5414 return NT_STATUS_NOT_SUPPORTED;
5417 /* Create the base directory. */
5418 base_name = talloc_strdup(ctx, fname);
5419 if (!base_name) {
5420 return NT_STATUS_NO_MEMORY;
5422 p = strrchr_m(base_name, '/');
5423 if (p) {
5424 p[1] = '\0';
5425 } else {
5426 base_name = talloc_strdup(ctx, "./");
5427 if (!base_name) {
5428 return NT_STATUS_NO_MEMORY;
5431 /* Append the new name. */
5432 base_name = talloc_asprintf_append(base_name,
5433 "%s",
5434 newname);
5435 if (!base_name) {
5436 return NT_STATUS_NO_MEMORY;
5439 status = unix_convert(ctx, conn, newname, False,
5440 &newname,
5441 &newname_last_component,
5442 &sbuf);
5444 /* If an error we expect this to be
5445 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5447 if (!NT_STATUS_IS_OK(status)
5448 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5449 status)) {
5450 return status;
5454 if (fsp) {
5455 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5456 fsp->fnum, fsp->fsp_name, base_name ));
5457 status = rename_internals_fsp(conn, fsp, base_name,
5458 newname_last_component, 0,
5459 overwrite);
5460 } else {
5461 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5462 fname, base_name ));
5463 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5464 overwrite, False, dest_has_wcard,
5465 FILE_WRITE_ATTRIBUTES);
5468 return status;
5471 /****************************************************************************
5472 Deal with SMB_SET_POSIX_ACL.
5473 ****************************************************************************/
5475 #if defined(HAVE_POSIX_ACLS)
5476 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5477 const char *pdata,
5478 int total_data,
5479 files_struct *fsp,
5480 const char *fname,
5481 SMB_STRUCT_STAT *psbuf)
5483 uint16 posix_acl_version;
5484 uint16 num_file_acls;
5485 uint16 num_def_acls;
5486 bool valid_file_acls = True;
5487 bool valid_def_acls = True;
5489 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5490 return NT_STATUS_INVALID_PARAMETER;
5492 posix_acl_version = SVAL(pdata,0);
5493 num_file_acls = SVAL(pdata,2);
5494 num_def_acls = SVAL(pdata,4);
5496 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5497 valid_file_acls = False;
5498 num_file_acls = 0;
5501 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5502 valid_def_acls = False;
5503 num_def_acls = 0;
5506 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5507 return NT_STATUS_INVALID_PARAMETER;
5510 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5511 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5512 return NT_STATUS_INVALID_PARAMETER;
5515 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5516 fname ? fname : fsp->fsp_name,
5517 (unsigned int)num_file_acls,
5518 (unsigned int)num_def_acls));
5520 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5521 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5522 return map_nt_error_from_unix(errno);
5525 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5526 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5527 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5528 return map_nt_error_from_unix(errno);
5530 return NT_STATUS_OK;
5532 #endif
5534 /****************************************************************************
5535 Deal with SMB_SET_POSIX_LOCK.
5536 ****************************************************************************/
5538 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5539 const struct smb_request *req,
5540 const char *pdata,
5541 int total_data,
5542 files_struct *fsp)
5544 SMB_BIG_UINT count;
5545 SMB_BIG_UINT offset;
5546 uint32 lock_pid;
5547 bool blocking_lock = False;
5548 enum brl_type lock_type;
5550 NTSTATUS status = NT_STATUS_OK;
5552 if (fsp == NULL || fsp->fh->fd == -1) {
5553 return NT_STATUS_INVALID_HANDLE;
5556 if (total_data != POSIX_LOCK_DATA_SIZE) {
5557 return NT_STATUS_INVALID_PARAMETER;
5560 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5561 case POSIX_LOCK_TYPE_READ:
5562 lock_type = READ_LOCK;
5563 break;
5564 case POSIX_LOCK_TYPE_WRITE:
5565 /* Return the right POSIX-mappable error code for files opened read-only. */
5566 if (!fsp->can_write) {
5567 return NT_STATUS_INVALID_HANDLE;
5569 lock_type = WRITE_LOCK;
5570 break;
5571 case POSIX_LOCK_TYPE_UNLOCK:
5572 lock_type = UNLOCK_LOCK;
5573 break;
5574 default:
5575 return NT_STATUS_INVALID_PARAMETER;
5578 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5579 blocking_lock = False;
5580 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5581 blocking_lock = True;
5582 } else {
5583 return NT_STATUS_INVALID_PARAMETER;
5586 if (!lp_blocking_locks(SNUM(conn))) {
5587 blocking_lock = False;
5590 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5591 #if defined(HAVE_LONGLONG)
5592 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5593 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5594 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5595 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5596 #else /* HAVE_LONGLONG */
5597 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5598 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5599 #endif /* HAVE_LONGLONG */
5601 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5602 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5603 fsp->fsp_name,
5604 (unsigned int)lock_type,
5605 (unsigned int)lock_pid,
5606 (double)count,
5607 (double)offset ));
5609 if (lock_type == UNLOCK_LOCK) {
5610 status = do_unlock(smbd_messaging_context(),
5611 fsp,
5612 lock_pid,
5613 count,
5614 offset,
5615 POSIX_LOCK);
5616 } else {
5617 uint32 block_smbpid;
5619 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5620 fsp,
5621 lock_pid,
5622 count,
5623 offset,
5624 lock_type,
5625 POSIX_LOCK,
5626 blocking_lock,
5627 &status,
5628 &block_smbpid);
5630 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5632 * A blocking lock was requested. Package up
5633 * this smb into a queued request and push it
5634 * onto the blocking lock queue.
5636 if(push_blocking_lock_request(br_lck,
5637 req,
5638 fsp,
5639 -1, /* infinite timeout. */
5641 lock_pid,
5642 lock_type,
5643 POSIX_LOCK,
5644 offset,
5645 count,
5646 block_smbpid)) {
5647 TALLOC_FREE(br_lck);
5648 return status;
5651 TALLOC_FREE(br_lck);
5654 return status;
5657 /****************************************************************************
5658 Deal with SMB_INFO_STANDARD.
5659 ****************************************************************************/
5661 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5662 const char *pdata,
5663 int total_data,
5664 files_struct *fsp,
5665 const char *fname,
5666 const SMB_STRUCT_STAT *psbuf)
5668 struct timespec ts[2];
5670 if (total_data < 12) {
5671 return NT_STATUS_INVALID_PARAMETER;
5674 /* access time */
5675 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5676 /* write time */
5677 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5679 DEBUG(10,("smb_set_info_standard: file %s\n",
5680 fname ? fname : fsp->fsp_name ));
5682 return smb_set_file_time(conn,
5683 fsp,
5684 fname,
5685 psbuf,
5687 true);
5690 /****************************************************************************
5691 Deal with SMB_SET_FILE_BASIC_INFO.
5692 ****************************************************************************/
5694 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5695 const char *pdata,
5696 int total_data,
5697 files_struct *fsp,
5698 const char *fname,
5699 SMB_STRUCT_STAT *psbuf)
5701 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5702 struct timespec write_time;
5703 struct timespec changed_time;
5704 uint32 dosmode = 0;
5705 struct timespec ts[2];
5706 NTSTATUS status = NT_STATUS_OK;
5707 bool setting_write_time = true;
5709 if (total_data < 36) {
5710 return NT_STATUS_INVALID_PARAMETER;
5713 /* Set the attributes */
5714 dosmode = IVAL(pdata,32);
5715 status = smb_set_file_dosmode(conn,
5716 fsp,
5717 fname,
5718 psbuf,
5719 dosmode);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 return status;
5725 /* Ignore create time at offset pdata. */
5727 /* access time */
5728 ts[0] = interpret_long_date(pdata+8);
5730 write_time = interpret_long_date(pdata+16);
5731 changed_time = interpret_long_date(pdata+24);
5733 /* mtime */
5734 ts[1] = timespec_min(&write_time, &changed_time);
5736 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5737 ts[1] = write_time;
5740 /* Prefer a defined time to an undefined one. */
5741 if (null_timespec(ts[1])) {
5742 if (null_timespec(write_time)) {
5743 ts[1] = changed_time;
5744 setting_write_time = false;
5745 } else {
5746 ts[1] = write_time;
5750 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5751 fname ? fname : fsp->fsp_name ));
5753 return smb_set_file_time(conn,
5754 fsp,
5755 fname,
5756 psbuf,
5758 setting_write_time);
5761 /****************************************************************************
5762 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5763 ****************************************************************************/
5765 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5766 struct smb_request *req,
5767 const char *pdata,
5768 int total_data,
5769 files_struct *fsp,
5770 const char *fname,
5771 SMB_STRUCT_STAT *psbuf)
5773 SMB_BIG_UINT allocation_size = 0;
5774 NTSTATUS status = NT_STATUS_OK;
5775 files_struct *new_fsp = NULL;
5777 if (!VALID_STAT(*psbuf)) {
5778 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5781 if (total_data < 8) {
5782 return NT_STATUS_INVALID_PARAMETER;
5785 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5786 #ifdef LARGE_SMB_OFF_T
5787 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5788 #else /* LARGE_SMB_OFF_T */
5789 if (IVAL(pdata,4) != 0) {
5790 /* more than 32 bits? */
5791 return NT_STATUS_INVALID_PARAMETER;
5793 #endif /* LARGE_SMB_OFF_T */
5795 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5796 fname, (double)allocation_size ));
5798 if (allocation_size) {
5799 allocation_size = smb_roundup(conn, allocation_size);
5802 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5803 fname, (double)allocation_size ));
5805 if (fsp && fsp->fh->fd != -1) {
5806 /* Open file handle. */
5807 /* Only change if needed. */
5808 if (allocation_size != get_file_size(*psbuf)) {
5809 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5810 return map_nt_error_from_unix(errno);
5813 /* But always update the time. */
5815 * This is equivalent to a write. Ensure it's seen immediately
5816 * if there are no pending writes.
5818 trigger_write_time_update_immediate(fsp);
5819 return NT_STATUS_OK;
5822 /* Pathname or stat or directory file. */
5824 status = open_file_ntcreate(conn, req, fname, psbuf,
5825 FILE_WRITE_DATA,
5826 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5827 FILE_OPEN,
5829 FILE_ATTRIBUTE_NORMAL,
5830 FORCE_OPLOCK_BREAK_TO_NONE,
5831 NULL, &new_fsp);
5833 if (!NT_STATUS_IS_OK(status)) {
5834 /* NB. We check for open_was_deferred in the caller. */
5835 return status;
5838 /* Only change if needed. */
5839 if (allocation_size != get_file_size(*psbuf)) {
5840 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5841 status = map_nt_error_from_unix(errno);
5842 close_file(new_fsp,NORMAL_CLOSE);
5843 return status;
5847 /* Changing the allocation size should set the last mod time. */
5849 * This is equivalent to a write. Ensure it's seen immediately
5850 * if there are no pending writes.
5852 trigger_write_time_update_immediate(new_fsp);
5854 close_file(new_fsp,NORMAL_CLOSE);
5855 return NT_STATUS_OK;
5858 /****************************************************************************
5859 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5860 ****************************************************************************/
5862 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5863 struct smb_request *req,
5864 const char *pdata,
5865 int total_data,
5866 files_struct *fsp,
5867 const char *fname,
5868 SMB_STRUCT_STAT *psbuf)
5870 SMB_OFF_T size;
5872 if (total_data < 8) {
5873 return NT_STATUS_INVALID_PARAMETER;
5876 size = IVAL(pdata,0);
5877 #ifdef LARGE_SMB_OFF_T
5878 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5879 #else /* LARGE_SMB_OFF_T */
5880 if (IVAL(pdata,4) != 0) {
5881 /* more than 32 bits? */
5882 return NT_STATUS_INVALID_PARAMETER;
5884 #endif /* LARGE_SMB_OFF_T */
5885 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5886 "file %s to %.0f\n", fname, (double)size ));
5888 return smb_set_file_size(conn, req,
5889 fsp,
5890 fname,
5891 psbuf,
5892 size);
5895 /****************************************************************************
5896 Allow a UNIX info mknod.
5897 ****************************************************************************/
5899 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5900 const char *pdata,
5901 int total_data,
5902 const char *fname,
5903 SMB_STRUCT_STAT *psbuf)
5905 uint32 file_type = IVAL(pdata,56);
5906 #if defined(HAVE_MAKEDEV)
5907 uint32 dev_major = IVAL(pdata,60);
5908 uint32 dev_minor = IVAL(pdata,68);
5909 #endif
5910 SMB_DEV_T dev = (SMB_DEV_T)0;
5911 uint32 raw_unixmode = IVAL(pdata,84);
5912 NTSTATUS status;
5913 mode_t unixmode;
5915 if (total_data < 100) {
5916 return NT_STATUS_INVALID_PARAMETER;
5919 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5920 if (!NT_STATUS_IS_OK(status)) {
5921 return status;
5924 #if defined(HAVE_MAKEDEV)
5925 dev = makedev(dev_major, dev_minor);
5926 #endif
5928 switch (file_type) {
5929 #if defined(S_IFIFO)
5930 case UNIX_TYPE_FIFO:
5931 unixmode |= S_IFIFO;
5932 break;
5933 #endif
5934 #if defined(S_IFSOCK)
5935 case UNIX_TYPE_SOCKET:
5936 unixmode |= S_IFSOCK;
5937 break;
5938 #endif
5939 #if defined(S_IFCHR)
5940 case UNIX_TYPE_CHARDEV:
5941 unixmode |= S_IFCHR;
5942 break;
5943 #endif
5944 #if defined(S_IFBLK)
5945 case UNIX_TYPE_BLKDEV:
5946 unixmode |= S_IFBLK;
5947 break;
5948 #endif
5949 default:
5950 return NT_STATUS_INVALID_PARAMETER;
5953 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5954 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5956 /* Ok - do the mknod. */
5957 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5958 return map_nt_error_from_unix(errno);
5961 /* If any of the other "set" calls fail we
5962 * don't want to end up with a half-constructed mknod.
5965 if (lp_inherit_perms(SNUM(conn))) {
5966 inherit_access_posix_acl(
5967 conn, parent_dirname(fname),
5968 fname, unixmode);
5971 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5972 status = map_nt_error_from_unix(errno);
5973 SMB_VFS_UNLINK(conn,fname);
5974 return status;
5976 return NT_STATUS_OK;
5979 /****************************************************************************
5980 Deal with SMB_SET_FILE_UNIX_BASIC.
5981 ****************************************************************************/
5983 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5984 struct smb_request *req,
5985 const char *pdata,
5986 int total_data,
5987 files_struct *fsp,
5988 const char *fname,
5989 SMB_STRUCT_STAT *psbuf)
5991 struct timespec ts[2];
5992 uint32 raw_unixmode;
5993 mode_t unixmode;
5994 SMB_OFF_T size = 0;
5995 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5996 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5997 NTSTATUS status = NT_STATUS_OK;
5998 bool delete_on_fail = False;
5999 enum perm_type ptype;
6001 if (total_data < 100) {
6002 return NT_STATUS_INVALID_PARAMETER;
6005 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6006 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6007 size=IVAL(pdata,0); /* first 8 Bytes are size */
6008 #ifdef LARGE_SMB_OFF_T
6009 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6010 #else /* LARGE_SMB_OFF_T */
6011 if (IVAL(pdata,4) != 0) {
6012 /* more than 32 bits? */
6013 return NT_STATUS_INVALID_PARAMETER;
6015 #endif /* LARGE_SMB_OFF_T */
6018 ts[0] = interpret_long_date(pdata+24); /* access_time */
6019 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6020 set_owner = (uid_t)IVAL(pdata,40);
6021 set_grp = (gid_t)IVAL(pdata,48);
6022 raw_unixmode = IVAL(pdata,84);
6024 if (VALID_STAT(*psbuf)) {
6025 if (S_ISDIR(psbuf->st_mode)) {
6026 ptype = PERM_EXISTING_DIR;
6027 } else {
6028 ptype = PERM_EXISTING_FILE;
6030 } else {
6031 ptype = PERM_NEW_FILE;
6034 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6035 if (!NT_STATUS_IS_OK(status)) {
6036 return status;
6039 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6040 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6041 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6043 if (!VALID_STAT(*psbuf)) {
6045 * The only valid use of this is to create character and block
6046 * devices, and named pipes. This is deprecated (IMHO) and
6047 * a new info level should be used for mknod. JRA.
6050 status = smb_unix_mknod(conn,
6051 pdata,
6052 total_data,
6053 fname,
6054 psbuf);
6055 if (!NT_STATUS_IS_OK(status)) {
6056 return status;
6059 /* Ensure we don't try and change anything else. */
6060 raw_unixmode = SMB_MODE_NO_CHANGE;
6061 size = get_file_size(*psbuf);
6062 ts[0] = get_atimespec(psbuf);
6063 ts[1] = get_mtimespec(psbuf);
6065 * We continue here as we might want to change the
6066 * owner uid/gid.
6068 delete_on_fail = True;
6071 #if 1
6072 /* Horrible backwards compatibility hack as an old server bug
6073 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6074 * */
6076 if (!size) {
6077 size = get_file_size(*psbuf);
6079 #endif
6082 * Deal with the UNIX specific mode set.
6085 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6086 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6087 (unsigned int)unixmode, fname ));
6088 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6089 return map_nt_error_from_unix(errno);
6094 * Deal with the UNIX specific uid set.
6097 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6098 int ret;
6100 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6101 (unsigned int)set_owner, fname ));
6103 if (S_ISLNK(psbuf->st_mode)) {
6104 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6105 } else {
6106 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6109 if (ret != 0) {
6110 status = map_nt_error_from_unix(errno);
6111 if (delete_on_fail) {
6112 SMB_VFS_UNLINK(conn,fname);
6114 return status;
6119 * Deal with the UNIX specific gid set.
6122 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6123 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6124 (unsigned int)set_owner, fname ));
6125 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6126 status = map_nt_error_from_unix(errno);
6127 if (delete_on_fail) {
6128 SMB_VFS_UNLINK(conn,fname);
6130 return status;
6134 /* Deal with any size changes. */
6136 status = smb_set_file_size(conn, req,
6137 fsp,
6138 fname,
6139 psbuf,
6140 size);
6141 if (!NT_STATUS_IS_OK(status)) {
6142 return status;
6145 /* Deal with any time changes. */
6147 return smb_set_file_time(conn,
6148 fsp,
6149 fname,
6150 psbuf,
6152 true);
6155 /****************************************************************************
6156 Deal with SMB_SET_FILE_UNIX_INFO2.
6157 ****************************************************************************/
6159 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6160 struct smb_request *req,
6161 const char *pdata,
6162 int total_data,
6163 files_struct *fsp,
6164 const char *fname,
6165 SMB_STRUCT_STAT *psbuf)
6167 NTSTATUS status;
6168 uint32 smb_fflags;
6169 uint32 smb_fmask;
6171 if (total_data < 116) {
6172 return NT_STATUS_INVALID_PARAMETER;
6175 /* Start by setting all the fields that are common between UNIX_BASIC
6176 * and UNIX_INFO2.
6178 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6179 fsp, fname, psbuf);
6180 if (!NT_STATUS_IS_OK(status)) {
6181 return status;
6184 smb_fflags = IVAL(pdata, 108);
6185 smb_fmask = IVAL(pdata, 112);
6187 /* NB: We should only attempt to alter the file flags if the client
6188 * sends a non-zero mask.
6190 if (smb_fmask != 0) {
6191 int stat_fflags = 0;
6193 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6194 &stat_fflags)) {
6195 /* Client asked to alter a flag we don't understand. */
6196 return NT_STATUS_INVALID_PARAMETER;
6199 if (fsp && fsp->fh->fd != -1) {
6200 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6201 return NT_STATUS_NOT_SUPPORTED;
6202 } else {
6203 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6204 return map_nt_error_from_unix(errno);
6209 /* XXX: need to add support for changing the create_time here. You
6210 * can do this for paths on Darwin with setattrlist(2). The right way
6211 * to hook this up is probably by extending the VFS utimes interface.
6214 return NT_STATUS_OK;
6217 /****************************************************************************
6218 Create a directory with POSIX semantics.
6219 ****************************************************************************/
6221 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6222 struct smb_request *req,
6223 char **ppdata,
6224 int total_data,
6225 const char *fname,
6226 SMB_STRUCT_STAT *psbuf,
6227 int *pdata_return_size)
6229 NTSTATUS status = NT_STATUS_OK;
6230 uint32 raw_unixmode = 0;
6231 uint32 mod_unixmode = 0;
6232 mode_t unixmode = (mode_t)0;
6233 files_struct *fsp = NULL;
6234 uint16 info_level_return = 0;
6235 int info;
6236 char *pdata = *ppdata;
6238 if (total_data < 18) {
6239 return NT_STATUS_INVALID_PARAMETER;
6242 raw_unixmode = IVAL(pdata,8);
6243 /* Next 4 bytes are not yet defined. */
6245 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6246 if (!NT_STATUS_IS_OK(status)) {
6247 return status;
6250 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6252 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6253 fname, (unsigned int)unixmode ));
6255 status = open_directory(conn, req,
6256 fname,
6257 psbuf,
6258 FILE_READ_ATTRIBUTES, /* Just a stat open */
6259 FILE_SHARE_NONE, /* Ignored for stat opens */
6260 FILE_CREATE,
6262 mod_unixmode,
6263 &info,
6264 &fsp);
6266 if (NT_STATUS_IS_OK(status)) {
6267 close_file(fsp, NORMAL_CLOSE);
6270 info_level_return = SVAL(pdata,16);
6272 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6273 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6274 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6275 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6276 } else {
6277 *pdata_return_size = 12;
6280 /* Realloc the data size */
6281 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6282 if (*ppdata == NULL) {
6283 *pdata_return_size = 0;
6284 return NT_STATUS_NO_MEMORY;
6286 pdata = *ppdata;
6288 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6289 SSVAL(pdata,2,0); /* No fnum. */
6290 SIVAL(pdata,4,info); /* Was directory created. */
6292 switch (info_level_return) {
6293 case SMB_QUERY_FILE_UNIX_BASIC:
6294 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6295 SSVAL(pdata,10,0); /* Padding. */
6296 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6297 break;
6298 case SMB_QUERY_FILE_UNIX_INFO2:
6299 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6300 SSVAL(pdata,10,0); /* Padding. */
6301 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6302 break;
6303 default:
6304 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6305 SSVAL(pdata,10,0); /* Padding. */
6306 break;
6309 return status;
6312 /****************************************************************************
6313 Open/Create a file with POSIX semantics.
6314 ****************************************************************************/
6316 static NTSTATUS smb_posix_open(connection_struct *conn,
6317 struct smb_request *req,
6318 char **ppdata,
6319 int total_data,
6320 const char *fname,
6321 SMB_STRUCT_STAT *psbuf,
6322 int *pdata_return_size)
6324 bool extended_oplock_granted = False;
6325 char *pdata = *ppdata;
6326 uint32 flags = 0;
6327 uint32 wire_open_mode = 0;
6328 uint32 raw_unixmode = 0;
6329 uint32 mod_unixmode = 0;
6330 uint32 create_disp = 0;
6331 uint32 access_mask = 0;
6332 uint32 create_options = 0;
6333 NTSTATUS status = NT_STATUS_OK;
6334 mode_t unixmode = (mode_t)0;
6335 files_struct *fsp = NULL;
6336 int oplock_request = 0;
6337 int info = 0;
6338 uint16 info_level_return = 0;
6340 if (total_data < 18) {
6341 return NT_STATUS_INVALID_PARAMETER;
6344 flags = IVAL(pdata,0);
6345 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6346 if (oplock_request) {
6347 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6350 wire_open_mode = IVAL(pdata,4);
6352 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6353 return smb_posix_mkdir(conn, req,
6354 ppdata,
6355 total_data,
6356 fname,
6357 psbuf,
6358 pdata_return_size);
6361 switch (wire_open_mode & SMB_ACCMODE) {
6362 case SMB_O_RDONLY:
6363 access_mask = FILE_READ_DATA;
6364 break;
6365 case SMB_O_WRONLY:
6366 access_mask = FILE_WRITE_DATA;
6367 break;
6368 case SMB_O_RDWR:
6369 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6370 break;
6371 default:
6372 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6373 (unsigned int)wire_open_mode ));
6374 return NT_STATUS_INVALID_PARAMETER;
6377 wire_open_mode &= ~SMB_ACCMODE;
6379 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6380 create_disp = FILE_CREATE;
6381 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6382 create_disp = FILE_OVERWRITE_IF;
6383 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6384 create_disp = FILE_OPEN_IF;
6385 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6386 create_disp = FILE_OPEN;
6387 } else {
6388 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6389 (unsigned int)wire_open_mode ));
6390 return NT_STATUS_INVALID_PARAMETER;
6393 raw_unixmode = IVAL(pdata,8);
6394 /* Next 4 bytes are not yet defined. */
6396 status = unix_perms_from_wire(conn,
6397 psbuf,
6398 raw_unixmode,
6399 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6400 &unixmode);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 return status;
6406 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6408 if (wire_open_mode & SMB_O_SYNC) {
6409 create_options |= FILE_WRITE_THROUGH;
6411 if (wire_open_mode & SMB_O_APPEND) {
6412 access_mask |= FILE_APPEND_DATA;
6414 if (wire_open_mode & SMB_O_DIRECT) {
6415 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6418 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6419 fname,
6420 (unsigned int)wire_open_mode,
6421 (unsigned int)unixmode ));
6423 status = open_file_ntcreate(conn, req,
6424 fname,
6425 psbuf,
6426 access_mask,
6427 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6428 create_disp,
6429 0, /* no create options yet. */
6430 mod_unixmode,
6431 oplock_request,
6432 &info,
6433 &fsp);
6435 if (!NT_STATUS_IS_OK(status)) {
6436 return status;
6439 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6440 extended_oplock_granted = True;
6443 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6444 extended_oplock_granted = True;
6447 info_level_return = SVAL(pdata,16);
6449 /* Allocate the correct return size. */
6451 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6452 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6453 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6454 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6455 } else {
6456 *pdata_return_size = 12;
6459 /* Realloc the data size */
6460 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6461 if (*ppdata == NULL) {
6462 close_file(fsp,ERROR_CLOSE);
6463 *pdata_return_size = 0;
6464 return NT_STATUS_NO_MEMORY;
6466 pdata = *ppdata;
6468 if (extended_oplock_granted) {
6469 if (flags & REQUEST_BATCH_OPLOCK) {
6470 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6471 } else {
6472 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6474 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6475 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6476 } else {
6477 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6480 SSVAL(pdata,2,fsp->fnum);
6481 SIVAL(pdata,4,info); /* Was file created etc. */
6483 switch (info_level_return) {
6484 case SMB_QUERY_FILE_UNIX_BASIC:
6485 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6486 SSVAL(pdata,10,0); /* padding. */
6487 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6488 break;
6489 case SMB_QUERY_FILE_UNIX_INFO2:
6490 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6491 SSVAL(pdata,10,0); /* padding. */
6492 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6493 break;
6494 default:
6495 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6496 SSVAL(pdata,10,0); /* padding. */
6497 break;
6499 return NT_STATUS_OK;
6502 /****************************************************************************
6503 Delete a file with POSIX semantics.
6504 ****************************************************************************/
6506 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6507 struct smb_request *req,
6508 const char *pdata,
6509 int total_data,
6510 const char *fname,
6511 SMB_STRUCT_STAT *psbuf)
6513 NTSTATUS status = NT_STATUS_OK;
6514 files_struct *fsp = NULL;
6515 uint16 flags = 0;
6516 char del = 1;
6517 int info = 0;
6518 int i;
6519 struct share_mode_lock *lck = NULL;
6521 if (total_data < 2) {
6522 return NT_STATUS_INVALID_PARAMETER;
6525 flags = SVAL(pdata,0);
6527 if (!VALID_STAT(*psbuf)) {
6528 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6531 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6532 !VALID_STAT_OF_DIR(*psbuf)) {
6533 return NT_STATUS_NOT_A_DIRECTORY;
6536 DEBUG(10,("smb_posix_unlink: %s %s\n",
6537 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6538 fname));
6540 if (VALID_STAT_OF_DIR(*psbuf)) {
6541 status = open_directory(conn, req,
6542 fname,
6543 psbuf,
6544 DELETE_ACCESS,
6545 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6546 FILE_OPEN,
6548 FILE_FLAG_POSIX_SEMANTICS|0777,
6549 &info,
6550 &fsp);
6551 } else {
6553 status = open_file_ntcreate(conn, req,
6554 fname,
6555 psbuf,
6556 DELETE_ACCESS,
6557 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6558 FILE_OPEN,
6560 FILE_FLAG_POSIX_SEMANTICS|0777,
6561 0, /* No oplock, but break existing ones. */
6562 &info,
6563 &fsp);
6566 if (!NT_STATUS_IS_OK(status)) {
6567 return status;
6571 * Don't lie to client. If we can't really delete due to
6572 * non-POSIX opens return SHARING_VIOLATION.
6575 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6576 NULL);
6577 if (lck == NULL) {
6578 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6579 "lock for file %s\n", fsp->fsp_name));
6580 close_file(fsp, NORMAL_CLOSE);
6581 return NT_STATUS_INVALID_PARAMETER;
6585 * See if others still have the file open. If this is the case, then
6586 * don't delete. If all opens are POSIX delete we can set the delete
6587 * on close disposition.
6589 for (i=0; i<lck->num_share_modes; i++) {
6590 struct share_mode_entry *e = &lck->share_modes[i];
6591 if (is_valid_share_mode_entry(e)) {
6592 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6593 continue;
6595 /* Fail with sharing violation. */
6596 close_file(fsp, NORMAL_CLOSE);
6597 TALLOC_FREE(lck);
6598 return NT_STATUS_SHARING_VIOLATION;
6603 * Set the delete on close.
6605 status = smb_set_file_disposition_info(conn,
6606 &del,
6608 fsp,
6609 fname,
6610 psbuf);
6612 if (!NT_STATUS_IS_OK(status)) {
6613 close_file(fsp, NORMAL_CLOSE);
6614 TALLOC_FREE(lck);
6615 return status;
6617 TALLOC_FREE(lck);
6618 return close_file(fsp, NORMAL_CLOSE);
6621 /****************************************************************************
6622 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6623 ****************************************************************************/
6625 static void call_trans2setfilepathinfo(connection_struct *conn,
6626 struct smb_request *req,
6627 unsigned int tran_call,
6628 char **pparams, int total_params,
6629 char **ppdata, int total_data,
6630 unsigned int max_data_bytes)
6632 char *params = *pparams;
6633 char *pdata = *ppdata;
6634 uint16 info_level;
6635 SMB_STRUCT_STAT sbuf;
6636 char *fname = NULL;
6637 files_struct *fsp = NULL;
6638 NTSTATUS status = NT_STATUS_OK;
6639 int data_return_size = 0;
6640 TALLOC_CTX *ctx = talloc_tos();
6642 if (!params) {
6643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6644 return;
6647 ZERO_STRUCT(sbuf);
6649 if (tran_call == TRANSACT2_SETFILEINFO) {
6650 if (total_params < 4) {
6651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6652 return;
6655 fsp = file_fsp(SVAL(params,0));
6656 /* Basic check for non-null fsp. */
6657 if (!check_fsp_open(conn, req, fsp)) {
6658 return;
6660 info_level = SVAL(params,2);
6662 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6663 if (!fname) {
6664 reply_nterror(req, NT_STATUS_NO_MEMORY);
6665 return;
6668 if(fsp->is_directory || fsp->fh->fd == -1) {
6670 * This is actually a SETFILEINFO on a directory
6671 * handle (returned from an NT SMB). NT5.0 seems
6672 * to do this call. JRA.
6674 if (INFO_LEVEL_IS_UNIX(info_level)) {
6675 /* Always do lstat for UNIX calls. */
6676 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6677 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6678 reply_unixerror(req,ERRDOS,ERRbadpath);
6679 return;
6681 } else {
6682 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6683 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6684 reply_unixerror(req,ERRDOS,ERRbadpath);
6685 return;
6688 } else if (fsp->print_file) {
6690 * Doing a DELETE_ON_CLOSE should cancel a print job.
6692 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6693 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6695 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6697 SSVAL(params,0,0);
6698 send_trans2_replies(conn, req, params, 2,
6699 *ppdata, 0,
6700 max_data_bytes);
6701 return;
6702 } else {
6703 reply_unixerror(req, ERRDOS, ERRbadpath);
6704 return;
6706 } else {
6708 * Original code - this is an open file.
6710 if (!check_fsp(conn, req, fsp)) {
6711 return;
6714 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6715 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6716 reply_unixerror(req, ERRDOS, ERRbadfid);
6717 return;
6720 } else {
6721 /* set path info */
6722 if (total_params < 7) {
6723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6724 return;
6727 info_level = SVAL(params,0);
6728 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6729 total_params - 6, STR_TERMINATE,
6730 &status);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 reply_nterror(req, status);
6733 return;
6736 status = resolve_dfspath(ctx, conn,
6737 req->flags2 & FLAGS2_DFS_PATHNAMES,
6738 fname,
6739 &fname);
6740 if (!NT_STATUS_IS_OK(status)) {
6741 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6742 reply_botherror(req,
6743 NT_STATUS_PATH_NOT_COVERED,
6744 ERRSRV, ERRbadpath);
6745 return;
6747 reply_nterror(req, status);
6748 return;
6751 status = unix_convert(ctx, conn, fname, False,
6752 &fname, NULL, &sbuf);
6753 if (!NT_STATUS_IS_OK(status)) {
6754 reply_nterror(req, status);
6755 return;
6758 status = check_name(conn, fname);
6759 if (!NT_STATUS_IS_OK(status)) {
6760 reply_nterror(req, status);
6761 return;
6764 if (INFO_LEVEL_IS_UNIX(info_level)) {
6766 * For CIFS UNIX extensions the target name may not exist.
6769 /* Always do lstat for UNIX calls. */
6770 SMB_VFS_LSTAT(conn,fname,&sbuf);
6772 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6773 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6774 reply_unixerror(req, ERRDOS, ERRbadpath);
6775 return;
6779 if (!CAN_WRITE(conn)) {
6780 reply_doserror(req, ERRSRV, ERRaccess);
6781 return;
6784 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6786 return;
6789 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6790 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6792 /* Realloc the parameter size */
6793 *pparams = (char *)SMB_REALLOC(*pparams,2);
6794 if (*pparams == NULL) {
6795 reply_nterror(req, NT_STATUS_NO_MEMORY);
6796 return;
6798 params = *pparams;
6800 SSVAL(params,0,0);
6802 switch (info_level) {
6804 case SMB_INFO_STANDARD:
6806 status = smb_set_info_standard(conn,
6807 pdata,
6808 total_data,
6809 fsp,
6810 fname,
6811 &sbuf);
6812 break;
6815 case SMB_INFO_SET_EA:
6817 status = smb_info_set_ea(conn,
6818 pdata,
6819 total_data,
6820 fsp,
6821 fname);
6822 break;
6825 case SMB_SET_FILE_BASIC_INFO:
6826 case SMB_FILE_BASIC_INFORMATION:
6828 status = smb_set_file_basic_info(conn,
6829 pdata,
6830 total_data,
6831 fsp,
6832 fname,
6833 &sbuf);
6834 break;
6837 case SMB_FILE_ALLOCATION_INFORMATION:
6838 case SMB_SET_FILE_ALLOCATION_INFO:
6840 status = smb_set_file_allocation_info(conn, req,
6841 pdata,
6842 total_data,
6843 fsp,
6844 fname,
6845 &sbuf);
6846 break;
6849 case SMB_FILE_END_OF_FILE_INFORMATION:
6850 case SMB_SET_FILE_END_OF_FILE_INFO:
6852 status = smb_set_file_end_of_file_info(conn, req,
6853 pdata,
6854 total_data,
6855 fsp,
6856 fname,
6857 &sbuf);
6858 break;
6861 case SMB_FILE_DISPOSITION_INFORMATION:
6862 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6864 #if 0
6865 /* JRA - We used to just ignore this on a path ?
6866 * Shouldn't this be invalid level on a pathname
6867 * based call ?
6869 if (tran_call != TRANSACT2_SETFILEINFO) {
6870 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6872 #endif
6873 status = smb_set_file_disposition_info(conn,
6874 pdata,
6875 total_data,
6876 fsp,
6877 fname,
6878 &sbuf);
6879 break;
6882 case SMB_FILE_POSITION_INFORMATION:
6884 status = smb_file_position_information(conn,
6885 pdata,
6886 total_data,
6887 fsp);
6888 break;
6891 /* From tridge Samba4 :
6892 * MODE_INFORMATION in setfileinfo (I have no
6893 * idea what "mode information" on a file is - it takes a value of 0,
6894 * 2, 4 or 6. What could it be?).
6897 case SMB_FILE_MODE_INFORMATION:
6899 status = smb_file_mode_information(conn,
6900 pdata,
6901 total_data);
6902 break;
6906 * CIFS UNIX extensions.
6909 case SMB_SET_FILE_UNIX_BASIC:
6911 status = smb_set_file_unix_basic(conn, req,
6912 pdata,
6913 total_data,
6914 fsp,
6915 fname,
6916 &sbuf);
6917 break;
6920 case SMB_SET_FILE_UNIX_INFO2:
6922 status = smb_set_file_unix_info2(conn, req,
6923 pdata,
6924 total_data,
6925 fsp,
6926 fname,
6927 &sbuf);
6928 break;
6931 case SMB_SET_FILE_UNIX_LINK:
6933 if (tran_call != TRANSACT2_SETPATHINFO) {
6934 /* We must have a pathname for this. */
6935 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6936 return;
6938 status = smb_set_file_unix_link(conn, req, pdata,
6939 total_data, fname);
6940 break;
6943 case SMB_SET_FILE_UNIX_HLINK:
6945 if (tran_call != TRANSACT2_SETPATHINFO) {
6946 /* We must have a pathname for this. */
6947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6948 return;
6950 status = smb_set_file_unix_hlink(conn, req,
6951 pdata, total_data,
6952 fname);
6953 break;
6956 case SMB_FILE_RENAME_INFORMATION:
6958 status = smb_file_rename_information(conn, req,
6959 pdata, total_data,
6960 fsp, fname);
6961 break;
6964 #if defined(HAVE_POSIX_ACLS)
6965 case SMB_SET_POSIX_ACL:
6967 status = smb_set_posix_acl(conn,
6968 pdata,
6969 total_data,
6970 fsp,
6971 fname,
6972 &sbuf);
6973 break;
6975 #endif
6977 case SMB_SET_POSIX_LOCK:
6979 if (tran_call != TRANSACT2_SETFILEINFO) {
6980 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6981 return;
6983 status = smb_set_posix_lock(conn, req,
6984 pdata, total_data, fsp);
6985 break;
6988 case SMB_POSIX_PATH_OPEN:
6990 if (tran_call != TRANSACT2_SETPATHINFO) {
6991 /* We must have a pathname for this. */
6992 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6993 return;
6996 status = smb_posix_open(conn, req,
6997 ppdata,
6998 total_data,
6999 fname,
7000 &sbuf,
7001 &data_return_size);
7002 break;
7005 case SMB_POSIX_PATH_UNLINK:
7007 if (tran_call != TRANSACT2_SETPATHINFO) {
7008 /* We must have a pathname for this. */
7009 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7010 return;
7013 status = smb_posix_unlink(conn, req,
7014 pdata,
7015 total_data,
7016 fname,
7017 &sbuf);
7018 break;
7021 default:
7022 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7023 return;
7027 if (!NT_STATUS_IS_OK(status)) {
7028 if (open_was_deferred(req->mid)) {
7029 /* We have re-scheduled this call. */
7030 return;
7032 if (blocking_lock_was_deferred(req->mid)) {
7033 /* We have re-scheduled this call. */
7034 return;
7036 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7037 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7038 ERRSRV, ERRbadpath);
7039 return;
7041 if (info_level == SMB_POSIX_PATH_OPEN) {
7042 reply_openerror(req, status);
7043 return;
7046 reply_nterror(req, status);
7047 return;
7050 SSVAL(params,0,0);
7051 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7052 max_data_bytes);
7054 return;
7057 /****************************************************************************
7058 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7059 ****************************************************************************/
7061 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7062 char **pparams, int total_params,
7063 char **ppdata, int total_data,
7064 unsigned int max_data_bytes)
7066 char *params = *pparams;
7067 char *pdata = *ppdata;
7068 char *directory = NULL;
7069 SMB_STRUCT_STAT sbuf;
7070 NTSTATUS status = NT_STATUS_OK;
7071 struct ea_list *ea_list = NULL;
7072 TALLOC_CTX *ctx = talloc_tos();
7074 if (!CAN_WRITE(conn)) {
7075 reply_doserror(req, ERRSRV, ERRaccess);
7076 return;
7079 if (total_params < 5) {
7080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7081 return;
7084 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7085 total_params - 4, STR_TERMINATE,
7086 &status);
7087 if (!NT_STATUS_IS_OK(status)) {
7088 reply_nterror(req, status);
7089 return;
7092 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7094 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7095 if (!NT_STATUS_IS_OK(status)) {
7096 reply_nterror(req, status);
7097 return;
7100 status = check_name(conn, directory);
7101 if (!NT_STATUS_IS_OK(status)) {
7102 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7103 reply_nterror(req, status);
7104 return;
7107 /* Any data in this call is an EA list. */
7108 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7109 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7110 return;
7114 * OS/2 workplace shell seems to send SET_EA requests of "null"
7115 * length (4 bytes containing IVAL 4).
7116 * They seem to have no effect. Bug #3212. JRA.
7119 if (total_data != 4) {
7120 if (total_data < 10) {
7121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7122 return;
7125 if (IVAL(pdata,0) > total_data) {
7126 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7127 IVAL(pdata,0), (unsigned int)total_data));
7128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7129 return;
7132 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7133 total_data - 4);
7134 if (!ea_list) {
7135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7136 return;
7139 /* If total_data == 4 Windows doesn't care what values
7140 * are placed in that field, it just ignores them.
7141 * The System i QNTC IBM SMB client puts bad values here,
7142 * so ignore them. */
7144 status = create_directory(conn, req, directory);
7146 if (!NT_STATUS_IS_OK(status)) {
7147 reply_nterror(req, status);
7148 return;
7151 /* Try and set any given EA. */
7152 if (ea_list) {
7153 status = set_ea(conn, NULL, directory, ea_list);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 reply_nterror(req, status);
7156 return;
7160 /* Realloc the parameter and data sizes */
7161 *pparams = (char *)SMB_REALLOC(*pparams,2);
7162 if(*pparams == NULL) {
7163 reply_nterror(req, NT_STATUS_NO_MEMORY);
7164 return;
7166 params = *pparams;
7168 SSVAL(params,0,0);
7170 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7172 return;
7175 /****************************************************************************
7176 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7177 We don't actually do this - we just send a null response.
7178 ****************************************************************************/
7180 static void call_trans2findnotifyfirst(connection_struct *conn,
7181 struct smb_request *req,
7182 char **pparams, int total_params,
7183 char **ppdata, int total_data,
7184 unsigned int max_data_bytes)
7186 static uint16 fnf_handle = 257;
7187 char *params = *pparams;
7188 uint16 info_level;
7190 if (total_params < 6) {
7191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7192 return;
7195 info_level = SVAL(params,4);
7196 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7198 switch (info_level) {
7199 case 1:
7200 case 2:
7201 break;
7202 default:
7203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7204 return;
7207 /* Realloc the parameter and data sizes */
7208 *pparams = (char *)SMB_REALLOC(*pparams,6);
7209 if (*pparams == NULL) {
7210 reply_nterror(req, NT_STATUS_NO_MEMORY);
7211 return;
7213 params = *pparams;
7215 SSVAL(params,0,fnf_handle);
7216 SSVAL(params,2,0); /* No changes */
7217 SSVAL(params,4,0); /* No EA errors */
7219 fnf_handle++;
7221 if(fnf_handle == 0)
7222 fnf_handle = 257;
7224 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7226 return;
7229 /****************************************************************************
7230 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7231 changes). Currently this does nothing.
7232 ****************************************************************************/
7234 static void call_trans2findnotifynext(connection_struct *conn,
7235 struct smb_request *req,
7236 char **pparams, int total_params,
7237 char **ppdata, int total_data,
7238 unsigned int max_data_bytes)
7240 char *params = *pparams;
7242 DEBUG(3,("call_trans2findnotifynext\n"));
7244 /* Realloc the parameter and data sizes */
7245 *pparams = (char *)SMB_REALLOC(*pparams,4);
7246 if (*pparams == NULL) {
7247 reply_nterror(req, NT_STATUS_NO_MEMORY);
7248 return;
7250 params = *pparams;
7252 SSVAL(params,0,0); /* No changes */
7253 SSVAL(params,2,0); /* No EA errors */
7255 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7257 return;
7260 /****************************************************************************
7261 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7262 ****************************************************************************/
7264 static void call_trans2getdfsreferral(connection_struct *conn,
7265 struct smb_request *req,
7266 char **pparams, int total_params,
7267 char **ppdata, int total_data,
7268 unsigned int max_data_bytes)
7270 char *params = *pparams;
7271 char *pathname = NULL;
7272 int reply_size = 0;
7273 int max_referral_level;
7274 NTSTATUS status = NT_STATUS_OK;
7275 TALLOC_CTX *ctx = talloc_tos();
7277 DEBUG(10,("call_trans2getdfsreferral\n"));
7279 if (total_params < 3) {
7280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7281 return;
7284 max_referral_level = SVAL(params,0);
7286 if(!lp_host_msdfs()) {
7287 reply_doserror(req, ERRDOS, ERRbadfunc);
7288 return;
7291 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7292 total_params - 2, STR_TERMINATE);
7293 if (!pathname) {
7294 reply_nterror(req, NT_STATUS_NOT_FOUND);
7295 return;
7297 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7298 ppdata,&status)) < 0) {
7299 reply_nterror(req, status);
7300 return;
7303 SSVAL(req->inbuf, smb_flg2,
7304 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7305 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7307 return;
7310 #define LMCAT_SPL 0x53
7311 #define LMFUNC_GETJOBID 0x60
7313 /****************************************************************************
7314 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7315 ****************************************************************************/
7317 static void call_trans2ioctl(connection_struct *conn,
7318 struct smb_request *req,
7319 char **pparams, int total_params,
7320 char **ppdata, int total_data,
7321 unsigned int max_data_bytes)
7323 char *pdata = *ppdata;
7324 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7326 /* check for an invalid fid before proceeding */
7328 if (!fsp) {
7329 reply_doserror(req, ERRDOS, ERRbadfid);
7330 return;
7333 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7334 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7335 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7336 if (*ppdata == NULL) {
7337 reply_nterror(req, NT_STATUS_NO_MEMORY);
7338 return;
7340 pdata = *ppdata;
7342 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7343 CAN ACCEPT THIS IN UNICODE. JRA. */
7345 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7346 srvstr_push(pdata, req->flags2, pdata + 2,
7347 global_myname(), 15,
7348 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7349 srvstr_push(pdata, req->flags2, pdata+18,
7350 lp_servicename(SNUM(conn)), 13,
7351 STR_ASCII|STR_TERMINATE); /* Service name */
7352 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7353 max_data_bytes);
7354 return;
7357 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7358 reply_doserror(req, ERRSRV, ERRerror);
7361 /****************************************************************************
7362 Reply to a SMBfindclose (stop trans2 directory search).
7363 ****************************************************************************/
7365 void reply_findclose(struct smb_request *req)
7367 int dptr_num;
7369 START_PROFILE(SMBfindclose);
7371 if (req->wct < 1) {
7372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7373 END_PROFILE(SMBfindclose);
7374 return;
7377 dptr_num = SVALS(req->inbuf,smb_vwv0);
7379 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7381 dptr_close(&dptr_num);
7383 reply_outbuf(req, 0, 0);
7385 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7387 END_PROFILE(SMBfindclose);
7388 return;
7391 /****************************************************************************
7392 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7393 ****************************************************************************/
7395 void reply_findnclose(struct smb_request *req)
7397 int dptr_num;
7399 START_PROFILE(SMBfindnclose);
7401 if (req->wct < 1) {
7402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7403 END_PROFILE(SMBfindnclose);
7404 return;
7407 dptr_num = SVAL(req->inbuf,smb_vwv0);
7409 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7411 /* We never give out valid handles for a
7412 findnotifyfirst - so any dptr_num is ok here.
7413 Just ignore it. */
7415 reply_outbuf(req, 0, 0);
7417 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7419 END_PROFILE(SMBfindnclose);
7420 return;
7423 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7424 struct trans_state *state)
7426 if (Protocol >= PROTOCOL_NT1) {
7427 req->flags2 |= 0x40; /* IS_LONG_NAME */
7428 SSVAL(req->inbuf,smb_flg2,req->flags2);
7431 if (conn->encrypt_level == Required && !req->encrypted) {
7432 if (state->call != TRANSACT2_QFSINFO &&
7433 state->call != TRANSACT2_SETFSINFO) {
7434 DEBUG(0,("handle_trans2: encryption required "
7435 "with call 0x%x\n",
7436 (unsigned int)state->call));
7437 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7438 return;
7442 /* Now we must call the relevant TRANS2 function */
7443 switch(state->call) {
7444 case TRANSACT2_OPEN:
7446 START_PROFILE(Trans2_open);
7447 call_trans2open(conn, req,
7448 &state->param, state->total_param,
7449 &state->data, state->total_data,
7450 state->max_data_return);
7451 END_PROFILE(Trans2_open);
7452 break;
7455 case TRANSACT2_FINDFIRST:
7457 START_PROFILE(Trans2_findfirst);
7458 call_trans2findfirst(conn, req,
7459 &state->param, state->total_param,
7460 &state->data, state->total_data,
7461 state->max_data_return);
7462 END_PROFILE(Trans2_findfirst);
7463 break;
7466 case TRANSACT2_FINDNEXT:
7468 START_PROFILE(Trans2_findnext);
7469 call_trans2findnext(conn, req,
7470 &state->param, state->total_param,
7471 &state->data, state->total_data,
7472 state->max_data_return);
7473 END_PROFILE(Trans2_findnext);
7474 break;
7477 case TRANSACT2_QFSINFO:
7479 START_PROFILE(Trans2_qfsinfo);
7480 call_trans2qfsinfo(conn, req,
7481 &state->param, state->total_param,
7482 &state->data, state->total_data,
7483 state->max_data_return);
7484 END_PROFILE(Trans2_qfsinfo);
7485 break;
7488 case TRANSACT2_SETFSINFO:
7490 START_PROFILE(Trans2_setfsinfo);
7491 call_trans2setfsinfo(conn, req,
7492 &state->param, state->total_param,
7493 &state->data, state->total_data,
7494 state->max_data_return);
7495 END_PROFILE(Trans2_setfsinfo);
7496 break;
7499 case TRANSACT2_QPATHINFO:
7500 case TRANSACT2_QFILEINFO:
7502 START_PROFILE(Trans2_qpathinfo);
7503 call_trans2qfilepathinfo(conn, req, state->call,
7504 &state->param, state->total_param,
7505 &state->data, state->total_data,
7506 state->max_data_return);
7507 END_PROFILE(Trans2_qpathinfo);
7508 break;
7511 case TRANSACT2_SETPATHINFO:
7512 case TRANSACT2_SETFILEINFO:
7514 START_PROFILE(Trans2_setpathinfo);
7515 call_trans2setfilepathinfo(conn, req, state->call,
7516 &state->param, state->total_param,
7517 &state->data, state->total_data,
7518 state->max_data_return);
7519 END_PROFILE(Trans2_setpathinfo);
7520 break;
7523 case TRANSACT2_FINDNOTIFYFIRST:
7525 START_PROFILE(Trans2_findnotifyfirst);
7526 call_trans2findnotifyfirst(conn, req,
7527 &state->param, state->total_param,
7528 &state->data, state->total_data,
7529 state->max_data_return);
7530 END_PROFILE(Trans2_findnotifyfirst);
7531 break;
7534 case TRANSACT2_FINDNOTIFYNEXT:
7536 START_PROFILE(Trans2_findnotifynext);
7537 call_trans2findnotifynext(conn, req,
7538 &state->param, state->total_param,
7539 &state->data, state->total_data,
7540 state->max_data_return);
7541 END_PROFILE(Trans2_findnotifynext);
7542 break;
7545 case TRANSACT2_MKDIR:
7547 START_PROFILE(Trans2_mkdir);
7548 call_trans2mkdir(conn, req,
7549 &state->param, state->total_param,
7550 &state->data, state->total_data,
7551 state->max_data_return);
7552 END_PROFILE(Trans2_mkdir);
7553 break;
7556 case TRANSACT2_GET_DFS_REFERRAL:
7558 START_PROFILE(Trans2_get_dfs_referral);
7559 call_trans2getdfsreferral(conn, req,
7560 &state->param, state->total_param,
7561 &state->data, state->total_data,
7562 state->max_data_return);
7563 END_PROFILE(Trans2_get_dfs_referral);
7564 break;
7567 case TRANSACT2_IOCTL:
7569 START_PROFILE(Trans2_ioctl);
7570 call_trans2ioctl(conn, req,
7571 &state->param, state->total_param,
7572 &state->data, state->total_data,
7573 state->max_data_return);
7574 END_PROFILE(Trans2_ioctl);
7575 break;
7578 default:
7579 /* Error in request */
7580 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7581 reply_doserror(req, ERRSRV,ERRerror);
7585 /****************************************************************************
7586 Reply to a SMBtrans2.
7587 ****************************************************************************/
7589 void reply_trans2(struct smb_request *req)
7591 connection_struct *conn = req->conn;
7592 unsigned int dsoff;
7593 unsigned int dscnt;
7594 unsigned int psoff;
7595 unsigned int pscnt;
7596 unsigned int tran_call;
7597 unsigned int size;
7598 unsigned int av_size;
7599 struct trans_state *state;
7600 NTSTATUS result;
7602 START_PROFILE(SMBtrans2);
7604 if (req->wct < 14) {
7605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7606 END_PROFILE(SMBtrans2);
7607 return;
7610 dsoff = SVAL(req->inbuf, smb_dsoff);
7611 dscnt = SVAL(req->inbuf, smb_dscnt);
7612 psoff = SVAL(req->inbuf, smb_psoff);
7613 pscnt = SVAL(req->inbuf, smb_pscnt);
7614 tran_call = SVAL(req->inbuf, smb_setup0);
7615 size = smb_len(req->inbuf) + 4;
7616 av_size = smb_len(req->inbuf);
7618 result = allow_new_trans(conn->pending_trans, req->mid);
7619 if (!NT_STATUS_IS_OK(result)) {
7620 DEBUG(2, ("Got invalid trans2 request: %s\n",
7621 nt_errstr(result)));
7622 reply_nterror(req, result);
7623 END_PROFILE(SMBtrans2);
7624 return;
7627 if (IS_IPC(conn)) {
7628 switch (tran_call) {
7629 /* List the allowed trans2 calls on IPC$ */
7630 case TRANSACT2_OPEN:
7631 case TRANSACT2_GET_DFS_REFERRAL:
7632 case TRANSACT2_QFILEINFO:
7633 case TRANSACT2_QFSINFO:
7634 case TRANSACT2_SETFSINFO:
7635 break;
7636 default:
7637 reply_doserror(req, ERRSRV, ERRaccess);
7638 END_PROFILE(SMBtrans2);
7639 return;
7643 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7644 DEBUG(0, ("talloc failed\n"));
7645 reply_nterror(req, NT_STATUS_NO_MEMORY);
7646 END_PROFILE(SMBtrans2);
7647 return;
7650 state->cmd = SMBtrans2;
7652 state->mid = req->mid;
7653 state->vuid = req->vuid;
7654 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7655 state->setup = NULL;
7656 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7657 state->param = NULL;
7658 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7659 state->data = NULL;
7660 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7661 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7662 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7663 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7664 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7666 state->call = tran_call;
7668 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7669 is so as a sanity check */
7670 if (state->setup_count != 1) {
7672 * Need to have rc=0 for ioctl to get job id for OS/2.
7673 * Network printing will fail if function is not successful.
7674 * Similar function in reply.c will be used if protocol
7675 * is LANMAN1.0 instead of LM1.2X002.
7676 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7677 * outbuf doesn't have to be set(only job id is used).
7679 if ( (state->setup_count == 4)
7680 && (tran_call == TRANSACT2_IOCTL)
7681 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7682 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7683 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7684 } else {
7685 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7686 DEBUG(2,("Transaction is %d\n",tran_call));
7687 TALLOC_FREE(state);
7688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7689 END_PROFILE(SMBtrans2);
7690 return;
7694 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7695 goto bad_param;
7697 if (state->total_data) {
7698 /* Can't use talloc here, the core routines do realloc on the
7699 * params and data. */
7700 state->data = (char *)SMB_MALLOC(state->total_data);
7701 if (state->data == NULL) {
7702 DEBUG(0,("reply_trans2: data malloc fail for %u "
7703 "bytes !\n", (unsigned int)state->total_data));
7704 TALLOC_FREE(state);
7705 reply_nterror(req, NT_STATUS_NO_MEMORY);
7706 END_PROFILE(SMBtrans2);
7707 return;
7710 if (dscnt > state->total_data ||
7711 dsoff+dscnt < dsoff) {
7712 goto bad_param;
7715 if (dsoff > av_size ||
7716 dscnt > av_size ||
7717 dsoff+dscnt > av_size) {
7718 goto bad_param;
7721 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7724 if (state->total_param) {
7725 /* Can't use talloc here, the core routines do realloc on the
7726 * params and data. */
7727 state->param = (char *)SMB_MALLOC(state->total_param);
7728 if (state->param == NULL) {
7729 DEBUG(0,("reply_trans: param malloc fail for %u "
7730 "bytes !\n", (unsigned int)state->total_param));
7731 SAFE_FREE(state->data);
7732 TALLOC_FREE(state);
7733 reply_nterror(req, NT_STATUS_NO_MEMORY);
7734 END_PROFILE(SMBtrans2);
7735 return;
7738 if (pscnt > state->total_param ||
7739 psoff+pscnt < psoff) {
7740 goto bad_param;
7743 if (psoff > av_size ||
7744 pscnt > av_size ||
7745 psoff+pscnt > av_size) {
7746 goto bad_param;
7749 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7752 state->received_data = dscnt;
7753 state->received_param = pscnt;
7755 if ((state->received_param == state->total_param) &&
7756 (state->received_data == state->total_data)) {
7758 handle_trans2(conn, req, state);
7760 SAFE_FREE(state->data);
7761 SAFE_FREE(state->param);
7762 TALLOC_FREE(state);
7763 END_PROFILE(SMBtrans2);
7764 return;
7767 DLIST_ADD(conn->pending_trans, state);
7769 /* We need to send an interim response then receive the rest
7770 of the parameter/data bytes */
7771 reply_outbuf(req, 0, 0);
7772 show_msg((char *)req->outbuf);
7773 END_PROFILE(SMBtrans2);
7774 return;
7776 bad_param:
7778 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7779 SAFE_FREE(state->data);
7780 SAFE_FREE(state->param);
7781 TALLOC_FREE(state);
7782 END_PROFILE(SMBtrans2);
7783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7787 /****************************************************************************
7788 Reply to a SMBtranss2
7789 ****************************************************************************/
7791 void reply_transs2(struct smb_request *req)
7793 connection_struct *conn = req->conn;
7794 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7795 struct trans_state *state;
7796 unsigned int size;
7797 unsigned int av_size;
7799 START_PROFILE(SMBtranss2);
7801 show_msg((char *)req->inbuf);
7803 if (req->wct < 8) {
7804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7805 END_PROFILE(SMBtranss2);
7806 return;
7809 size = smb_len(req->inbuf)+4;
7810 av_size = smb_len(req->inbuf);
7812 for (state = conn->pending_trans; state != NULL;
7813 state = state->next) {
7814 if (state->mid == req->mid) {
7815 break;
7819 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7821 END_PROFILE(SMBtranss2);
7822 return;
7825 /* Revise state->total_param and state->total_data in case they have
7826 changed downwards */
7828 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7829 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7830 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7831 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7833 pcnt = SVAL(req->inbuf, smb_spscnt);
7834 poff = SVAL(req->inbuf, smb_spsoff);
7835 pdisp = SVAL(req->inbuf, smb_spsdisp);
7837 dcnt = SVAL(req->inbuf, smb_sdscnt);
7838 doff = SVAL(req->inbuf, smb_sdsoff);
7839 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7841 state->received_param += pcnt;
7842 state->received_data += dcnt;
7844 if ((state->received_data > state->total_data) ||
7845 (state->received_param > state->total_param))
7846 goto bad_param;
7848 if (pcnt) {
7849 if (pdisp > state->total_param ||
7850 pcnt > state->total_param ||
7851 pdisp+pcnt > state->total_param ||
7852 pdisp+pcnt < pdisp) {
7853 goto bad_param;
7856 if (poff > av_size ||
7857 pcnt > av_size ||
7858 poff+pcnt > av_size ||
7859 poff+pcnt < poff) {
7860 goto bad_param;
7863 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7864 pcnt);
7867 if (dcnt) {
7868 if (ddisp > state->total_data ||
7869 dcnt > state->total_data ||
7870 ddisp+dcnt > state->total_data ||
7871 ddisp+dcnt < ddisp) {
7872 goto bad_param;
7875 if (doff > av_size ||
7876 dcnt > av_size ||
7877 doff+dcnt > av_size ||
7878 doff+dcnt < doff) {
7879 goto bad_param;
7882 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7883 dcnt);
7886 if ((state->received_param < state->total_param) ||
7887 (state->received_data < state->total_data)) {
7888 END_PROFILE(SMBtranss2);
7889 return;
7893 * construct_reply_common will copy smb_com from inbuf to
7894 * outbuf. SMBtranss2 is wrong here.
7896 SCVAL(req->inbuf,smb_com,SMBtrans2);
7898 handle_trans2(conn, req, state);
7900 DLIST_REMOVE(conn->pending_trans, state);
7901 SAFE_FREE(state->data);
7902 SAFE_FREE(state->param);
7903 TALLOC_FREE(state);
7905 END_PROFILE(SMBtranss2);
7906 return;
7908 bad_param:
7910 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7911 DLIST_REMOVE(conn->pending_trans, state);
7912 SAFE_FREE(state->data);
7913 SAFE_FREE(state->param);
7914 TALLOC_FREE(state);
7915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7916 END_PROFILE(SMBtranss2);
7917 return;