s3: Fix stream marshalling to return the correct streaminfo status
[Samba/bb.git] / source / smbd / trans2.c
blobc27464a945406465f006081883158c55d03f16f5
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 const char *fname,
4975 SMB_STRUCT_STAT *psbuf,
4976 uint32 dosmode)
4978 if (!VALID_STAT(*psbuf)) {
4979 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4982 if (dosmode) {
4983 if (S_ISDIR(psbuf->st_mode)) {
4984 dosmode |= aDIR;
4985 } else {
4986 dosmode &= ~aDIR;
4990 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4992 /* check the mode isn't different, before changing it */
4993 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4995 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4996 fname, (unsigned int)dosmode ));
4998 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4999 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5000 fname, strerror(errno)));
5001 return map_nt_error_from_unix(errno);
5004 return NT_STATUS_OK;
5007 /****************************************************************************
5008 Deal with setting the size from any of the setfilepathinfo functions.
5009 ****************************************************************************/
5011 static NTSTATUS smb_set_file_size(connection_struct *conn,
5012 struct smb_request *req,
5013 files_struct *fsp,
5014 const char *fname,
5015 SMB_STRUCT_STAT *psbuf,
5016 SMB_OFF_T size)
5018 NTSTATUS status = NT_STATUS_OK;
5019 files_struct *new_fsp = NULL;
5021 if (!VALID_STAT(*psbuf)) {
5022 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5025 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5027 if (size == get_file_size(*psbuf)) {
5028 return NT_STATUS_OK;
5031 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5032 fname, (double)size ));
5034 if (fsp && fsp->fh->fd != -1) {
5035 /* Handle based call. */
5036 if (vfs_set_filelen(fsp, size) == -1) {
5037 return map_nt_error_from_unix(errno);
5039 trigger_write_time_update_immediate(fsp);
5040 return NT_STATUS_OK;
5043 status = open_file_ntcreate(conn, req, fname, psbuf,
5044 FILE_WRITE_ATTRIBUTES,
5045 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5046 FILE_OPEN,
5048 FILE_ATTRIBUTE_NORMAL,
5049 FORCE_OPLOCK_BREAK_TO_NONE,
5050 NULL, &new_fsp);
5052 if (!NT_STATUS_IS_OK(status)) {
5053 /* NB. We check for open_was_deferred in the caller. */
5054 return status;
5057 if (vfs_set_filelen(new_fsp, size) == -1) {
5058 status = map_nt_error_from_unix(errno);
5059 close_file(new_fsp,NORMAL_CLOSE);
5060 return status;
5063 trigger_write_time_update_immediate(new_fsp);
5064 close_file(new_fsp,NORMAL_CLOSE);
5065 return NT_STATUS_OK;
5068 /****************************************************************************
5069 Deal with SMB_INFO_SET_EA.
5070 ****************************************************************************/
5072 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5073 const char *pdata,
5074 int total_data,
5075 files_struct *fsp,
5076 const char *fname)
5078 struct ea_list *ea_list = NULL;
5079 TALLOC_CTX *ctx = NULL;
5080 NTSTATUS status = NT_STATUS_OK;
5082 if (total_data < 10) {
5084 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5085 length. They seem to have no effect. Bug #3212. JRA */
5087 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5088 /* We're done. We only get EA info in this call. */
5089 return NT_STATUS_OK;
5092 return NT_STATUS_INVALID_PARAMETER;
5095 if (IVAL(pdata,0) > total_data) {
5096 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5097 IVAL(pdata,0), (unsigned int)total_data));
5098 return NT_STATUS_INVALID_PARAMETER;
5101 ctx = talloc_tos();
5102 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5103 if (!ea_list) {
5104 return NT_STATUS_INVALID_PARAMETER;
5106 status = set_ea(conn, fsp, fname, ea_list);
5108 return status;
5111 /****************************************************************************
5112 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5113 ****************************************************************************/
5115 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5116 const char *pdata,
5117 int total_data,
5118 files_struct *fsp,
5119 const char *fname,
5120 SMB_STRUCT_STAT *psbuf)
5122 NTSTATUS status = NT_STATUS_OK;
5123 bool delete_on_close;
5124 uint32 dosmode = 0;
5126 if (total_data < 1) {
5127 return NT_STATUS_INVALID_PARAMETER;
5130 if (fsp == NULL) {
5131 return NT_STATUS_INVALID_HANDLE;
5134 delete_on_close = (CVAL(pdata,0) ? True : False);
5135 dosmode = dos_mode(conn, fname, psbuf);
5137 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5138 "delete_on_close = %u\n",
5139 fsp->fsp_name,
5140 (unsigned int)dosmode,
5141 (unsigned int)delete_on_close ));
5143 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5145 if (!NT_STATUS_IS_OK(status)) {
5146 return status;
5149 /* The set is across all open files on this dev/inode pair. */
5150 if (!set_delete_on_close(fsp, delete_on_close,
5151 &conn->server_info->utok)) {
5152 return NT_STATUS_ACCESS_DENIED;
5154 return NT_STATUS_OK;
5157 /****************************************************************************
5158 Deal with SMB_FILE_POSITION_INFORMATION.
5159 ****************************************************************************/
5161 static NTSTATUS smb_file_position_information(connection_struct *conn,
5162 const char *pdata,
5163 int total_data,
5164 files_struct *fsp)
5166 SMB_BIG_UINT position_information;
5168 if (total_data < 8) {
5169 return NT_STATUS_INVALID_PARAMETER;
5172 if (fsp == NULL) {
5173 /* Ignore on pathname based set. */
5174 return NT_STATUS_OK;
5177 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5178 #ifdef LARGE_SMB_OFF_T
5179 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5180 #else /* LARGE_SMB_OFF_T */
5181 if (IVAL(pdata,4) != 0) {
5182 /* more than 32 bits? */
5183 return NT_STATUS_INVALID_PARAMETER;
5185 #endif /* LARGE_SMB_OFF_T */
5187 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5188 fsp->fsp_name, (double)position_information ));
5189 fsp->fh->position_information = position_information;
5190 return NT_STATUS_OK;
5193 /****************************************************************************
5194 Deal with SMB_FILE_MODE_INFORMATION.
5195 ****************************************************************************/
5197 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5198 const char *pdata,
5199 int total_data)
5201 uint32 mode;
5203 if (total_data < 4) {
5204 return NT_STATUS_INVALID_PARAMETER;
5206 mode = IVAL(pdata,0);
5207 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5208 return NT_STATUS_INVALID_PARAMETER;
5210 return NT_STATUS_OK;
5213 /****************************************************************************
5214 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5215 ****************************************************************************/
5217 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5218 struct smb_request *req,
5219 const char *pdata,
5220 int total_data,
5221 const char *fname)
5223 char *link_target = NULL;
5224 const char *newname = fname;
5225 NTSTATUS status = NT_STATUS_OK;
5226 TALLOC_CTX *ctx = talloc_tos();
5228 /* Set a symbolic link. */
5229 /* Don't allow this if follow links is false. */
5231 if (total_data == 0) {
5232 return NT_STATUS_INVALID_PARAMETER;
5235 if (!lp_symlinks(SNUM(conn))) {
5236 return NT_STATUS_ACCESS_DENIED;
5239 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5240 total_data, STR_TERMINATE);
5242 if (!link_target) {
5243 return NT_STATUS_INVALID_PARAMETER;
5246 /* !widelinks forces the target path to be within the share. */
5247 /* This means we can interpret the target as a pathname. */
5248 if (!lp_widelinks(SNUM(conn))) {
5249 char *rel_name = NULL;
5250 char *last_dirp = NULL;
5252 if (*link_target == '/') {
5253 /* No absolute paths allowed. */
5254 return NT_STATUS_ACCESS_DENIED;
5256 rel_name = talloc_strdup(ctx,newname);
5257 if (!rel_name) {
5258 return NT_STATUS_NO_MEMORY;
5260 last_dirp = strrchr_m(rel_name, '/');
5261 if (last_dirp) {
5262 last_dirp[1] = '\0';
5263 } else {
5264 rel_name = talloc_strdup(ctx,"./");
5265 if (!rel_name) {
5266 return NT_STATUS_NO_MEMORY;
5269 rel_name = talloc_asprintf_append(rel_name,
5270 "%s",
5271 link_target);
5272 if (!rel_name) {
5273 return NT_STATUS_NO_MEMORY;
5276 status = check_name(conn, rel_name);
5277 if (!NT_STATUS_IS_OK(status)) {
5278 return status;
5282 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5283 newname, link_target ));
5285 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5286 return map_nt_error_from_unix(errno);
5289 return NT_STATUS_OK;
5292 /****************************************************************************
5293 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5294 ****************************************************************************/
5296 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5297 struct smb_request *req,
5298 const char *pdata, int total_data,
5299 const char *fname)
5301 char *oldname = NULL;
5302 TALLOC_CTX *ctx = talloc_tos();
5303 NTSTATUS status = NT_STATUS_OK;
5305 /* Set a hard link. */
5306 if (total_data == 0) {
5307 return NT_STATUS_INVALID_PARAMETER;
5310 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5311 total_data, STR_TERMINATE, &status);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 return status;
5316 status = resolve_dfspath(ctx, conn,
5317 req->flags2 & FLAGS2_DFS_PATHNAMES,
5318 oldname,
5319 &oldname);
5320 if (!NT_STATUS_IS_OK(status)) {
5321 return status;
5324 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5325 fname, oldname));
5327 return hardlink_internals(ctx, conn, oldname, fname);
5330 /****************************************************************************
5331 Deal with SMB_FILE_RENAME_INFORMATION.
5332 ****************************************************************************/
5334 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5335 struct smb_request *req,
5336 const char *pdata,
5337 int total_data,
5338 files_struct *fsp,
5339 const char *fname)
5341 bool overwrite;
5342 uint32 root_fid;
5343 uint32 len;
5344 char *newname = NULL;
5345 char *base_name = NULL;
5346 bool dest_has_wcard = False;
5347 SMB_STRUCT_STAT sbuf;
5348 char *newname_last_component = NULL;
5349 NTSTATUS status = NT_STATUS_OK;
5350 char *p;
5351 TALLOC_CTX *ctx = talloc_tos();
5353 if (total_data < 13) {
5354 return NT_STATUS_INVALID_PARAMETER;
5357 ZERO_STRUCT(sbuf);
5359 overwrite = (CVAL(pdata,0) ? True : False);
5360 root_fid = IVAL(pdata,4);
5361 len = IVAL(pdata,8);
5363 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5364 return NT_STATUS_INVALID_PARAMETER;
5367 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5368 len, 0, &status,
5369 &dest_has_wcard);
5370 if (!NT_STATUS_IS_OK(status)) {
5371 return status;
5374 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5375 newname));
5377 status = resolve_dfspath_wcard(ctx, conn,
5378 req->flags2 & FLAGS2_DFS_PATHNAMES,
5379 newname,
5380 &newname,
5381 &dest_has_wcard);
5382 if (!NT_STATUS_IS_OK(status)) {
5383 return status;
5386 /* Check the new name has no '/' characters. */
5387 if (strchr_m(newname, '/')) {
5388 return NT_STATUS_NOT_SUPPORTED;
5391 if (fsp && fsp->base_fsp) {
5392 /* newname must be a stream name. */
5393 if (newname[0] != ':') {
5394 return NT_STATUS_NOT_SUPPORTED;
5396 base_name = talloc_asprintf(ctx, "%s%s",
5397 fsp->base_fsp->fsp_name,
5398 newname);
5399 if (!base_name) {
5400 return NT_STATUS_NO_MEMORY;
5402 } else {
5403 /* newname must *not* be a stream name. */
5404 if (is_ntfs_stream_name(newname)) {
5405 return NT_STATUS_NOT_SUPPORTED;
5408 /* Create the base directory. */
5409 base_name = talloc_strdup(ctx, fname);
5410 if (!base_name) {
5411 return NT_STATUS_NO_MEMORY;
5413 p = strrchr_m(base_name, '/');
5414 if (p) {
5415 p[1] = '\0';
5416 } else {
5417 base_name = talloc_strdup(ctx, "./");
5418 if (!base_name) {
5419 return NT_STATUS_NO_MEMORY;
5422 /* Append the new name. */
5423 base_name = talloc_asprintf_append(base_name,
5424 "%s",
5425 newname);
5426 if (!base_name) {
5427 return NT_STATUS_NO_MEMORY;
5430 status = unix_convert(ctx, conn, newname, False,
5431 &newname,
5432 &newname_last_component,
5433 &sbuf);
5435 /* If an error we expect this to be
5436 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5438 if (!NT_STATUS_IS_OK(status)
5439 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5440 status)) {
5441 return status;
5445 if (fsp) {
5446 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5447 fsp->fnum, fsp->fsp_name, base_name ));
5448 status = rename_internals_fsp(conn, fsp, base_name,
5449 newname_last_component, 0,
5450 overwrite);
5451 } else {
5452 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5453 fname, base_name ));
5454 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5455 overwrite, False, dest_has_wcard,
5456 FILE_WRITE_ATTRIBUTES);
5459 return status;
5462 /****************************************************************************
5463 Deal with SMB_SET_POSIX_ACL.
5464 ****************************************************************************/
5466 #if defined(HAVE_POSIX_ACLS)
5467 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5468 const char *pdata,
5469 int total_data,
5470 files_struct *fsp,
5471 const char *fname,
5472 SMB_STRUCT_STAT *psbuf)
5474 uint16 posix_acl_version;
5475 uint16 num_file_acls;
5476 uint16 num_def_acls;
5477 bool valid_file_acls = True;
5478 bool valid_def_acls = True;
5480 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5481 return NT_STATUS_INVALID_PARAMETER;
5483 posix_acl_version = SVAL(pdata,0);
5484 num_file_acls = SVAL(pdata,2);
5485 num_def_acls = SVAL(pdata,4);
5487 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5488 valid_file_acls = False;
5489 num_file_acls = 0;
5492 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5493 valid_def_acls = False;
5494 num_def_acls = 0;
5497 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5498 return NT_STATUS_INVALID_PARAMETER;
5501 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5502 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5503 return NT_STATUS_INVALID_PARAMETER;
5506 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5507 fname ? fname : fsp->fsp_name,
5508 (unsigned int)num_file_acls,
5509 (unsigned int)num_def_acls));
5511 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5512 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5513 return map_nt_error_from_unix(errno);
5516 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5517 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5518 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5519 return map_nt_error_from_unix(errno);
5521 return NT_STATUS_OK;
5523 #endif
5525 /****************************************************************************
5526 Deal with SMB_SET_POSIX_LOCK.
5527 ****************************************************************************/
5529 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5530 const struct smb_request *req,
5531 const char *pdata,
5532 int total_data,
5533 files_struct *fsp)
5535 SMB_BIG_UINT count;
5536 SMB_BIG_UINT offset;
5537 uint32 lock_pid;
5538 bool blocking_lock = False;
5539 enum brl_type lock_type;
5541 NTSTATUS status = NT_STATUS_OK;
5543 if (fsp == NULL || fsp->fh->fd == -1) {
5544 return NT_STATUS_INVALID_HANDLE;
5547 if (total_data != POSIX_LOCK_DATA_SIZE) {
5548 return NT_STATUS_INVALID_PARAMETER;
5551 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5552 case POSIX_LOCK_TYPE_READ:
5553 lock_type = READ_LOCK;
5554 break;
5555 case POSIX_LOCK_TYPE_WRITE:
5556 /* Return the right POSIX-mappable error code for files opened read-only. */
5557 if (!fsp->can_write) {
5558 return NT_STATUS_INVALID_HANDLE;
5560 lock_type = WRITE_LOCK;
5561 break;
5562 case POSIX_LOCK_TYPE_UNLOCK:
5563 lock_type = UNLOCK_LOCK;
5564 break;
5565 default:
5566 return NT_STATUS_INVALID_PARAMETER;
5569 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5570 blocking_lock = False;
5571 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5572 blocking_lock = True;
5573 } else {
5574 return NT_STATUS_INVALID_PARAMETER;
5577 if (!lp_blocking_locks(SNUM(conn))) {
5578 blocking_lock = False;
5581 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5582 #if defined(HAVE_LONGLONG)
5583 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5584 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5585 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5586 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5587 #else /* HAVE_LONGLONG */
5588 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5589 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5590 #endif /* HAVE_LONGLONG */
5592 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5593 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5594 fsp->fsp_name,
5595 (unsigned int)lock_type,
5596 (unsigned int)lock_pid,
5597 (double)count,
5598 (double)offset ));
5600 if (lock_type == UNLOCK_LOCK) {
5601 status = do_unlock(smbd_messaging_context(),
5602 fsp,
5603 lock_pid,
5604 count,
5605 offset,
5606 POSIX_LOCK);
5607 } else {
5608 uint32 block_smbpid;
5610 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5611 fsp,
5612 lock_pid,
5613 count,
5614 offset,
5615 lock_type,
5616 POSIX_LOCK,
5617 blocking_lock,
5618 &status,
5619 &block_smbpid);
5621 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5623 * A blocking lock was requested. Package up
5624 * this smb into a queued request and push it
5625 * onto the blocking lock queue.
5627 if(push_blocking_lock_request(br_lck,
5628 req,
5629 fsp,
5630 -1, /* infinite timeout. */
5632 lock_pid,
5633 lock_type,
5634 POSIX_LOCK,
5635 offset,
5636 count,
5637 block_smbpid)) {
5638 TALLOC_FREE(br_lck);
5639 return status;
5642 TALLOC_FREE(br_lck);
5645 return status;
5648 /****************************************************************************
5649 Deal with SMB_INFO_STANDARD.
5650 ****************************************************************************/
5652 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5653 const char *pdata,
5654 int total_data,
5655 files_struct *fsp,
5656 const char *fname,
5657 const SMB_STRUCT_STAT *psbuf)
5659 struct timespec ts[2];
5661 if (total_data < 12) {
5662 return NT_STATUS_INVALID_PARAMETER;
5665 /* access time */
5666 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5667 /* write time */
5668 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5670 DEBUG(10,("smb_set_info_standard: file %s\n",
5671 fname ? fname : fsp->fsp_name ));
5673 return smb_set_file_time(conn,
5674 fsp,
5675 fname,
5676 psbuf,
5678 true);
5681 /****************************************************************************
5682 Deal with SMB_SET_FILE_BASIC_INFO.
5683 ****************************************************************************/
5685 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5686 const char *pdata,
5687 int total_data,
5688 files_struct *fsp,
5689 const char *fname,
5690 SMB_STRUCT_STAT *psbuf)
5692 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5693 struct timespec write_time;
5694 struct timespec changed_time;
5695 uint32 dosmode = 0;
5696 struct timespec ts[2];
5697 NTSTATUS status = NT_STATUS_OK;
5698 bool setting_write_time = true;
5700 if (total_data < 36) {
5701 return NT_STATUS_INVALID_PARAMETER;
5704 /* Set the attributes */
5705 dosmode = IVAL(pdata,32);
5706 status = smb_set_file_dosmode(conn,
5707 fname,
5708 psbuf,
5709 dosmode);
5710 if (!NT_STATUS_IS_OK(status)) {
5711 return status;
5714 /* Ignore create time at offset pdata. */
5716 /* access time */
5717 ts[0] = interpret_long_date(pdata+8);
5719 write_time = interpret_long_date(pdata+16);
5720 changed_time = interpret_long_date(pdata+24);
5722 /* mtime */
5723 ts[1] = timespec_min(&write_time, &changed_time);
5725 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5726 ts[1] = write_time;
5729 /* Prefer a defined time to an undefined one. */
5730 if (null_timespec(ts[1])) {
5731 if (null_timespec(write_time)) {
5732 ts[1] = changed_time;
5733 setting_write_time = false;
5734 } else {
5735 ts[1] = write_time;
5739 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5740 fname ? fname : fsp->fsp_name ));
5742 return smb_set_file_time(conn,
5743 fsp,
5744 fname,
5745 psbuf,
5747 setting_write_time);
5750 /****************************************************************************
5751 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5752 ****************************************************************************/
5754 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5755 struct smb_request *req,
5756 const char *pdata,
5757 int total_data,
5758 files_struct *fsp,
5759 const char *fname,
5760 SMB_STRUCT_STAT *psbuf)
5762 SMB_BIG_UINT allocation_size = 0;
5763 NTSTATUS status = NT_STATUS_OK;
5764 files_struct *new_fsp = NULL;
5766 if (!VALID_STAT(*psbuf)) {
5767 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5770 if (total_data < 8) {
5771 return NT_STATUS_INVALID_PARAMETER;
5774 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5775 #ifdef LARGE_SMB_OFF_T
5776 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5777 #else /* LARGE_SMB_OFF_T */
5778 if (IVAL(pdata,4) != 0) {
5779 /* more than 32 bits? */
5780 return NT_STATUS_INVALID_PARAMETER;
5782 #endif /* LARGE_SMB_OFF_T */
5784 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5785 fname, (double)allocation_size ));
5787 if (allocation_size) {
5788 allocation_size = smb_roundup(conn, allocation_size);
5791 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5792 fname, (double)allocation_size ));
5794 if (fsp && fsp->fh->fd != -1) {
5795 /* Open file handle. */
5796 /* Only change if needed. */
5797 if (allocation_size != get_file_size(*psbuf)) {
5798 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5799 return map_nt_error_from_unix(errno);
5802 /* But always update the time. */
5804 * This is equivalent to a write. Ensure it's seen immediately
5805 * if there are no pending writes.
5807 trigger_write_time_update_immediate(fsp);
5808 return NT_STATUS_OK;
5811 /* Pathname or stat or directory file. */
5813 status = open_file_ntcreate(conn, req, fname, psbuf,
5814 FILE_WRITE_DATA,
5815 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5816 FILE_OPEN,
5818 FILE_ATTRIBUTE_NORMAL,
5819 FORCE_OPLOCK_BREAK_TO_NONE,
5820 NULL, &new_fsp);
5822 if (!NT_STATUS_IS_OK(status)) {
5823 /* NB. We check for open_was_deferred in the caller. */
5824 return status;
5827 /* Only change if needed. */
5828 if (allocation_size != get_file_size(*psbuf)) {
5829 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5830 status = map_nt_error_from_unix(errno);
5831 close_file(new_fsp,NORMAL_CLOSE);
5832 return status;
5836 /* Changing the allocation size should set the last mod time. */
5838 * This is equivalent to a write. Ensure it's seen immediately
5839 * if there are no pending writes.
5841 trigger_write_time_update_immediate(new_fsp);
5843 close_file(new_fsp,NORMAL_CLOSE);
5844 return NT_STATUS_OK;
5847 /****************************************************************************
5848 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5849 ****************************************************************************/
5851 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5852 struct smb_request *req,
5853 const char *pdata,
5854 int total_data,
5855 files_struct *fsp,
5856 const char *fname,
5857 SMB_STRUCT_STAT *psbuf)
5859 SMB_OFF_T size;
5861 if (total_data < 8) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 size = IVAL(pdata,0);
5866 #ifdef LARGE_SMB_OFF_T
5867 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5868 #else /* LARGE_SMB_OFF_T */
5869 if (IVAL(pdata,4) != 0) {
5870 /* more than 32 bits? */
5871 return NT_STATUS_INVALID_PARAMETER;
5873 #endif /* LARGE_SMB_OFF_T */
5874 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5875 "file %s to %.0f\n", fname, (double)size ));
5877 return smb_set_file_size(conn, req,
5878 fsp,
5879 fname,
5880 psbuf,
5881 size);
5884 /****************************************************************************
5885 Allow a UNIX info mknod.
5886 ****************************************************************************/
5888 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5889 const char *pdata,
5890 int total_data,
5891 const char *fname,
5892 SMB_STRUCT_STAT *psbuf)
5894 uint32 file_type = IVAL(pdata,56);
5895 #if defined(HAVE_MAKEDEV)
5896 uint32 dev_major = IVAL(pdata,60);
5897 uint32 dev_minor = IVAL(pdata,68);
5898 #endif
5899 SMB_DEV_T dev = (SMB_DEV_T)0;
5900 uint32 raw_unixmode = IVAL(pdata,84);
5901 NTSTATUS status;
5902 mode_t unixmode;
5904 if (total_data < 100) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5909 if (!NT_STATUS_IS_OK(status)) {
5910 return status;
5913 #if defined(HAVE_MAKEDEV)
5914 dev = makedev(dev_major, dev_minor);
5915 #endif
5917 switch (file_type) {
5918 #if defined(S_IFIFO)
5919 case UNIX_TYPE_FIFO:
5920 unixmode |= S_IFIFO;
5921 break;
5922 #endif
5923 #if defined(S_IFSOCK)
5924 case UNIX_TYPE_SOCKET:
5925 unixmode |= S_IFSOCK;
5926 break;
5927 #endif
5928 #if defined(S_IFCHR)
5929 case UNIX_TYPE_CHARDEV:
5930 unixmode |= S_IFCHR;
5931 break;
5932 #endif
5933 #if defined(S_IFBLK)
5934 case UNIX_TYPE_BLKDEV:
5935 unixmode |= S_IFBLK;
5936 break;
5937 #endif
5938 default:
5939 return NT_STATUS_INVALID_PARAMETER;
5942 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5943 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5945 /* Ok - do the mknod. */
5946 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5947 return map_nt_error_from_unix(errno);
5950 /* If any of the other "set" calls fail we
5951 * don't want to end up with a half-constructed mknod.
5954 if (lp_inherit_perms(SNUM(conn))) {
5955 inherit_access_posix_acl(
5956 conn, parent_dirname(fname),
5957 fname, unixmode);
5960 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5961 status = map_nt_error_from_unix(errno);
5962 SMB_VFS_UNLINK(conn,fname);
5963 return status;
5965 return NT_STATUS_OK;
5968 /****************************************************************************
5969 Deal with SMB_SET_FILE_UNIX_BASIC.
5970 ****************************************************************************/
5972 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5973 struct smb_request *req,
5974 const char *pdata,
5975 int total_data,
5976 files_struct *fsp,
5977 const char *fname,
5978 SMB_STRUCT_STAT *psbuf)
5980 struct timespec ts[2];
5981 uint32 raw_unixmode;
5982 mode_t unixmode;
5983 SMB_OFF_T size = 0;
5984 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5985 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5986 NTSTATUS status = NT_STATUS_OK;
5987 bool delete_on_fail = False;
5988 enum perm_type ptype;
5990 if (total_data < 100) {
5991 return NT_STATUS_INVALID_PARAMETER;
5994 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5995 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5996 size=IVAL(pdata,0); /* first 8 Bytes are size */
5997 #ifdef LARGE_SMB_OFF_T
5998 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5999 #else /* LARGE_SMB_OFF_T */
6000 if (IVAL(pdata,4) != 0) {
6001 /* more than 32 bits? */
6002 return NT_STATUS_INVALID_PARAMETER;
6004 #endif /* LARGE_SMB_OFF_T */
6007 ts[0] = interpret_long_date(pdata+24); /* access_time */
6008 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6009 set_owner = (uid_t)IVAL(pdata,40);
6010 set_grp = (gid_t)IVAL(pdata,48);
6011 raw_unixmode = IVAL(pdata,84);
6013 if (VALID_STAT(*psbuf)) {
6014 if (S_ISDIR(psbuf->st_mode)) {
6015 ptype = PERM_EXISTING_DIR;
6016 } else {
6017 ptype = PERM_EXISTING_FILE;
6019 } else {
6020 ptype = PERM_NEW_FILE;
6023 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6024 if (!NT_STATUS_IS_OK(status)) {
6025 return status;
6028 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6029 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6030 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6032 if (!VALID_STAT(*psbuf)) {
6034 * The only valid use of this is to create character and block
6035 * devices, and named pipes. This is deprecated (IMHO) and
6036 * a new info level should be used for mknod. JRA.
6039 status = smb_unix_mknod(conn,
6040 pdata,
6041 total_data,
6042 fname,
6043 psbuf);
6044 if (!NT_STATUS_IS_OK(status)) {
6045 return status;
6048 /* Ensure we don't try and change anything else. */
6049 raw_unixmode = SMB_MODE_NO_CHANGE;
6050 size = get_file_size(*psbuf);
6051 ts[0] = get_atimespec(psbuf);
6052 ts[1] = get_mtimespec(psbuf);
6054 * We continue here as we might want to change the
6055 * owner uid/gid.
6057 delete_on_fail = True;
6060 #if 1
6061 /* Horrible backwards compatibility hack as an old server bug
6062 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6063 * */
6065 if (!size) {
6066 size = get_file_size(*psbuf);
6068 #endif
6071 * Deal with the UNIX specific mode set.
6074 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6075 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6076 (unsigned int)unixmode, fname ));
6077 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6078 return map_nt_error_from_unix(errno);
6083 * Deal with the UNIX specific uid set.
6086 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6087 int ret;
6089 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6090 (unsigned int)set_owner, fname ));
6092 if (S_ISLNK(psbuf->st_mode)) {
6093 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6094 } else {
6095 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6098 if (ret != 0) {
6099 status = map_nt_error_from_unix(errno);
6100 if (delete_on_fail) {
6101 SMB_VFS_UNLINK(conn,fname);
6103 return status;
6108 * Deal with the UNIX specific gid set.
6111 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6112 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6113 (unsigned int)set_owner, fname ));
6114 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6115 status = map_nt_error_from_unix(errno);
6116 if (delete_on_fail) {
6117 SMB_VFS_UNLINK(conn,fname);
6119 return status;
6123 /* Deal with any size changes. */
6125 status = smb_set_file_size(conn, req,
6126 fsp,
6127 fname,
6128 psbuf,
6129 size);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 return status;
6134 /* Deal with any time changes. */
6136 return smb_set_file_time(conn,
6137 fsp,
6138 fname,
6139 psbuf,
6141 true);
6144 /****************************************************************************
6145 Deal with SMB_SET_FILE_UNIX_INFO2.
6146 ****************************************************************************/
6148 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6149 struct smb_request *req,
6150 const char *pdata,
6151 int total_data,
6152 files_struct *fsp,
6153 const char *fname,
6154 SMB_STRUCT_STAT *psbuf)
6156 NTSTATUS status;
6157 uint32 smb_fflags;
6158 uint32 smb_fmask;
6160 if (total_data < 116) {
6161 return NT_STATUS_INVALID_PARAMETER;
6164 /* Start by setting all the fields that are common between UNIX_BASIC
6165 * and UNIX_INFO2.
6167 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6168 fsp, fname, psbuf);
6169 if (!NT_STATUS_IS_OK(status)) {
6170 return status;
6173 smb_fflags = IVAL(pdata, 108);
6174 smb_fmask = IVAL(pdata, 112);
6176 /* NB: We should only attempt to alter the file flags if the client
6177 * sends a non-zero mask.
6179 if (smb_fmask != 0) {
6180 int stat_fflags = 0;
6182 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6183 &stat_fflags)) {
6184 /* Client asked to alter a flag we don't understand. */
6185 return NT_STATUS_INVALID_PARAMETER;
6188 if (fsp && fsp->fh->fd != -1) {
6189 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6190 return NT_STATUS_NOT_SUPPORTED;
6191 } else {
6192 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6193 return map_nt_error_from_unix(errno);
6198 /* XXX: need to add support for changing the create_time here. You
6199 * can do this for paths on Darwin with setattrlist(2). The right way
6200 * to hook this up is probably by extending the VFS utimes interface.
6203 return NT_STATUS_OK;
6206 /****************************************************************************
6207 Create a directory with POSIX semantics.
6208 ****************************************************************************/
6210 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6211 struct smb_request *req,
6212 char **ppdata,
6213 int total_data,
6214 const char *fname,
6215 SMB_STRUCT_STAT *psbuf,
6216 int *pdata_return_size)
6218 NTSTATUS status = NT_STATUS_OK;
6219 uint32 raw_unixmode = 0;
6220 uint32 mod_unixmode = 0;
6221 mode_t unixmode = (mode_t)0;
6222 files_struct *fsp = NULL;
6223 uint16 info_level_return = 0;
6224 int info;
6225 char *pdata = *ppdata;
6227 if (total_data < 18) {
6228 return NT_STATUS_INVALID_PARAMETER;
6231 raw_unixmode = IVAL(pdata,8);
6232 /* Next 4 bytes are not yet defined. */
6234 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 return status;
6239 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6241 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6242 fname, (unsigned int)unixmode ));
6244 status = open_directory(conn, req,
6245 fname,
6246 psbuf,
6247 FILE_READ_ATTRIBUTES, /* Just a stat open */
6248 FILE_SHARE_NONE, /* Ignored for stat opens */
6249 FILE_CREATE,
6251 mod_unixmode,
6252 &info,
6253 &fsp);
6255 if (NT_STATUS_IS_OK(status)) {
6256 close_file(fsp, NORMAL_CLOSE);
6259 info_level_return = SVAL(pdata,16);
6261 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6262 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6263 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6264 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6265 } else {
6266 *pdata_return_size = 12;
6269 /* Realloc the data size */
6270 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6271 if (*ppdata == NULL) {
6272 *pdata_return_size = 0;
6273 return NT_STATUS_NO_MEMORY;
6275 pdata = *ppdata;
6277 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6278 SSVAL(pdata,2,0); /* No fnum. */
6279 SIVAL(pdata,4,info); /* Was directory created. */
6281 switch (info_level_return) {
6282 case SMB_QUERY_FILE_UNIX_BASIC:
6283 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6284 SSVAL(pdata,10,0); /* Padding. */
6285 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6286 break;
6287 case SMB_QUERY_FILE_UNIX_INFO2:
6288 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6289 SSVAL(pdata,10,0); /* Padding. */
6290 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6291 break;
6292 default:
6293 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6294 SSVAL(pdata,10,0); /* Padding. */
6295 break;
6298 return status;
6301 /****************************************************************************
6302 Open/Create a file with POSIX semantics.
6303 ****************************************************************************/
6305 static NTSTATUS smb_posix_open(connection_struct *conn,
6306 struct smb_request *req,
6307 char **ppdata,
6308 int total_data,
6309 const char *fname,
6310 SMB_STRUCT_STAT *psbuf,
6311 int *pdata_return_size)
6313 bool extended_oplock_granted = False;
6314 char *pdata = *ppdata;
6315 uint32 flags = 0;
6316 uint32 wire_open_mode = 0;
6317 uint32 raw_unixmode = 0;
6318 uint32 mod_unixmode = 0;
6319 uint32 create_disp = 0;
6320 uint32 access_mask = 0;
6321 uint32 create_options = 0;
6322 NTSTATUS status = NT_STATUS_OK;
6323 mode_t unixmode = (mode_t)0;
6324 files_struct *fsp = NULL;
6325 int oplock_request = 0;
6326 int info = 0;
6327 uint16 info_level_return = 0;
6329 if (total_data < 18) {
6330 return NT_STATUS_INVALID_PARAMETER;
6333 flags = IVAL(pdata,0);
6334 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6335 if (oplock_request) {
6336 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6339 wire_open_mode = IVAL(pdata,4);
6341 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6342 return smb_posix_mkdir(conn, req,
6343 ppdata,
6344 total_data,
6345 fname,
6346 psbuf,
6347 pdata_return_size);
6350 switch (wire_open_mode & SMB_ACCMODE) {
6351 case SMB_O_RDONLY:
6352 access_mask = FILE_READ_DATA;
6353 break;
6354 case SMB_O_WRONLY:
6355 access_mask = FILE_WRITE_DATA;
6356 break;
6357 case SMB_O_RDWR:
6358 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6359 break;
6360 default:
6361 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6362 (unsigned int)wire_open_mode ));
6363 return NT_STATUS_INVALID_PARAMETER;
6366 wire_open_mode &= ~SMB_ACCMODE;
6368 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6369 create_disp = FILE_CREATE;
6370 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6371 create_disp = FILE_OVERWRITE_IF;
6372 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6373 create_disp = FILE_OPEN_IF;
6374 } else {
6375 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6376 (unsigned int)wire_open_mode ));
6377 return NT_STATUS_INVALID_PARAMETER;
6380 raw_unixmode = IVAL(pdata,8);
6381 /* Next 4 bytes are not yet defined. */
6383 status = unix_perms_from_wire(conn,
6384 psbuf,
6385 raw_unixmode,
6386 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6387 &unixmode);
6389 if (!NT_STATUS_IS_OK(status)) {
6390 return status;
6393 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6395 if (wire_open_mode & SMB_O_SYNC) {
6396 create_options |= FILE_WRITE_THROUGH;
6398 if (wire_open_mode & SMB_O_APPEND) {
6399 access_mask |= FILE_APPEND_DATA;
6401 if (wire_open_mode & SMB_O_DIRECT) {
6402 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6405 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6406 fname,
6407 (unsigned int)wire_open_mode,
6408 (unsigned int)unixmode ));
6410 status = open_file_ntcreate(conn, req,
6411 fname,
6412 psbuf,
6413 access_mask,
6414 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6415 create_disp,
6416 0, /* no create options yet. */
6417 mod_unixmode,
6418 oplock_request,
6419 &info,
6420 &fsp);
6422 if (!NT_STATUS_IS_OK(status)) {
6423 return status;
6426 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6427 extended_oplock_granted = True;
6430 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6431 extended_oplock_granted = True;
6434 info_level_return = SVAL(pdata,16);
6436 /* Allocate the correct return size. */
6438 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6439 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6440 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6441 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6442 } else {
6443 *pdata_return_size = 12;
6446 /* Realloc the data size */
6447 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6448 if (*ppdata == NULL) {
6449 close_file(fsp,ERROR_CLOSE);
6450 *pdata_return_size = 0;
6451 return NT_STATUS_NO_MEMORY;
6453 pdata = *ppdata;
6455 if (extended_oplock_granted) {
6456 if (flags & REQUEST_BATCH_OPLOCK) {
6457 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6458 } else {
6459 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6461 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6462 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6463 } else {
6464 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6467 SSVAL(pdata,2,fsp->fnum);
6468 SIVAL(pdata,4,info); /* Was file created etc. */
6470 switch (info_level_return) {
6471 case SMB_QUERY_FILE_UNIX_BASIC:
6472 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6473 SSVAL(pdata,10,0); /* padding. */
6474 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6475 break;
6476 case SMB_QUERY_FILE_UNIX_INFO2:
6477 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6478 SSVAL(pdata,10,0); /* padding. */
6479 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6480 break;
6481 default:
6482 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6483 SSVAL(pdata,10,0); /* padding. */
6484 break;
6486 return NT_STATUS_OK;
6489 /****************************************************************************
6490 Delete a file with POSIX semantics.
6491 ****************************************************************************/
6493 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6494 struct smb_request *req,
6495 const char *pdata,
6496 int total_data,
6497 const char *fname,
6498 SMB_STRUCT_STAT *psbuf)
6500 NTSTATUS status = NT_STATUS_OK;
6501 files_struct *fsp = NULL;
6502 uint16 flags = 0;
6503 char del = 1;
6504 int info = 0;
6505 int i;
6506 struct share_mode_lock *lck = NULL;
6508 if (total_data < 2) {
6509 return NT_STATUS_INVALID_PARAMETER;
6512 flags = SVAL(pdata,0);
6514 if (!VALID_STAT(*psbuf)) {
6515 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6518 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6519 !VALID_STAT_OF_DIR(*psbuf)) {
6520 return NT_STATUS_NOT_A_DIRECTORY;
6523 DEBUG(10,("smb_posix_unlink: %s %s\n",
6524 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6525 fname));
6527 if (VALID_STAT_OF_DIR(*psbuf)) {
6528 status = open_directory(conn, req,
6529 fname,
6530 psbuf,
6531 DELETE_ACCESS,
6532 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6533 FILE_OPEN,
6535 FILE_FLAG_POSIX_SEMANTICS|0777,
6536 &info,
6537 &fsp);
6538 } else {
6540 status = open_file_ntcreate(conn, req,
6541 fname,
6542 psbuf,
6543 DELETE_ACCESS,
6544 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6545 FILE_OPEN,
6547 FILE_FLAG_POSIX_SEMANTICS|0777,
6548 0, /* No oplock, but break existing ones. */
6549 &info,
6550 &fsp);
6553 if (!NT_STATUS_IS_OK(status)) {
6554 return status;
6558 * Don't lie to client. If we can't really delete due to
6559 * non-POSIX opens return SHARING_VIOLATION.
6562 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6563 NULL);
6564 if (lck == NULL) {
6565 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6566 "lock for file %s\n", fsp->fsp_name));
6567 close_file(fsp, NORMAL_CLOSE);
6568 return NT_STATUS_INVALID_PARAMETER;
6572 * See if others still have the file open. If this is the case, then
6573 * don't delete. If all opens are POSIX delete we can set the delete
6574 * on close disposition.
6576 for (i=0; i<lck->num_share_modes; i++) {
6577 struct share_mode_entry *e = &lck->share_modes[i];
6578 if (is_valid_share_mode_entry(e)) {
6579 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6580 continue;
6582 /* Fail with sharing violation. */
6583 close_file(fsp, NORMAL_CLOSE);
6584 TALLOC_FREE(lck);
6585 return NT_STATUS_SHARING_VIOLATION;
6590 * Set the delete on close.
6592 status = smb_set_file_disposition_info(conn,
6593 &del,
6595 fsp,
6596 fname,
6597 psbuf);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 close_file(fsp, NORMAL_CLOSE);
6601 TALLOC_FREE(lck);
6602 return status;
6604 TALLOC_FREE(lck);
6605 return close_file(fsp, NORMAL_CLOSE);
6608 /****************************************************************************
6609 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6610 ****************************************************************************/
6612 static void call_trans2setfilepathinfo(connection_struct *conn,
6613 struct smb_request *req,
6614 unsigned int tran_call,
6615 char **pparams, int total_params,
6616 char **ppdata, int total_data,
6617 unsigned int max_data_bytes)
6619 char *params = *pparams;
6620 char *pdata = *ppdata;
6621 uint16 info_level;
6622 SMB_STRUCT_STAT sbuf;
6623 char *fname = NULL;
6624 files_struct *fsp = NULL;
6625 NTSTATUS status = NT_STATUS_OK;
6626 int data_return_size = 0;
6627 TALLOC_CTX *ctx = talloc_tos();
6629 if (!params) {
6630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6631 return;
6634 ZERO_STRUCT(sbuf);
6636 if (tran_call == TRANSACT2_SETFILEINFO) {
6637 if (total_params < 4) {
6638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6639 return;
6642 fsp = file_fsp(SVAL(params,0));
6643 /* Basic check for non-null fsp. */
6644 if (!check_fsp_open(conn, req, fsp)) {
6645 return;
6647 info_level = SVAL(params,2);
6649 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6650 if (!fname) {
6651 reply_nterror(req, NT_STATUS_NO_MEMORY);
6652 return;
6655 if(fsp->is_directory || fsp->fh->fd == -1) {
6657 * This is actually a SETFILEINFO on a directory
6658 * handle (returned from an NT SMB). NT5.0 seems
6659 * to do this call. JRA.
6661 if (INFO_LEVEL_IS_UNIX(info_level)) {
6662 /* Always do lstat for UNIX calls. */
6663 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6664 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6665 reply_unixerror(req,ERRDOS,ERRbadpath);
6666 return;
6668 } else {
6669 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6670 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6671 reply_unixerror(req,ERRDOS,ERRbadpath);
6672 return;
6675 } else if (fsp->print_file) {
6677 * Doing a DELETE_ON_CLOSE should cancel a print job.
6679 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6680 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6682 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6684 SSVAL(params,0,0);
6685 send_trans2_replies(conn, req, params, 2,
6686 *ppdata, 0,
6687 max_data_bytes);
6688 return;
6689 } else {
6690 reply_unixerror(req, ERRDOS, ERRbadpath);
6691 return;
6693 } else {
6695 * Original code - this is an open file.
6697 if (!check_fsp(conn, req, fsp)) {
6698 return;
6701 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6702 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6703 reply_unixerror(req, ERRDOS, ERRbadfid);
6704 return;
6707 } else {
6708 /* set path info */
6709 if (total_params < 7) {
6710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6711 return;
6714 info_level = SVAL(params,0);
6715 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6716 total_params - 6, STR_TERMINATE,
6717 &status);
6718 if (!NT_STATUS_IS_OK(status)) {
6719 reply_nterror(req, status);
6720 return;
6723 status = resolve_dfspath(ctx, conn,
6724 req->flags2 & FLAGS2_DFS_PATHNAMES,
6725 fname,
6726 &fname);
6727 if (!NT_STATUS_IS_OK(status)) {
6728 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6729 reply_botherror(req,
6730 NT_STATUS_PATH_NOT_COVERED,
6731 ERRSRV, ERRbadpath);
6732 return;
6734 reply_nterror(req, status);
6735 return;
6738 status = unix_convert(ctx, conn, fname, False,
6739 &fname, NULL, &sbuf);
6740 if (!NT_STATUS_IS_OK(status)) {
6741 reply_nterror(req, status);
6742 return;
6745 status = check_name(conn, fname);
6746 if (!NT_STATUS_IS_OK(status)) {
6747 reply_nterror(req, status);
6748 return;
6751 if (INFO_LEVEL_IS_UNIX(info_level)) {
6753 * For CIFS UNIX extensions the target name may not exist.
6756 /* Always do lstat for UNIX calls. */
6757 SMB_VFS_LSTAT(conn,fname,&sbuf);
6759 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6760 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6761 reply_unixerror(req, ERRDOS, ERRbadpath);
6762 return;
6766 if (!CAN_WRITE(conn)) {
6767 reply_doserror(req, ERRSRV, ERRaccess);
6768 return;
6771 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6772 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6773 return;
6776 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6777 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6779 /* Realloc the parameter size */
6780 *pparams = (char *)SMB_REALLOC(*pparams,2);
6781 if (*pparams == NULL) {
6782 reply_nterror(req, NT_STATUS_NO_MEMORY);
6783 return;
6785 params = *pparams;
6787 SSVAL(params,0,0);
6789 switch (info_level) {
6791 case SMB_INFO_STANDARD:
6793 status = smb_set_info_standard(conn,
6794 pdata,
6795 total_data,
6796 fsp,
6797 fname,
6798 &sbuf);
6799 break;
6802 case SMB_INFO_SET_EA:
6804 status = smb_info_set_ea(conn,
6805 pdata,
6806 total_data,
6807 fsp,
6808 fname);
6809 break;
6812 case SMB_SET_FILE_BASIC_INFO:
6813 case SMB_FILE_BASIC_INFORMATION:
6815 status = smb_set_file_basic_info(conn,
6816 pdata,
6817 total_data,
6818 fsp,
6819 fname,
6820 &sbuf);
6821 break;
6824 case SMB_FILE_ALLOCATION_INFORMATION:
6825 case SMB_SET_FILE_ALLOCATION_INFO:
6827 status = smb_set_file_allocation_info(conn, req,
6828 pdata,
6829 total_data,
6830 fsp,
6831 fname,
6832 &sbuf);
6833 break;
6836 case SMB_FILE_END_OF_FILE_INFORMATION:
6837 case SMB_SET_FILE_END_OF_FILE_INFO:
6839 status = smb_set_file_end_of_file_info(conn, req,
6840 pdata,
6841 total_data,
6842 fsp,
6843 fname,
6844 &sbuf);
6845 break;
6848 case SMB_FILE_DISPOSITION_INFORMATION:
6849 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6851 #if 0
6852 /* JRA - We used to just ignore this on a path ?
6853 * Shouldn't this be invalid level on a pathname
6854 * based call ?
6856 if (tran_call != TRANSACT2_SETFILEINFO) {
6857 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6859 #endif
6860 status = smb_set_file_disposition_info(conn,
6861 pdata,
6862 total_data,
6863 fsp,
6864 fname,
6865 &sbuf);
6866 break;
6869 case SMB_FILE_POSITION_INFORMATION:
6871 status = smb_file_position_information(conn,
6872 pdata,
6873 total_data,
6874 fsp);
6875 break;
6878 /* From tridge Samba4 :
6879 * MODE_INFORMATION in setfileinfo (I have no
6880 * idea what "mode information" on a file is - it takes a value of 0,
6881 * 2, 4 or 6. What could it be?).
6884 case SMB_FILE_MODE_INFORMATION:
6886 status = smb_file_mode_information(conn,
6887 pdata,
6888 total_data);
6889 break;
6893 * CIFS UNIX extensions.
6896 case SMB_SET_FILE_UNIX_BASIC:
6898 status = smb_set_file_unix_basic(conn, req,
6899 pdata,
6900 total_data,
6901 fsp,
6902 fname,
6903 &sbuf);
6904 break;
6907 case SMB_SET_FILE_UNIX_INFO2:
6909 status = smb_set_file_unix_info2(conn, req,
6910 pdata,
6911 total_data,
6912 fsp,
6913 fname,
6914 &sbuf);
6915 break;
6918 case SMB_SET_FILE_UNIX_LINK:
6920 if (tran_call != TRANSACT2_SETPATHINFO) {
6921 /* We must have a pathname for this. */
6922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6923 return;
6925 status = smb_set_file_unix_link(conn, req, pdata,
6926 total_data, fname);
6927 break;
6930 case SMB_SET_FILE_UNIX_HLINK:
6932 if (tran_call != TRANSACT2_SETPATHINFO) {
6933 /* We must have a pathname for this. */
6934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6935 return;
6937 status = smb_set_file_unix_hlink(conn, req,
6938 pdata, total_data,
6939 fname);
6940 break;
6943 case SMB_FILE_RENAME_INFORMATION:
6945 status = smb_file_rename_information(conn, req,
6946 pdata, total_data,
6947 fsp, fname);
6948 break;
6951 #if defined(HAVE_POSIX_ACLS)
6952 case SMB_SET_POSIX_ACL:
6954 status = smb_set_posix_acl(conn,
6955 pdata,
6956 total_data,
6957 fsp,
6958 fname,
6959 &sbuf);
6960 break;
6962 #endif
6964 case SMB_SET_POSIX_LOCK:
6966 if (tran_call != TRANSACT2_SETFILEINFO) {
6967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6968 return;
6970 status = smb_set_posix_lock(conn, req,
6971 pdata, total_data, fsp);
6972 break;
6975 case SMB_POSIX_PATH_OPEN:
6977 if (tran_call != TRANSACT2_SETPATHINFO) {
6978 /* We must have a pathname for this. */
6979 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6980 return;
6983 status = smb_posix_open(conn, req,
6984 ppdata,
6985 total_data,
6986 fname,
6987 &sbuf,
6988 &data_return_size);
6989 break;
6992 case SMB_POSIX_PATH_UNLINK:
6994 if (tran_call != TRANSACT2_SETPATHINFO) {
6995 /* We must have a pathname for this. */
6996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6997 return;
7000 status = smb_posix_unlink(conn, req,
7001 pdata,
7002 total_data,
7003 fname,
7004 &sbuf);
7005 break;
7008 default:
7009 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7010 return;
7014 if (!NT_STATUS_IS_OK(status)) {
7015 if (open_was_deferred(req->mid)) {
7016 /* We have re-scheduled this call. */
7017 return;
7019 if (blocking_lock_was_deferred(req->mid)) {
7020 /* We have re-scheduled this call. */
7021 return;
7023 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7024 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7025 ERRSRV, ERRbadpath);
7026 return;
7028 if (info_level == SMB_POSIX_PATH_OPEN) {
7029 reply_openerror(req, status);
7030 return;
7033 reply_nterror(req, status);
7034 return;
7037 SSVAL(params,0,0);
7038 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7039 max_data_bytes);
7041 return;
7044 /****************************************************************************
7045 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7046 ****************************************************************************/
7048 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7049 char **pparams, int total_params,
7050 char **ppdata, int total_data,
7051 unsigned int max_data_bytes)
7053 char *params = *pparams;
7054 char *pdata = *ppdata;
7055 char *directory = NULL;
7056 SMB_STRUCT_STAT sbuf;
7057 NTSTATUS status = NT_STATUS_OK;
7058 struct ea_list *ea_list = NULL;
7059 TALLOC_CTX *ctx = talloc_tos();
7061 if (!CAN_WRITE(conn)) {
7062 reply_doserror(req, ERRSRV, ERRaccess);
7063 return;
7066 if (total_params < 5) {
7067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7068 return;
7071 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7072 total_params - 4, STR_TERMINATE,
7073 &status);
7074 if (!NT_STATUS_IS_OK(status)) {
7075 reply_nterror(req, status);
7076 return;
7079 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7081 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 reply_nterror(req, status);
7084 return;
7087 status = check_name(conn, directory);
7088 if (!NT_STATUS_IS_OK(status)) {
7089 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7090 reply_nterror(req, status);
7091 return;
7094 /* Any data in this call is an EA list. */
7095 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7096 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7097 return;
7101 * OS/2 workplace shell seems to send SET_EA requests of "null"
7102 * length (4 bytes containing IVAL 4).
7103 * They seem to have no effect. Bug #3212. JRA.
7106 if (total_data != 4) {
7107 if (total_data < 10) {
7108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7109 return;
7112 if (IVAL(pdata,0) > total_data) {
7113 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7114 IVAL(pdata,0), (unsigned int)total_data));
7115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7116 return;
7119 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7120 total_data - 4);
7121 if (!ea_list) {
7122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7123 return;
7126 /* If total_data == 4 Windows doesn't care what values
7127 * are placed in that field, it just ignores them.
7128 * The System i QNTC IBM SMB client puts bad values here,
7129 * so ignore them. */
7131 status = create_directory(conn, req, directory);
7133 if (!NT_STATUS_IS_OK(status)) {
7134 reply_nterror(req, status);
7135 return;
7138 /* Try and set any given EA. */
7139 if (ea_list) {
7140 status = set_ea(conn, NULL, directory, ea_list);
7141 if (!NT_STATUS_IS_OK(status)) {
7142 reply_nterror(req, status);
7143 return;
7147 /* Realloc the parameter and data sizes */
7148 *pparams = (char *)SMB_REALLOC(*pparams,2);
7149 if(*pparams == NULL) {
7150 reply_nterror(req, NT_STATUS_NO_MEMORY);
7151 return;
7153 params = *pparams;
7155 SSVAL(params,0,0);
7157 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7159 return;
7162 /****************************************************************************
7163 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7164 We don't actually do this - we just send a null response.
7165 ****************************************************************************/
7167 static void call_trans2findnotifyfirst(connection_struct *conn,
7168 struct smb_request *req,
7169 char **pparams, int total_params,
7170 char **ppdata, int total_data,
7171 unsigned int max_data_bytes)
7173 static uint16 fnf_handle = 257;
7174 char *params = *pparams;
7175 uint16 info_level;
7177 if (total_params < 6) {
7178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7179 return;
7182 info_level = SVAL(params,4);
7183 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7185 switch (info_level) {
7186 case 1:
7187 case 2:
7188 break;
7189 default:
7190 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7191 return;
7194 /* Realloc the parameter and data sizes */
7195 *pparams = (char *)SMB_REALLOC(*pparams,6);
7196 if (*pparams == NULL) {
7197 reply_nterror(req, NT_STATUS_NO_MEMORY);
7198 return;
7200 params = *pparams;
7202 SSVAL(params,0,fnf_handle);
7203 SSVAL(params,2,0); /* No changes */
7204 SSVAL(params,4,0); /* No EA errors */
7206 fnf_handle++;
7208 if(fnf_handle == 0)
7209 fnf_handle = 257;
7211 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7213 return;
7216 /****************************************************************************
7217 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7218 changes). Currently this does nothing.
7219 ****************************************************************************/
7221 static void call_trans2findnotifynext(connection_struct *conn,
7222 struct smb_request *req,
7223 char **pparams, int total_params,
7224 char **ppdata, int total_data,
7225 unsigned int max_data_bytes)
7227 char *params = *pparams;
7229 DEBUG(3,("call_trans2findnotifynext\n"));
7231 /* Realloc the parameter and data sizes */
7232 *pparams = (char *)SMB_REALLOC(*pparams,4);
7233 if (*pparams == NULL) {
7234 reply_nterror(req, NT_STATUS_NO_MEMORY);
7235 return;
7237 params = *pparams;
7239 SSVAL(params,0,0); /* No changes */
7240 SSVAL(params,2,0); /* No EA errors */
7242 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7244 return;
7247 /****************************************************************************
7248 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7249 ****************************************************************************/
7251 static void call_trans2getdfsreferral(connection_struct *conn,
7252 struct smb_request *req,
7253 char **pparams, int total_params,
7254 char **ppdata, int total_data,
7255 unsigned int max_data_bytes)
7257 char *params = *pparams;
7258 char *pathname = NULL;
7259 int reply_size = 0;
7260 int max_referral_level;
7261 NTSTATUS status = NT_STATUS_OK;
7262 TALLOC_CTX *ctx = talloc_tos();
7264 DEBUG(10,("call_trans2getdfsreferral\n"));
7266 if (total_params < 3) {
7267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7268 return;
7271 max_referral_level = SVAL(params,0);
7273 if(!lp_host_msdfs()) {
7274 reply_doserror(req, ERRDOS, ERRbadfunc);
7275 return;
7278 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7279 total_params - 2, STR_TERMINATE);
7280 if (!pathname) {
7281 reply_nterror(req, NT_STATUS_NOT_FOUND);
7282 return;
7284 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7285 ppdata,&status)) < 0) {
7286 reply_nterror(req, status);
7287 return;
7290 SSVAL(req->inbuf, smb_flg2,
7291 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7292 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7294 return;
7297 #define LMCAT_SPL 0x53
7298 #define LMFUNC_GETJOBID 0x60
7300 /****************************************************************************
7301 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7302 ****************************************************************************/
7304 static void call_trans2ioctl(connection_struct *conn,
7305 struct smb_request *req,
7306 char **pparams, int total_params,
7307 char **ppdata, int total_data,
7308 unsigned int max_data_bytes)
7310 char *pdata = *ppdata;
7311 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7313 /* check for an invalid fid before proceeding */
7315 if (!fsp) {
7316 reply_doserror(req, ERRDOS, ERRbadfid);
7317 return;
7320 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7321 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7322 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7323 if (*ppdata == NULL) {
7324 reply_nterror(req, NT_STATUS_NO_MEMORY);
7325 return;
7327 pdata = *ppdata;
7329 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7330 CAN ACCEPT THIS IN UNICODE. JRA. */
7332 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7333 srvstr_push(pdata, req->flags2, pdata + 2,
7334 global_myname(), 15,
7335 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7336 srvstr_push(pdata, req->flags2, pdata+18,
7337 lp_servicename(SNUM(conn)), 13,
7338 STR_ASCII|STR_TERMINATE); /* Service name */
7339 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7340 max_data_bytes);
7341 return;
7344 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7345 reply_doserror(req, ERRSRV, ERRerror);
7348 /****************************************************************************
7349 Reply to a SMBfindclose (stop trans2 directory search).
7350 ****************************************************************************/
7352 void reply_findclose(struct smb_request *req)
7354 int dptr_num;
7356 START_PROFILE(SMBfindclose);
7358 if (req->wct < 1) {
7359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7360 END_PROFILE(SMBfindclose);
7361 return;
7364 dptr_num = SVALS(req->inbuf,smb_vwv0);
7366 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7368 dptr_close(&dptr_num);
7370 reply_outbuf(req, 0, 0);
7372 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7374 END_PROFILE(SMBfindclose);
7375 return;
7378 /****************************************************************************
7379 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7380 ****************************************************************************/
7382 void reply_findnclose(struct smb_request *req)
7384 int dptr_num;
7386 START_PROFILE(SMBfindnclose);
7388 if (req->wct < 1) {
7389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7390 END_PROFILE(SMBfindnclose);
7391 return;
7394 dptr_num = SVAL(req->inbuf,smb_vwv0);
7396 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7398 /* We never give out valid handles for a
7399 findnotifyfirst - so any dptr_num is ok here.
7400 Just ignore it. */
7402 reply_outbuf(req, 0, 0);
7404 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7406 END_PROFILE(SMBfindnclose);
7407 return;
7410 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7411 struct trans_state *state)
7413 if (Protocol >= PROTOCOL_NT1) {
7414 req->flags2 |= 0x40; /* IS_LONG_NAME */
7415 SSVAL(req->inbuf,smb_flg2,req->flags2);
7418 if (conn->encrypt_level == Required && !req->encrypted) {
7419 if (state->call != TRANSACT2_QFSINFO &&
7420 state->call != TRANSACT2_SETFSINFO) {
7421 DEBUG(0,("handle_trans2: encryption required "
7422 "with call 0x%x\n",
7423 (unsigned int)state->call));
7424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7425 return;
7429 /* Now we must call the relevant TRANS2 function */
7430 switch(state->call) {
7431 case TRANSACT2_OPEN:
7433 START_PROFILE(Trans2_open);
7434 call_trans2open(conn, req,
7435 &state->param, state->total_param,
7436 &state->data, state->total_data,
7437 state->max_data_return);
7438 END_PROFILE(Trans2_open);
7439 break;
7442 case TRANSACT2_FINDFIRST:
7444 START_PROFILE(Trans2_findfirst);
7445 call_trans2findfirst(conn, req,
7446 &state->param, state->total_param,
7447 &state->data, state->total_data,
7448 state->max_data_return);
7449 END_PROFILE(Trans2_findfirst);
7450 break;
7453 case TRANSACT2_FINDNEXT:
7455 START_PROFILE(Trans2_findnext);
7456 call_trans2findnext(conn, req,
7457 &state->param, state->total_param,
7458 &state->data, state->total_data,
7459 state->max_data_return);
7460 END_PROFILE(Trans2_findnext);
7461 break;
7464 case TRANSACT2_QFSINFO:
7466 START_PROFILE(Trans2_qfsinfo);
7467 call_trans2qfsinfo(conn, req,
7468 &state->param, state->total_param,
7469 &state->data, state->total_data,
7470 state->max_data_return);
7471 END_PROFILE(Trans2_qfsinfo);
7472 break;
7475 case TRANSACT2_SETFSINFO:
7477 START_PROFILE(Trans2_setfsinfo);
7478 call_trans2setfsinfo(conn, req,
7479 &state->param, state->total_param,
7480 &state->data, state->total_data,
7481 state->max_data_return);
7482 END_PROFILE(Trans2_setfsinfo);
7483 break;
7486 case TRANSACT2_QPATHINFO:
7487 case TRANSACT2_QFILEINFO:
7489 START_PROFILE(Trans2_qpathinfo);
7490 call_trans2qfilepathinfo(conn, req, state->call,
7491 &state->param, state->total_param,
7492 &state->data, state->total_data,
7493 state->max_data_return);
7494 END_PROFILE(Trans2_qpathinfo);
7495 break;
7498 case TRANSACT2_SETPATHINFO:
7499 case TRANSACT2_SETFILEINFO:
7501 START_PROFILE(Trans2_setpathinfo);
7502 call_trans2setfilepathinfo(conn, req, state->call,
7503 &state->param, state->total_param,
7504 &state->data, state->total_data,
7505 state->max_data_return);
7506 END_PROFILE(Trans2_setpathinfo);
7507 break;
7510 case TRANSACT2_FINDNOTIFYFIRST:
7512 START_PROFILE(Trans2_findnotifyfirst);
7513 call_trans2findnotifyfirst(conn, req,
7514 &state->param, state->total_param,
7515 &state->data, state->total_data,
7516 state->max_data_return);
7517 END_PROFILE(Trans2_findnotifyfirst);
7518 break;
7521 case TRANSACT2_FINDNOTIFYNEXT:
7523 START_PROFILE(Trans2_findnotifynext);
7524 call_trans2findnotifynext(conn, req,
7525 &state->param, state->total_param,
7526 &state->data, state->total_data,
7527 state->max_data_return);
7528 END_PROFILE(Trans2_findnotifynext);
7529 break;
7532 case TRANSACT2_MKDIR:
7534 START_PROFILE(Trans2_mkdir);
7535 call_trans2mkdir(conn, req,
7536 &state->param, state->total_param,
7537 &state->data, state->total_data,
7538 state->max_data_return);
7539 END_PROFILE(Trans2_mkdir);
7540 break;
7543 case TRANSACT2_GET_DFS_REFERRAL:
7545 START_PROFILE(Trans2_get_dfs_referral);
7546 call_trans2getdfsreferral(conn, req,
7547 &state->param, state->total_param,
7548 &state->data, state->total_data,
7549 state->max_data_return);
7550 END_PROFILE(Trans2_get_dfs_referral);
7551 break;
7554 case TRANSACT2_IOCTL:
7556 START_PROFILE(Trans2_ioctl);
7557 call_trans2ioctl(conn, req,
7558 &state->param, state->total_param,
7559 &state->data, state->total_data,
7560 state->max_data_return);
7561 END_PROFILE(Trans2_ioctl);
7562 break;
7565 default:
7566 /* Error in request */
7567 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7568 reply_doserror(req, ERRSRV,ERRerror);
7572 /****************************************************************************
7573 Reply to a SMBtrans2.
7574 ****************************************************************************/
7576 void reply_trans2(struct smb_request *req)
7578 connection_struct *conn = req->conn;
7579 unsigned int dsoff;
7580 unsigned int dscnt;
7581 unsigned int psoff;
7582 unsigned int pscnt;
7583 unsigned int tran_call;
7584 unsigned int size;
7585 unsigned int av_size;
7586 struct trans_state *state;
7587 NTSTATUS result;
7589 START_PROFILE(SMBtrans2);
7591 if (req->wct < 14) {
7592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7593 END_PROFILE(SMBtrans2);
7594 return;
7597 dsoff = SVAL(req->inbuf, smb_dsoff);
7598 dscnt = SVAL(req->inbuf, smb_dscnt);
7599 psoff = SVAL(req->inbuf, smb_psoff);
7600 pscnt = SVAL(req->inbuf, smb_pscnt);
7601 tran_call = SVAL(req->inbuf, smb_setup0);
7602 size = smb_len(req->inbuf) + 4;
7603 av_size = smb_len(req->inbuf);
7605 result = allow_new_trans(conn->pending_trans, req->mid);
7606 if (!NT_STATUS_IS_OK(result)) {
7607 DEBUG(2, ("Got invalid trans2 request: %s\n",
7608 nt_errstr(result)));
7609 reply_nterror(req, result);
7610 END_PROFILE(SMBtrans2);
7611 return;
7614 if (IS_IPC(conn)) {
7615 switch (tran_call) {
7616 /* List the allowed trans2 calls on IPC$ */
7617 case TRANSACT2_OPEN:
7618 case TRANSACT2_GET_DFS_REFERRAL:
7619 case TRANSACT2_QFILEINFO:
7620 case TRANSACT2_QFSINFO:
7621 case TRANSACT2_SETFSINFO:
7622 break;
7623 default:
7624 reply_doserror(req, ERRSRV, ERRaccess);
7625 END_PROFILE(SMBtrans2);
7626 return;
7630 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7631 DEBUG(0, ("talloc failed\n"));
7632 reply_nterror(req, NT_STATUS_NO_MEMORY);
7633 END_PROFILE(SMBtrans2);
7634 return;
7637 state->cmd = SMBtrans2;
7639 state->mid = req->mid;
7640 state->vuid = req->vuid;
7641 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7642 state->setup = NULL;
7643 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7644 state->param = NULL;
7645 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7646 state->data = NULL;
7647 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7648 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7649 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7650 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7651 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7653 state->call = tran_call;
7655 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7656 is so as a sanity check */
7657 if (state->setup_count != 1) {
7659 * Need to have rc=0 for ioctl to get job id for OS/2.
7660 * Network printing will fail if function is not successful.
7661 * Similar function in reply.c will be used if protocol
7662 * is LANMAN1.0 instead of LM1.2X002.
7663 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7664 * outbuf doesn't have to be set(only job id is used).
7666 if ( (state->setup_count == 4)
7667 && (tran_call == TRANSACT2_IOCTL)
7668 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7669 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7670 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7671 } else {
7672 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7673 DEBUG(2,("Transaction is %d\n",tran_call));
7674 TALLOC_FREE(state);
7675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7676 END_PROFILE(SMBtrans2);
7677 return;
7681 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7682 goto bad_param;
7684 if (state->total_data) {
7685 /* Can't use talloc here, the core routines do realloc on the
7686 * params and data. */
7687 state->data = (char *)SMB_MALLOC(state->total_data);
7688 if (state->data == NULL) {
7689 DEBUG(0,("reply_trans2: data malloc fail for %u "
7690 "bytes !\n", (unsigned int)state->total_data));
7691 TALLOC_FREE(state);
7692 reply_nterror(req, NT_STATUS_NO_MEMORY);
7693 END_PROFILE(SMBtrans2);
7694 return;
7697 if (dscnt > state->total_data ||
7698 dsoff+dscnt < dsoff) {
7699 goto bad_param;
7702 if (dsoff > av_size ||
7703 dscnt > av_size ||
7704 dsoff+dscnt > av_size) {
7705 goto bad_param;
7708 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7711 if (state->total_param) {
7712 /* Can't use talloc here, the core routines do realloc on the
7713 * params and data. */
7714 state->param = (char *)SMB_MALLOC(state->total_param);
7715 if (state->param == NULL) {
7716 DEBUG(0,("reply_trans: param malloc fail for %u "
7717 "bytes !\n", (unsigned int)state->total_param));
7718 SAFE_FREE(state->data);
7719 TALLOC_FREE(state);
7720 reply_nterror(req, NT_STATUS_NO_MEMORY);
7721 END_PROFILE(SMBtrans2);
7722 return;
7725 if (pscnt > state->total_param ||
7726 psoff+pscnt < psoff) {
7727 goto bad_param;
7730 if (psoff > av_size ||
7731 pscnt > av_size ||
7732 psoff+pscnt > av_size) {
7733 goto bad_param;
7736 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7739 state->received_data = dscnt;
7740 state->received_param = pscnt;
7742 if ((state->received_param == state->total_param) &&
7743 (state->received_data == state->total_data)) {
7745 handle_trans2(conn, req, state);
7747 SAFE_FREE(state->data);
7748 SAFE_FREE(state->param);
7749 TALLOC_FREE(state);
7750 END_PROFILE(SMBtrans2);
7751 return;
7754 DLIST_ADD(conn->pending_trans, state);
7756 /* We need to send an interim response then receive the rest
7757 of the parameter/data bytes */
7758 reply_outbuf(req, 0, 0);
7759 show_msg((char *)req->outbuf);
7760 END_PROFILE(SMBtrans2);
7761 return;
7763 bad_param:
7765 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7766 SAFE_FREE(state->data);
7767 SAFE_FREE(state->param);
7768 TALLOC_FREE(state);
7769 END_PROFILE(SMBtrans2);
7770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7774 /****************************************************************************
7775 Reply to a SMBtranss2
7776 ****************************************************************************/
7778 void reply_transs2(struct smb_request *req)
7780 connection_struct *conn = req->conn;
7781 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7782 struct trans_state *state;
7783 unsigned int size;
7784 unsigned int av_size;
7786 START_PROFILE(SMBtranss2);
7788 show_msg((char *)req->inbuf);
7790 if (req->wct < 8) {
7791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7792 END_PROFILE(SMBtranss2);
7793 return;
7796 size = smb_len(req->inbuf)+4;
7797 av_size = smb_len(req->inbuf);
7799 for (state = conn->pending_trans; state != NULL;
7800 state = state->next) {
7801 if (state->mid == req->mid) {
7802 break;
7806 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7808 END_PROFILE(SMBtranss2);
7809 return;
7812 /* Revise state->total_param and state->total_data in case they have
7813 changed downwards */
7815 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7816 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7817 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7818 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7820 pcnt = SVAL(req->inbuf, smb_spscnt);
7821 poff = SVAL(req->inbuf, smb_spsoff);
7822 pdisp = SVAL(req->inbuf, smb_spsdisp);
7824 dcnt = SVAL(req->inbuf, smb_sdscnt);
7825 doff = SVAL(req->inbuf, smb_sdsoff);
7826 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7828 state->received_param += pcnt;
7829 state->received_data += dcnt;
7831 if ((state->received_data > state->total_data) ||
7832 (state->received_param > state->total_param))
7833 goto bad_param;
7835 if (pcnt) {
7836 if (pdisp > state->total_param ||
7837 pcnt > state->total_param ||
7838 pdisp+pcnt > state->total_param ||
7839 pdisp+pcnt < pdisp) {
7840 goto bad_param;
7843 if (poff > av_size ||
7844 pcnt > av_size ||
7845 poff+pcnt > av_size ||
7846 poff+pcnt < poff) {
7847 goto bad_param;
7850 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7851 pcnt);
7854 if (dcnt) {
7855 if (ddisp > state->total_data ||
7856 dcnt > state->total_data ||
7857 ddisp+dcnt > state->total_data ||
7858 ddisp+dcnt < ddisp) {
7859 goto bad_param;
7862 if (doff > av_size ||
7863 dcnt > av_size ||
7864 doff+dcnt > av_size ||
7865 doff+dcnt < doff) {
7866 goto bad_param;
7869 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7870 dcnt);
7873 if ((state->received_param < state->total_param) ||
7874 (state->received_data < state->total_data)) {
7875 END_PROFILE(SMBtranss2);
7876 return;
7880 * construct_reply_common will copy smb_com from inbuf to
7881 * outbuf. SMBtranss2 is wrong here.
7883 SCVAL(req->inbuf,smb_com,SMBtrans2);
7885 handle_trans2(conn, req, state);
7887 DLIST_REMOVE(conn->pending_trans, state);
7888 SAFE_FREE(state->data);
7889 SAFE_FREE(state->param);
7890 TALLOC_FREE(state);
7892 END_PROFILE(SMBtranss2);
7893 return;
7895 bad_param:
7897 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7898 DLIST_REMOVE(conn->pending_trans, state);
7899 SAFE_FREE(state->data);
7900 SAFE_FREE(state->param);
7901 TALLOC_FREE(state);
7902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7903 END_PROFILE(SMBtranss2);
7904 return;