s3: make better use of ccache by not including version.h in every C-file.
[Samba.git] / source3 / smbd / trans2.c
blob52340d53703873135d462993bfa4b7d5c4a51eed
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"
27 #include "version.h"
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
64 account sparse files.
65 ********************************************************************/
67 uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
69 uint64_t ret;
71 if(S_ISDIR(sbuf->st_mode)) {
72 return 0;
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
77 #else
78 ret = (uint64_t)get_file_size(*sbuf);
79 #endif
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char * const prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 NULL
103 int i;
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
107 return true;
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 return true;
113 return false;
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
126 char *val = NULL;
127 ssize_t sizeret;
129 again:
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (!val) {
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 } else {
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 attr_size = 65536;
144 goto again;
147 if (sizeret == -1) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
154 pea->flags = 0;
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 } else {
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
161 TALLOC_FREE(val);
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
166 return NT_STATUS_OK;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
177 char *p;
178 char **names, **tmp;
179 size_t num_names;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
183 *pnames = NULL;
184 *pnum_names = 0;
185 return NT_STATUS_OK;
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
193 if (names == NULL) {
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
204 TALLOC_FREE(names);
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
210 ea_namelist_size);
211 } else {
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
213 ea_namelist_size);
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
219 else {
220 break;
224 if (sizeret == -1) {
225 TALLOC_FREE(names);
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
232 if (sizeret == 0) {
233 TALLOC_FREE(names);
234 *pnames = NULL;
235 *pnum_names = 0;
236 return NT_STATUS_OK;
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
244 TALLOC_FREE(names);
245 return NT_STATUS_INTERNAL_ERROR;
249 * count the names
251 num_names = 0;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
254 num_names += 1;
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 if (tmp == NULL) {
259 DEBUG(0, ("talloc failed\n"));
260 TALLOC_FREE(names);
261 return NT_STATUS_NO_MEMORY;
264 names = tmp;
265 num_names = 0;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
271 *pnames = names;
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
401 return 0;
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
405 return total_ea_len;
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
414 size_t total_ea_len;
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
423 break;
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
439 int ret;
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
460 } else {
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
465 #ifdef ENOATTR
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
469 unix_ea_name));
470 ret = 0;
472 #endif
473 } else {
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
479 } else {
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
487 if (ret == -1) {
488 #ifdef ENOTSUP
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
492 #endif
493 return map_nt_error_from_unix(errno);
497 return NT_STATUS_OK;
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
518 break;
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
522 return NULL;
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
525 &converted_size)) {
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
529 if (!eal->ea.name) {
530 return NULL;
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 return ea_list_head;
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
548 uint16 val_len;
549 unsigned int namelen;
550 size_t converted_size;
552 if (!eal) {
553 return NULL;
556 if (data_size < 6) {
557 return NULL;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
565 return NULL;
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
570 return NULL;
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
574 strerror(errno)));
576 if (!eal->ea.name) {
577 return NULL;
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
582 return NULL;
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
592 if (pbytes_used) {
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
599 return eal;
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
609 size_t offset = 0;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
615 if (!eal) {
616 return NULL;
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
623 return ea_list_head;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
632 fstring dos_ea_name;
633 struct ea_list *listp;
634 size_t ret = 0;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
641 if (ret) {
642 ret += 4;
645 return ret;
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
661 break;
665 if (flistp) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
669 } else {
670 /* Null entry. */
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
677 return name_list;
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
689 const char *params,
690 int paramsize,
691 const char *pdata,
692 int datasize,
693 int max_data_bytes)
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
703 int useable_space;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
714 for OS/2. */
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
720 overflow = True;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
728 return;
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
743 + 2 * 10 /* wct */
744 + alignment_offset
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
772 * We might have SMBtrans2s in req which was transferred to
773 * the outbuf, fix that.
775 SCVAL(req->outbuf, smb_com, SMBtrans2);
777 /* Set total params and data to be sent */
778 SSVAL(req->outbuf,smb_tprcnt,paramsize);
779 SSVAL(req->outbuf,smb_tdrcnt,datasize);
781 /* Calculate how many parameters and data we can fit into
782 * this packet. Parameters get precedence
785 params_sent_thistime = MIN(params_to_send,useable_space);
786 data_sent_thistime = useable_space - params_sent_thistime;
787 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
789 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
791 /* smb_proff is the offset from the start of the SMB header to the
792 parameter bytes, however the first 4 bytes of outbuf are
793 the Netbios over TCP header. Thus use smb_base() to subtract
794 them from the calculation */
796 SSVAL(req->outbuf,smb_proff,
797 ((smb_buf(req->outbuf)+alignment_offset)
798 - smb_base(req->outbuf)));
800 if(params_sent_thistime == 0)
801 SSVAL(req->outbuf,smb_prdisp,0);
802 else
803 /* Absolute displacement of param bytes sent in this packet */
804 SSVAL(req->outbuf,smb_prdisp,pp - params);
806 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
807 if(data_sent_thistime == 0) {
808 SSVAL(req->outbuf,smb_droff,0);
809 SSVAL(req->outbuf,smb_drdisp, 0);
810 } else {
811 /* The offset of the data bytes is the offset of the
812 parameter bytes plus the number of parameters being sent this time */
813 SSVAL(req->outbuf, smb_droff,
814 ((smb_buf(req->outbuf)+alignment_offset)
815 - smb_base(req->outbuf))
816 + params_sent_thistime + data_alignment_offset);
817 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
820 /* Initialize the padding for alignment */
822 if (alignment_offset != 0) {
823 memset(smb_buf(req->outbuf), 0, alignment_offset);
826 /* Copy the param bytes into the packet */
828 if(params_sent_thistime) {
829 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
830 params_sent_thistime);
833 /* Copy in the data bytes */
834 if(data_sent_thistime) {
835 if (data_alignment_offset != 0) {
836 memset((smb_buf(req->outbuf)+alignment_offset+
837 params_sent_thistime), 0,
838 data_alignment_offset);
840 memcpy(smb_buf(req->outbuf)+alignment_offset
841 +params_sent_thistime+data_alignment_offset,
842 pd,data_sent_thistime);
845 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
846 params_sent_thistime, data_sent_thistime, useable_space));
847 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
848 params_to_send, data_to_send, paramsize, datasize));
850 if (overflow) {
851 error_packet_set((char *)req->outbuf,
852 ERRDOS,ERRbufferoverflow,
853 STATUS_BUFFER_OVERFLOW,
854 __LINE__,__FILE__);
857 /* Send the packet */
858 show_msg((char *)req->outbuf);
859 if (!srv_send_smb(smbd_server_fd(),
860 (char *)req->outbuf,
861 IS_CONN_ENCRYPTED(conn)))
862 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
864 TALLOC_FREE(req->outbuf);
866 pp += params_sent_thistime;
867 pd += data_sent_thistime;
869 params_to_send -= params_sent_thistime;
870 data_to_send -= data_sent_thistime;
872 /* Sanity check */
873 if(params_to_send < 0 || data_to_send < 0) {
874 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
875 params_to_send, data_to_send));
876 return;
880 return;
883 /****************************************************************************
884 Reply to a TRANSACT2_OPEN.
885 ****************************************************************************/
887 static void call_trans2open(connection_struct *conn,
888 struct smb_request *req,
889 char **pparams, int total_params,
890 char **ppdata, int total_data,
891 unsigned int max_data_bytes)
893 char *params = *pparams;
894 char *pdata = *ppdata;
895 int deny_mode;
896 int32 open_attr;
897 bool oplock_request;
898 #if 0
899 bool return_additional_info;
900 int16 open_sattr;
901 time_t open_time;
902 #endif
903 int open_ofun;
904 uint32 open_size;
905 char *pname;
906 char *fname = NULL;
907 SMB_OFF_T size=0;
908 int fattr=0,mtime=0;
909 SMB_INO_T inode = 0;
910 SMB_STRUCT_STAT sbuf;
911 int smb_action = 0;
912 files_struct *fsp;
913 struct ea_list *ea_list = NULL;
914 uint16 flags = 0;
915 NTSTATUS status;
916 uint32 access_mask;
917 uint32 share_mode;
918 uint32 create_disposition;
919 uint32 create_options = 0;
920 TALLOC_CTX *ctx = talloc_tos();
923 * Ensure we have enough parameters to perform the operation.
926 if (total_params < 29) {
927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 return;
931 flags = SVAL(params, 0);
932 deny_mode = SVAL(params, 2);
933 open_attr = SVAL(params,6);
934 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
935 if (oplock_request) {
936 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
939 #if 0
940 return_additional_info = BITSETW(params,0);
941 open_sattr = SVAL(params, 4);
942 open_time = make_unix_date3(params+8);
943 #endif
944 open_ofun = SVAL(params,12);
945 open_size = IVAL(params,14);
946 pname = &params[28];
948 if (IS_IPC(conn)) {
949 reply_doserror(req, ERRSRV, ERRaccess);
950 return;
953 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
954 total_params - 28, STR_TERMINATE,
955 &status);
956 if (!NT_STATUS_IS_OK(status)) {
957 reply_nterror(req, status);
958 return;
961 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
962 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
963 (unsigned int)open_ofun, open_size));
965 if (open_ofun == 0) {
966 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
967 return;
970 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
971 &access_mask,
972 &share_mode,
973 &create_disposition,
974 &create_options)) {
975 reply_doserror(req, ERRDOS, ERRbadaccess);
976 return;
979 /* Any data in this call is an EA list. */
980 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
981 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
982 return;
985 if (total_data != 4) {
986 if (total_data < 10) {
987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 return;
991 if (IVAL(pdata,0) > total_data) {
992 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
993 IVAL(pdata,0), (unsigned int)total_data));
994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
995 return;
998 ea_list = read_ea_list(talloc_tos(), pdata + 4,
999 total_data - 4);
1000 if (!ea_list) {
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1002 return;
1004 } else if (IVAL(pdata,0) != 4) {
1005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1006 return;
1009 status = SMB_VFS_CREATE_FILE(
1010 conn, /* conn */
1011 req, /* req */
1012 0, /* root_dir_fid */
1013 fname, /* fname */
1014 CFF_DOS_PATH, /* create_file_flags */
1015 access_mask, /* access_mask */
1016 share_mode, /* share_access */
1017 create_disposition, /* create_disposition*/
1018 create_options, /* create_options */
1019 open_attr, /* file_attributes */
1020 oplock_request, /* oplock_request */
1021 open_size, /* allocation_size */
1022 NULL, /* sd */
1023 ea_list, /* ea_list */
1024 &fsp, /* result */
1025 &smb_action, /* pinfo */
1026 &sbuf); /* psbuf */
1028 if (!NT_STATUS_IS_OK(status)) {
1029 if (open_was_deferred(req->mid)) {
1030 /* We have re-scheduled this call. */
1031 return;
1033 reply_openerror(req, status);
1034 return;
1037 size = get_file_size(sbuf);
1038 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1039 mtime = sbuf.st_mtime;
1040 inode = sbuf.st_ino;
1041 if (fattr & aDIR) {
1042 close_file(req, fsp, ERROR_CLOSE);
1043 reply_doserror(req, ERRDOS,ERRnoaccess);
1044 return;
1047 /* Realloc the size of parameters and data we will return */
1048 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1049 if(*pparams == NULL ) {
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1051 return;
1053 params = *pparams;
1055 SSVAL(params,0,fsp->fnum);
1056 SSVAL(params,2,fattr);
1057 srv_put_dos_date2(params,4, mtime);
1058 SIVAL(params,8, (uint32)size);
1059 SSVAL(params,12,deny_mode);
1060 SSVAL(params,14,0); /* open_type - file or directory. */
1061 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1063 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1064 smb_action |= EXTENDED_OPLOCK_GRANTED;
1067 SSVAL(params,18,smb_action);
1070 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1072 SIVAL(params,20,inode);
1073 SSVAL(params,24,0); /* Padding. */
1074 if (flags & 8) {
1075 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1076 SIVAL(params, 26, ea_size);
1077 } else {
1078 SIVAL(params, 26, 0);
1081 /* Send the required number of replies */
1082 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1085 /*********************************************************
1086 Routine to check if a given string matches exactly.
1087 as a special case a mask of "." does NOT match. That
1088 is required for correct wildcard semantics
1089 Case can be significant or not.
1090 **********************************************************/
1092 static bool exact_match(connection_struct *conn,
1093 const char *str,
1094 const char *mask)
1096 if (mask[0] == '.' && mask[1] == 0)
1097 return False;
1098 if (dptr_has_wild(conn->dirptr)) {
1099 return False;
1101 if (conn->case_sensitive)
1102 return strcmp(str,mask)==0;
1103 else
1104 return StrCaseCmp(str,mask) == 0;
1107 /****************************************************************************
1108 Return the filetype for UNIX extensions.
1109 ****************************************************************************/
1111 static uint32 unix_filetype(mode_t mode)
1113 if(S_ISREG(mode))
1114 return UNIX_TYPE_FILE;
1115 else if(S_ISDIR(mode))
1116 return UNIX_TYPE_DIR;
1117 #ifdef S_ISLNK
1118 else if(S_ISLNK(mode))
1119 return UNIX_TYPE_SYMLINK;
1120 #endif
1121 #ifdef S_ISCHR
1122 else if(S_ISCHR(mode))
1123 return UNIX_TYPE_CHARDEV;
1124 #endif
1125 #ifdef S_ISBLK
1126 else if(S_ISBLK(mode))
1127 return UNIX_TYPE_BLKDEV;
1128 #endif
1129 #ifdef S_ISFIFO
1130 else if(S_ISFIFO(mode))
1131 return UNIX_TYPE_FIFO;
1132 #endif
1133 #ifdef S_ISSOCK
1134 else if(S_ISSOCK(mode))
1135 return UNIX_TYPE_SOCKET;
1136 #endif
1138 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1139 return UNIX_TYPE_UNKNOWN;
1142 /****************************************************************************
1143 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1144 ****************************************************************************/
1146 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1148 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1149 SMB_STRUCT_STAT *psbuf,
1150 uint32 perms,
1151 enum perm_type ptype,
1152 mode_t *ret_perms)
1154 mode_t ret = 0;
1156 if (perms == SMB_MODE_NO_CHANGE) {
1157 if (!VALID_STAT(*psbuf)) {
1158 return NT_STATUS_INVALID_PARAMETER;
1159 } else {
1160 *ret_perms = psbuf->st_mode;
1161 return NT_STATUS_OK;
1165 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1166 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1167 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1168 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1169 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1170 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1171 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1172 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1173 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1174 #ifdef S_ISVTX
1175 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1176 #endif
1177 #ifdef S_ISGID
1178 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1179 #endif
1180 #ifdef S_ISUID
1181 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1182 #endif
1184 switch (ptype) {
1185 case PERM_NEW_FILE:
1186 /* Apply mode mask */
1187 ret &= lp_create_mask(SNUM(conn));
1188 /* Add in force bits */
1189 ret |= lp_force_create_mode(SNUM(conn));
1190 break;
1191 case PERM_NEW_DIR:
1192 ret &= lp_dir_mask(SNUM(conn));
1193 /* Add in force bits */
1194 ret |= lp_force_dir_mode(SNUM(conn));
1195 break;
1196 case PERM_EXISTING_FILE:
1197 /* Apply mode mask */
1198 ret &= lp_security_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_security_mode(SNUM(conn));
1201 break;
1202 case PERM_EXISTING_DIR:
1203 /* Apply mode mask */
1204 ret &= lp_dir_security_mask(SNUM(conn));
1205 /* Add in force bits */
1206 ret |= lp_force_dir_security_mode(SNUM(conn));
1207 break;
1210 *ret_perms = ret;
1211 return NT_STATUS_OK;
1214 /****************************************************************************
1215 Needed to show the msdfs symlinks as directories. Modifies psbuf
1216 to be a directory if it's a msdfs link.
1217 ****************************************************************************/
1219 static bool check_msdfs_link(connection_struct *conn,
1220 const char *pathname,
1221 SMB_STRUCT_STAT *psbuf)
1223 int saved_errno = errno;
1224 if(lp_host_msdfs() &&
1225 lp_msdfs_root(SNUM(conn)) &&
1226 is_msdfs_link(conn, pathname, psbuf)) {
1228 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1229 "as a directory\n",
1230 pathname));
1231 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1232 errno = saved_errno;
1233 return true;
1235 errno = saved_errno;
1236 return false;
1240 /****************************************************************************
1241 Get a level dependent lanman2 dir entry.
1242 ****************************************************************************/
1244 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1245 connection_struct *conn,
1246 uint16 flags2,
1247 const char *path_mask,
1248 uint32 dirtype,
1249 int info_level,
1250 int requires_resume_key,
1251 bool dont_descend,
1252 bool ask_sharemode,
1253 char **ppdata,
1254 char *base_data,
1255 char *end_data,
1256 int space_remaining,
1257 bool *out_of_space,
1258 bool *got_exact_match,
1259 int *last_entry_off,
1260 struct ea_list *name_list)
1262 const char *dname;
1263 bool found = False;
1264 SMB_STRUCT_STAT sbuf;
1265 const char *mask = NULL;
1266 char *pathreal = NULL;
1267 const char *fname = NULL;
1268 char *p, *q, *pdata = *ppdata;
1269 uint32 reskey=0;
1270 long prev_dirpos=0;
1271 uint32 mode=0;
1272 SMB_OFF_T file_size = 0;
1273 uint64_t allocation_size = 0;
1274 uint32 len;
1275 struct timespec mdate_ts, adate_ts, create_date_ts;
1276 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1277 char *nameptr;
1278 char *last_entry_ptr;
1279 bool was_8_3;
1280 uint32 nt_extmode; /* Used for NT connections instead of mode */
1281 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1282 bool check_mangled_names = lp_manglednames(conn->params);
1283 char mangled_name[13]; /* mangled 8.3 name. */
1285 *out_of_space = False;
1286 *got_exact_match = False;
1288 ZERO_STRUCT(mdate_ts);
1289 ZERO_STRUCT(adate_ts);
1290 ZERO_STRUCT(create_date_ts);
1292 if (!conn->dirptr) {
1293 return(False);
1296 p = strrchr_m(path_mask,'/');
1297 if(p != NULL) {
1298 if(p[1] == '\0') {
1299 mask = talloc_strdup(ctx,"*.*");
1300 } else {
1301 mask = p+1;
1303 } else {
1304 mask = path_mask;
1307 while (!found) {
1308 bool got_match;
1309 bool ms_dfs_link = False;
1311 /* Needed if we run out of space */
1312 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1313 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1316 * Due to bugs in NT client redirectors we are not using
1317 * resume keys any more - set them to zero.
1318 * Check out the related comments in findfirst/findnext.
1319 * JRA.
1322 reskey = 0;
1324 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1325 (long)conn->dirptr,curr_dirpos));
1327 if (!dname) {
1328 return(False);
1332 * fname may get mangled, dname is never mangled.
1333 * Whenever we're accessing the filesystem we use
1334 * pathreal which is composed from dname.
1337 pathreal = NULL;
1338 fname = dname;
1340 /* Mangle fname if it's an illegal name. */
1341 if (mangle_must_mangle(dname,conn->params)) {
1342 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1343 continue; /* Error - couldn't mangle. */
1345 fname = mangled_name;
1348 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1349 got_match = mask_match(fname, mask, conn->case_sensitive);
1352 if(!got_match && check_mangled_names &&
1353 !mangle_is_8_3(fname, False, conn->params)) {
1355 * It turns out that NT matches wildcards against
1356 * both long *and* short names. This may explain some
1357 * of the wildcard wierdness from old DOS clients
1358 * that some people have been seeing.... JRA.
1360 /* Force the mangling into 8.3. */
1361 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1362 continue; /* Error - couldn't mangle. */
1365 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1366 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1370 if (got_match) {
1371 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1373 if (dont_descend && !isdots) {
1374 continue;
1377 if (needslash) {
1378 pathreal = NULL;
1379 pathreal = talloc_asprintf(ctx,
1380 "%s/%s",
1381 conn->dirpath,
1382 dname);
1383 } else {
1384 pathreal = talloc_asprintf(ctx,
1385 "%s%s",
1386 conn->dirpath,
1387 dname);
1390 if (!pathreal) {
1391 return False;
1394 if (INFO_LEVEL_IS_UNIX(info_level)) {
1395 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1396 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1397 pathreal,strerror(errno)));
1398 TALLOC_FREE(pathreal);
1399 continue;
1401 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1402 /* Needed to show the msdfs symlinks as
1403 * directories */
1405 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1406 if (!ms_dfs_link) {
1407 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1408 pathreal,strerror(errno)));
1409 TALLOC_FREE(pathreal);
1410 continue;
1414 if (ms_dfs_link) {
1415 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1416 } else {
1417 mode = dos_mode(conn,pathreal,&sbuf);
1420 if (!dir_check_ftype(conn,mode,dirtype)) {
1421 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1422 TALLOC_FREE(pathreal);
1423 continue;
1426 if (!(mode & aDIR)) {
1427 file_size = get_file_size(sbuf);
1429 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1431 mdate_ts = get_mtimespec(&sbuf);
1432 adate_ts = get_atimespec(&sbuf);
1433 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1435 if (ask_sharemode) {
1436 struct timespec write_time_ts;
1437 struct file_id fileid;
1439 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1440 get_file_infos(fileid, NULL, &write_time_ts);
1441 if (!null_timespec(write_time_ts)) {
1442 mdate_ts = write_time_ts;
1446 if (lp_dos_filetime_resolution(SNUM(conn))) {
1447 dos_filetime_timespec(&create_date_ts);
1448 dos_filetime_timespec(&mdate_ts);
1449 dos_filetime_timespec(&adate_ts);
1452 create_date = convert_timespec_to_time_t(create_date_ts);
1453 mdate = convert_timespec_to_time_t(mdate_ts);
1454 adate = convert_timespec_to_time_t(adate_ts);
1456 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1458 found = True;
1460 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1464 p = pdata;
1465 last_entry_ptr = p;
1467 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1469 switch (info_level) {
1470 case SMB_FIND_INFO_STANDARD:
1471 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1472 if(requires_resume_key) {
1473 SIVAL(p,0,reskey);
1474 p += 4;
1476 srv_put_dos_date2(p,0,create_date);
1477 srv_put_dos_date2(p,4,adate);
1478 srv_put_dos_date2(p,8,mdate);
1479 SIVAL(p,12,(uint32)file_size);
1480 SIVAL(p,16,(uint32)allocation_size);
1481 SSVAL(p,20,mode);
1482 p += 23;
1483 nameptr = p;
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1485 p += ucs2_align(base_data, p, 0);
1487 len = srvstr_push(base_data, flags2, p,
1488 fname, PTR_DIFF(end_data, p),
1489 STR_TERMINATE);
1490 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1491 if (len > 2) {
1492 SCVAL(nameptr, -1, len - 2);
1493 } else {
1494 SCVAL(nameptr, -1, 0);
1496 } else {
1497 if (len > 1) {
1498 SCVAL(nameptr, -1, len - 1);
1499 } else {
1500 SCVAL(nameptr, -1, 0);
1503 p += len;
1504 break;
1506 case SMB_FIND_EA_SIZE:
1507 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1508 if(requires_resume_key) {
1509 SIVAL(p,0,reskey);
1510 p += 4;
1512 srv_put_dos_date2(p,0,create_date);
1513 srv_put_dos_date2(p,4,adate);
1514 srv_put_dos_date2(p,8,mdate);
1515 SIVAL(p,12,(uint32)file_size);
1516 SIVAL(p,16,(uint32)allocation_size);
1517 SSVAL(p,20,mode);
1519 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1520 SIVAL(p,22,ea_size); /* Extended attributes */
1522 p += 27;
1523 nameptr = p - 1;
1524 len = srvstr_push(base_data, flags2,
1525 p, fname, PTR_DIFF(end_data, p),
1526 STR_TERMINATE | STR_NOALIGN);
1527 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1528 if (len > 2) {
1529 len -= 2;
1530 } else {
1531 len = 0;
1533 } else {
1534 if (len > 1) {
1535 len -= 1;
1536 } else {
1537 len = 0;
1540 SCVAL(nameptr,0,len);
1541 p += len;
1542 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1543 break;
1545 case SMB_FIND_EA_LIST:
1547 struct ea_list *file_list = NULL;
1548 size_t ea_len = 0;
1550 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1551 if (!name_list) {
1552 return False;
1554 if(requires_resume_key) {
1555 SIVAL(p,0,reskey);
1556 p += 4;
1558 srv_put_dos_date2(p,0,create_date);
1559 srv_put_dos_date2(p,4,adate);
1560 srv_put_dos_date2(p,8,mdate);
1561 SIVAL(p,12,(uint32)file_size);
1562 SIVAL(p,16,(uint32)allocation_size);
1563 SSVAL(p,20,mode);
1564 p += 22; /* p now points to the EA area. */
1566 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1567 name_list = ea_list_union(name_list, file_list, &ea_len);
1569 /* We need to determine if this entry will fit in the space available. */
1570 /* Max string size is 255 bytes. */
1571 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1572 /* Move the dirptr back to prev_dirpos */
1573 dptr_SeekDir(conn->dirptr, prev_dirpos);
1574 *out_of_space = True;
1575 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1576 return False; /* Not finished - just out of space */
1579 /* Push the ea_data followed by the name. */
1580 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1581 nameptr = p;
1582 len = srvstr_push(base_data, flags2,
1583 p + 1, fname, PTR_DIFF(end_data, p+1),
1584 STR_TERMINATE | STR_NOALIGN);
1585 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1586 if (len > 2) {
1587 len -= 2;
1588 } else {
1589 len = 0;
1591 } else {
1592 if (len > 1) {
1593 len -= 1;
1594 } else {
1595 len = 0;
1598 SCVAL(nameptr,0,len);
1599 p += len + 1;
1600 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1601 break;
1604 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1605 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1606 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1607 p += 4;
1608 SIVAL(p,0,reskey); p += 4;
1609 put_long_date_timespec(p,create_date_ts); p += 8;
1610 put_long_date_timespec(p,adate_ts); p += 8;
1611 put_long_date_timespec(p,mdate_ts); p += 8;
1612 put_long_date_timespec(p,mdate_ts); p += 8;
1613 SOFF_T(p,0,file_size); p += 8;
1614 SOFF_T(p,0,allocation_size); p += 8;
1615 SIVAL(p,0,nt_extmode); p += 4;
1616 q = p; p += 4; /* q is placeholder for name length. */
1618 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1619 SIVAL(p,0,ea_size); /* Extended attributes */
1620 p += 4;
1622 /* Clear the short name buffer. This is
1623 * IMPORTANT as not doing so will trigger
1624 * a Win2k client bug. JRA.
1626 if (!was_8_3 && check_mangled_names) {
1627 if (!name_to_8_3(fname,mangled_name,True,
1628 conn->params)) {
1629 /* Error - mangle failed ! */
1630 memset(mangled_name,'\0',12);
1632 mangled_name[12] = 0;
1633 len = srvstr_push(base_data, flags2,
1634 p+2, mangled_name, 24,
1635 STR_UPPER|STR_UNICODE);
1636 if (len < 24) {
1637 memset(p + 2 + len,'\0',24 - len);
1639 SSVAL(p, 0, len);
1640 } else {
1641 memset(p,'\0',26);
1643 p += 2 + 24;
1644 len = srvstr_push(base_data, flags2, p,
1645 fname, PTR_DIFF(end_data, p),
1646 STR_TERMINATE_ASCII);
1647 SIVAL(q,0,len);
1648 p += len;
1649 SIVAL(p,0,0); /* Ensure any padding is null. */
1650 len = PTR_DIFF(p, pdata);
1651 len = (len + 3) & ~3;
1652 SIVAL(pdata,0,len);
1653 p = pdata + len;
1654 break;
1656 case SMB_FIND_FILE_DIRECTORY_INFO:
1657 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1658 p += 4;
1659 SIVAL(p,0,reskey); p += 4;
1660 put_long_date_timespec(p,create_date_ts); p += 8;
1661 put_long_date_timespec(p,adate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 put_long_date_timespec(p,mdate_ts); p += 8;
1664 SOFF_T(p,0,file_size); p += 8;
1665 SOFF_T(p,0,allocation_size); p += 8;
1666 SIVAL(p,0,nt_extmode); p += 4;
1667 len = srvstr_push(base_data, flags2,
1668 p + 4, fname, PTR_DIFF(end_data, p+4),
1669 STR_TERMINATE_ASCII);
1670 SIVAL(p,0,len);
1671 p += 4 + len;
1672 SIVAL(p,0,0); /* Ensure any padding is null. */
1673 len = PTR_DIFF(p, pdata);
1674 len = (len + 3) & ~3;
1675 SIVAL(pdata,0,len);
1676 p = pdata + len;
1677 break;
1679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1681 p += 4;
1682 SIVAL(p,0,reskey); p += 4;
1683 put_long_date_timespec(p,create_date_ts); p += 8;
1684 put_long_date_timespec(p,adate_ts); p += 8;
1685 put_long_date_timespec(p,mdate_ts); p += 8;
1686 put_long_date_timespec(p,mdate_ts); p += 8;
1687 SOFF_T(p,0,file_size); p += 8;
1688 SOFF_T(p,0,allocation_size); p += 8;
1689 SIVAL(p,0,nt_extmode); p += 4;
1690 q = p; p += 4; /* q is placeholder for name length. */
1692 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1693 SIVAL(p,0,ea_size); /* Extended attributes */
1694 p +=4;
1696 len = srvstr_push(base_data, flags2, p,
1697 fname, PTR_DIFF(end_data, p),
1698 STR_TERMINATE_ASCII);
1699 SIVAL(q, 0, len);
1700 p += len;
1702 SIVAL(p,0,0); /* Ensure any padding is null. */
1703 len = PTR_DIFF(p, pdata);
1704 len = (len + 3) & ~3;
1705 SIVAL(pdata,0,len);
1706 p = pdata + len;
1707 break;
1709 case SMB_FIND_FILE_NAMES_INFO:
1710 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1711 p += 4;
1712 SIVAL(p,0,reskey); p += 4;
1713 p += 4;
1714 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1715 acl on a dir (tridge) */
1716 len = srvstr_push(base_data, flags2, p,
1717 fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE_ASCII);
1719 SIVAL(p, -4, len);
1720 p += len;
1721 SIVAL(p,0,0); /* Ensure any padding is null. */
1722 len = PTR_DIFF(p, pdata);
1723 len = (len + 3) & ~3;
1724 SIVAL(pdata,0,len);
1725 p = pdata + len;
1726 break;
1728 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1729 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1730 p += 4;
1731 SIVAL(p,0,reskey); p += 4;
1732 put_long_date_timespec(p,create_date_ts); p += 8;
1733 put_long_date_timespec(p,adate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 put_long_date_timespec(p,mdate_ts); p += 8;
1736 SOFF_T(p,0,file_size); p += 8;
1737 SOFF_T(p,0,allocation_size); p += 8;
1738 SIVAL(p,0,nt_extmode); p += 4;
1739 q = p; p += 4; /* q is placeholder for name length. */
1741 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1742 SIVAL(p,0,ea_size); /* Extended attributes */
1743 p +=4;
1745 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1746 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1747 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1748 len = srvstr_push(base_data, flags2, p,
1749 fname, PTR_DIFF(end_data, p),
1750 STR_TERMINATE_ASCII);
1751 SIVAL(q, 0, len);
1752 p += len;
1753 SIVAL(p,0,0); /* Ensure any padding is null. */
1754 len = PTR_DIFF(p, pdata);
1755 len = (len + 3) & ~3;
1756 SIVAL(pdata,0,len);
1757 p = pdata + len;
1758 break;
1760 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1761 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1762 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1763 p += 4;
1764 SIVAL(p,0,reskey); p += 4;
1765 put_long_date_timespec(p,create_date_ts); p += 8;
1766 put_long_date_timespec(p,adate_ts); p += 8;
1767 put_long_date_timespec(p,mdate_ts); p += 8;
1768 put_long_date_timespec(p,mdate_ts); p += 8;
1769 SOFF_T(p,0,file_size); p += 8;
1770 SOFF_T(p,0,allocation_size); p += 8;
1771 SIVAL(p,0,nt_extmode); p += 4;
1772 q = p; p += 4; /* q is placeholder for name length */
1774 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1775 SIVAL(p,0,ea_size); /* Extended attributes */
1776 p +=4;
1778 /* Clear the short name buffer. This is
1779 * IMPORTANT as not doing so will trigger
1780 * a Win2k client bug. JRA.
1782 if (!was_8_3 && check_mangled_names) {
1783 if (!name_to_8_3(fname,mangled_name,True,
1784 conn->params)) {
1785 /* Error - mangle failed ! */
1786 memset(mangled_name,'\0',12);
1788 mangled_name[12] = 0;
1789 len = srvstr_push(base_data, flags2,
1790 p+2, mangled_name, 24,
1791 STR_UPPER|STR_UNICODE);
1792 SSVAL(p, 0, len);
1793 if (len < 24) {
1794 memset(p + 2 + len,'\0',24 - len);
1796 SSVAL(p, 0, len);
1797 } else {
1798 memset(p,'\0',26);
1800 p += 26;
1801 SSVAL(p,0,0); p += 2; /* Reserved ? */
1802 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1803 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1804 len = srvstr_push(base_data, flags2, p,
1805 fname, PTR_DIFF(end_data, p),
1806 STR_TERMINATE_ASCII);
1807 SIVAL(q,0,len);
1808 p += len;
1809 SIVAL(p,0,0); /* Ensure any padding is null. */
1810 len = PTR_DIFF(p, pdata);
1811 len = (len + 3) & ~3;
1812 SIVAL(pdata,0,len);
1813 p = pdata + len;
1814 break;
1816 /* CIFS UNIX Extension. */
1818 case SMB_FIND_FILE_UNIX:
1819 case SMB_FIND_FILE_UNIX_INFO2:
1820 p+= 4;
1821 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1823 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1825 if (info_level == SMB_FIND_FILE_UNIX) {
1826 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1827 p = store_file_unix_basic(conn, p,
1828 NULL, &sbuf);
1829 len = srvstr_push(base_data, flags2, p,
1830 fname, PTR_DIFF(end_data, p),
1831 STR_TERMINATE);
1832 } else {
1833 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1834 p = store_file_unix_basic_info2(conn, p,
1835 NULL, &sbuf);
1836 nameptr = p;
1837 p += 4;
1838 len = srvstr_push(base_data, flags2, p, fname,
1839 PTR_DIFF(end_data, p), 0);
1840 SIVAL(nameptr, 0, len);
1843 p += len;
1844 SIVAL(p,0,0); /* Ensure any padding is null. */
1846 len = PTR_DIFF(p, pdata);
1847 len = (len + 3) & ~3;
1848 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1849 p = pdata + len;
1850 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1852 break;
1854 default:
1855 return(False);
1859 if (PTR_DIFF(p,pdata) > space_remaining) {
1860 /* Move the dirptr back to prev_dirpos */
1861 dptr_SeekDir(conn->dirptr, prev_dirpos);
1862 *out_of_space = True;
1863 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1864 return False; /* Not finished - just out of space */
1867 /* Setup the last entry pointer, as an offset from base_data */
1868 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1869 /* Advance the data pointer to the next slot */
1870 *ppdata = p;
1872 return(found);
1875 /****************************************************************************
1876 Reply to a TRANS2_FINDFIRST.
1877 ****************************************************************************/
1879 static void call_trans2findfirst(connection_struct *conn,
1880 struct smb_request *req,
1881 char **pparams, int total_params,
1882 char **ppdata, int total_data,
1883 unsigned int max_data_bytes)
1885 /* We must be careful here that we don't return more than the
1886 allowed number of data bytes. If this means returning fewer than
1887 maxentries then so be it. We assume that the redirector has
1888 enough room for the fixed number of parameter bytes it has
1889 requested. */
1890 char *params = *pparams;
1891 char *pdata = *ppdata;
1892 char *data_end;
1893 uint32 dirtype;
1894 int maxentries;
1895 uint16 findfirst_flags;
1896 bool close_after_first;
1897 bool close_if_end;
1898 bool requires_resume_key;
1899 int info_level;
1900 char *directory = NULL;
1901 char *mask = NULL;
1902 char *p;
1903 int last_entry_off=0;
1904 int dptr_num = -1;
1905 int numentries = 0;
1906 int i;
1907 bool finished = False;
1908 bool dont_descend = False;
1909 bool out_of_space = False;
1910 int space_remaining;
1911 bool mask_contains_wcard = False;
1912 SMB_STRUCT_STAT sbuf;
1913 struct ea_list *ea_list = NULL;
1914 NTSTATUS ntstatus = NT_STATUS_OK;
1915 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1916 TALLOC_CTX *ctx = talloc_tos();
1918 if (total_params < 13) {
1919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1920 return;
1923 dirtype = SVAL(params,0);
1924 maxentries = SVAL(params,2);
1925 findfirst_flags = SVAL(params,4);
1926 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1927 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1928 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1929 info_level = SVAL(params,6);
1931 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1932 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1933 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1934 info_level, max_data_bytes));
1936 if (!maxentries) {
1937 /* W2K3 seems to treat zero as 1. */
1938 maxentries = 1;
1941 switch (info_level) {
1942 case SMB_FIND_INFO_STANDARD:
1943 case SMB_FIND_EA_SIZE:
1944 case SMB_FIND_EA_LIST:
1945 case SMB_FIND_FILE_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_NAMES_INFO:
1948 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1949 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1950 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1951 break;
1952 case SMB_FIND_FILE_UNIX:
1953 case SMB_FIND_FILE_UNIX_INFO2:
1954 /* Always use filesystem for UNIX mtime query. */
1955 ask_sharemode = false;
1956 if (!lp_unix_extensions()) {
1957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1958 return;
1960 break;
1961 default:
1962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1963 return;
1966 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1967 params+12, total_params - 12,
1968 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 reply_nterror(req, ntstatus);
1971 return;
1974 ntstatus = resolve_dfspath_wcard(ctx, conn,
1975 req->flags2 & FLAGS2_DFS_PATHNAMES,
1976 directory,
1977 &directory,
1978 &mask_contains_wcard);
1979 if (!NT_STATUS_IS_OK(ntstatus)) {
1980 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1981 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1982 ERRSRV, ERRbadpath);
1983 return;
1985 reply_nterror(req, ntstatus);
1986 return;
1989 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1990 if (!NT_STATUS_IS_OK(ntstatus)) {
1991 reply_nterror(req, ntstatus);
1992 return;
1995 ntstatus = check_name(conn, directory);
1996 if (!NT_STATUS_IS_OK(ntstatus)) {
1997 reply_nterror(req, ntstatus);
1998 return;
2001 p = strrchr_m(directory,'/');
2002 if(p == NULL) {
2003 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2004 if((directory[0] == '.') && (directory[1] == '\0')) {
2005 mask = talloc_strdup(ctx,"*");
2006 if (!mask) {
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 return;
2010 mask_contains_wcard = True;
2012 directory = talloc_strdup(talloc_tos(), "./");
2013 if (!directory) {
2014 reply_nterror(req, NT_STATUS_NO_MEMORY);
2015 return;
2017 } else {
2018 *p = 0;
2021 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2023 if (info_level == SMB_FIND_EA_LIST) {
2024 uint32 ea_size;
2026 if (total_data < 4) {
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 return;
2031 ea_size = IVAL(pdata,0);
2032 if (ea_size != total_data) {
2033 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2034 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2036 return;
2039 if (!lp_ea_support(SNUM(conn))) {
2040 reply_doserror(req, ERRDOS, ERReasnotsupported);
2041 return;
2044 /* Pull out the list of names. */
2045 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2046 if (!ea_list) {
2047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2048 return;
2052 *ppdata = (char *)SMB_REALLOC(
2053 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2054 if(*ppdata == NULL ) {
2055 reply_nterror(req, NT_STATUS_NO_MEMORY);
2056 return;
2058 pdata = *ppdata;
2059 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2061 /* Realloc the params space */
2062 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2063 if (*pparams == NULL) {
2064 reply_nterror(req, NT_STATUS_NO_MEMORY);
2065 return;
2067 params = *pparams;
2069 /* Save the wildcard match and attribs we are using on this directory -
2070 needed as lanman2 assumes these are being saved between calls */
2072 ntstatus = dptr_create(conn,
2073 directory,
2074 False,
2075 True,
2076 req->smbpid,
2077 mask,
2078 mask_contains_wcard,
2079 dirtype,
2080 &conn->dirptr);
2082 if (!NT_STATUS_IS_OK(ntstatus)) {
2083 reply_nterror(req, ntstatus);
2084 return;
2087 dptr_num = dptr_dnum(conn->dirptr);
2088 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2090 /* We don't need to check for VOL here as this is returned by
2091 a different TRANS2 call. */
2093 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2094 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2095 dont_descend = True;
2097 p = pdata;
2098 space_remaining = max_data_bytes;
2099 out_of_space = False;
2101 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2102 bool got_exact_match = False;
2104 /* this is a heuristic to avoid seeking the dirptr except when
2105 absolutely necessary. It allows for a filename of about 40 chars */
2106 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2107 out_of_space = True;
2108 finished = False;
2109 } else {
2110 finished = !get_lanman2_dir_entry(ctx,
2111 conn,
2112 req->flags2,
2113 mask,dirtype,info_level,
2114 requires_resume_key,dont_descend,
2115 ask_sharemode,
2116 &p,pdata,data_end,
2117 space_remaining, &out_of_space,
2118 &got_exact_match,
2119 &last_entry_off, ea_list);
2122 if (finished && out_of_space)
2123 finished = False;
2125 if (!finished && !out_of_space)
2126 numentries++;
2129 * As an optimisation if we know we aren't looking
2130 * for a wildcard name (ie. the name matches the wildcard exactly)
2131 * then we can finish on any (first) match.
2132 * This speeds up large directory searches. JRA.
2135 if(got_exact_match)
2136 finished = True;
2138 /* Ensure space_remaining never goes -ve. */
2139 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2140 space_remaining = 0;
2141 out_of_space = true;
2142 } else {
2143 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2147 /* Check if we can close the dirptr */
2148 if(close_after_first || (finished && close_if_end)) {
2149 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2150 dptr_close(&dptr_num);
2154 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2155 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2156 * the protocol level is less than NT1. Tested with smbclient. JRA.
2157 * This should fix the OS/2 client bug #2335.
2160 if(numentries == 0) {
2161 dptr_close(&dptr_num);
2162 if (Protocol < PROTOCOL_NT1) {
2163 reply_doserror(req, ERRDOS, ERRnofiles);
2164 return;
2165 } else {
2166 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2167 ERRDOS, ERRbadfile);
2168 return;
2172 /* At this point pdata points to numentries directory entries. */
2174 /* Set up the return parameter block */
2175 SSVAL(params,0,dptr_num);
2176 SSVAL(params,2,numentries);
2177 SSVAL(params,4,finished);
2178 SSVAL(params,6,0); /* Never an EA error */
2179 SSVAL(params,8,last_entry_off);
2181 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2182 max_data_bytes);
2184 if ((! *directory) && dptr_path(dptr_num)) {
2185 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2186 if (!directory) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2192 smb_fn_name(req->cmd),
2193 mask, directory, dirtype, numentries ) );
2196 * Force a name mangle here to ensure that the
2197 * mask as an 8.3 name is top of the mangled cache.
2198 * The reasons for this are subtle. Don't remove
2199 * this code unless you know what you are doing
2200 * (see PR#13758). JRA.
2203 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2204 char mangled_name[13];
2205 name_to_8_3(mask, mangled_name, True, conn->params);
2208 return;
2211 /****************************************************************************
2212 Reply to a TRANS2_FINDNEXT.
2213 ****************************************************************************/
2215 static void call_trans2findnext(connection_struct *conn,
2216 struct smb_request *req,
2217 char **pparams, int total_params,
2218 char **ppdata, int total_data,
2219 unsigned int max_data_bytes)
2221 /* We must be careful here that we don't return more than the
2222 allowed number of data bytes. If this means returning fewer than
2223 maxentries then so be it. We assume that the redirector has
2224 enough room for the fixed number of parameter bytes it has
2225 requested. */
2226 char *params = *pparams;
2227 char *pdata = *ppdata;
2228 char *data_end;
2229 int dptr_num;
2230 int maxentries;
2231 uint16 info_level;
2232 uint32 resume_key;
2233 uint16 findnext_flags;
2234 bool close_after_request;
2235 bool close_if_end;
2236 bool requires_resume_key;
2237 bool continue_bit;
2238 bool mask_contains_wcard = False;
2239 char *resume_name = NULL;
2240 const char *mask = NULL;
2241 const char *directory = NULL;
2242 char *p = NULL;
2243 uint16 dirtype;
2244 int numentries = 0;
2245 int i, last_entry_off=0;
2246 bool finished = False;
2247 bool dont_descend = False;
2248 bool out_of_space = False;
2249 int space_remaining;
2250 struct ea_list *ea_list = NULL;
2251 NTSTATUS ntstatus = NT_STATUS_OK;
2252 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2253 TALLOC_CTX *ctx = talloc_tos();
2255 if (total_params < 13) {
2256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2257 return;
2260 dptr_num = SVAL(params,0);
2261 maxentries = SVAL(params,2);
2262 info_level = SVAL(params,4);
2263 resume_key = IVAL(params,6);
2264 findnext_flags = SVAL(params,10);
2265 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2266 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2267 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2268 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2270 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2271 params+12,
2272 total_params - 12, STR_TERMINATE, &ntstatus,
2273 &mask_contains_wcard);
2274 if (!NT_STATUS_IS_OK(ntstatus)) {
2275 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2276 complain (it thinks we're asking for the directory above the shared
2277 path or an invalid name). Catch this as the resume name is only compared, never used in
2278 a file access. JRA. */
2279 srvstr_pull_talloc(ctx, params, req->flags2,
2280 &resume_name, params+12,
2281 total_params - 12,
2282 STR_TERMINATE);
2284 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2285 reply_nterror(req, ntstatus);
2286 return;
2290 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2291 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2292 resume_key = %d resume name = %s continue=%d level = %d\n",
2293 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2294 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2296 if (!maxentries) {
2297 /* W2K3 seems to treat zero as 1. */
2298 maxentries = 1;
2301 switch (info_level) {
2302 case SMB_FIND_INFO_STANDARD:
2303 case SMB_FIND_EA_SIZE:
2304 case SMB_FIND_EA_LIST:
2305 case SMB_FIND_FILE_DIRECTORY_INFO:
2306 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_NAMES_INFO:
2308 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2309 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2310 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2311 break;
2312 case SMB_FIND_FILE_UNIX:
2313 case SMB_FIND_FILE_UNIX_INFO2:
2314 /* Always use filesystem for UNIX mtime query. */
2315 ask_sharemode = false;
2316 if (!lp_unix_extensions()) {
2317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 return;
2320 break;
2321 default:
2322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2323 return;
2326 if (info_level == SMB_FIND_EA_LIST) {
2327 uint32 ea_size;
2329 if (total_data < 4) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 return;
2334 ea_size = IVAL(pdata,0);
2335 if (ea_size != total_data) {
2336 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2337 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2339 return;
2342 if (!lp_ea_support(SNUM(conn))) {
2343 reply_doserror(req, ERRDOS, ERReasnotsupported);
2344 return;
2347 /* Pull out the list of names. */
2348 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2349 if (!ea_list) {
2350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2351 return;
2355 *ppdata = (char *)SMB_REALLOC(
2356 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2357 if(*ppdata == NULL) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 return;
2362 pdata = *ppdata;
2363 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2365 /* Realloc the params space */
2366 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2367 if(*pparams == NULL ) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 return;
2372 params = *pparams;
2374 /* Check that the dptr is valid */
2375 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2376 reply_doserror(req, ERRDOS, ERRnofiles);
2377 return;
2380 string_set(&conn->dirpath,dptr_path(dptr_num));
2382 /* Get the wildcard mask from the dptr */
2383 if((p = dptr_wcard(dptr_num))== NULL) {
2384 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2385 reply_doserror(req, ERRDOS, ERRnofiles);
2386 return;
2389 mask = p;
2390 directory = conn->dirpath;
2392 /* Get the attr mask from the dptr */
2393 dirtype = dptr_attr(dptr_num);
2395 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2396 dptr_num, mask, dirtype,
2397 (long)conn->dirptr,
2398 dptr_TellDir(conn->dirptr)));
2400 /* We don't need to check for VOL here as this is returned by
2401 a different TRANS2 call. */
2403 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2404 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2405 dont_descend = True;
2407 p = pdata;
2408 space_remaining = max_data_bytes;
2409 out_of_space = False;
2412 * Seek to the correct position. We no longer use the resume key but
2413 * depend on the last file name instead.
2416 if(*resume_name && !continue_bit) {
2417 SMB_STRUCT_STAT st;
2419 long current_pos = 0;
2421 * Remember, name_to_8_3 is called by
2422 * get_lanman2_dir_entry(), so the resume name
2423 * could be mangled. Ensure we check the unmangled name.
2426 if (mangle_is_mangled(resume_name, conn->params)) {
2427 char *new_resume_name = NULL;
2428 mangle_lookup_name_from_8_3(ctx,
2429 resume_name,
2430 &new_resume_name,
2431 conn->params);
2432 if (new_resume_name) {
2433 resume_name = new_resume_name;
2438 * Fix for NT redirector problem triggered by resume key indexes
2439 * changing between directory scans. We now return a resume key of 0
2440 * and instead look for the filename to continue from (also given
2441 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2442 * findfirst/findnext (as is usual) then the directory pointer
2443 * should already be at the correct place.
2446 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2447 } /* end if resume_name && !continue_bit */
2449 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2450 bool got_exact_match = False;
2452 /* this is a heuristic to avoid seeking the dirptr except when
2453 absolutely necessary. It allows for a filename of about 40 chars */
2454 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2455 out_of_space = True;
2456 finished = False;
2457 } else {
2458 finished = !get_lanman2_dir_entry(ctx,
2459 conn,
2460 req->flags2,
2461 mask,dirtype,info_level,
2462 requires_resume_key,dont_descend,
2463 ask_sharemode,
2464 &p,pdata,data_end,
2465 space_remaining, &out_of_space,
2466 &got_exact_match,
2467 &last_entry_off, ea_list);
2470 if (finished && out_of_space)
2471 finished = False;
2473 if (!finished && !out_of_space)
2474 numentries++;
2477 * As an optimisation if we know we aren't looking
2478 * for a wildcard name (ie. the name matches the wildcard exactly)
2479 * then we can finish on any (first) match.
2480 * This speeds up large directory searches. JRA.
2483 if(got_exact_match)
2484 finished = True;
2486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2489 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2490 smb_fn_name(req->cmd),
2491 mask, directory, dirtype, numentries ) );
2493 /* Check if we can close the dirptr */
2494 if(close_after_request || (finished && close_if_end)) {
2495 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2496 dptr_close(&dptr_num); /* This frees up the saved mask */
2499 /* Set up the return parameter block */
2500 SSVAL(params,0,numentries);
2501 SSVAL(params,2,finished);
2502 SSVAL(params,4,0); /* Never an EA error */
2503 SSVAL(params,6,last_entry_off);
2505 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2506 max_data_bytes);
2508 return;
2511 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2513 E_md4hash(lp_servicename(SNUM(conn)),objid);
2514 return objid;
2517 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2519 SMB_ASSERT(extended_info != NULL);
2521 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2522 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2523 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2524 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2525 #ifdef SAMBA_VERSION_REVISION
2526 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2527 #endif
2528 extended_info->samba_subversion = 0;
2529 #ifdef SAMBA_VERSION_RC_RELEASE
2530 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2531 #else
2532 #ifdef SAMBA_VERSION_PRE_RELEASE
2533 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2534 #endif
2535 #endif
2536 #ifdef SAMBA_VERSION_VENDOR_PATCH
2537 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2538 #endif
2539 extended_info->samba_gitcommitdate = 0;
2540 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2541 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2542 #endif
2544 memset(extended_info->samba_version_string, 0,
2545 sizeof(extended_info->samba_version_string));
2547 snprintf (extended_info->samba_version_string,
2548 sizeof(extended_info->samba_version_string),
2549 "%s", samba_version_string());
2552 /****************************************************************************
2553 Reply to a TRANS2_QFSINFO (query filesystem info).
2554 ****************************************************************************/
2556 static void call_trans2qfsinfo(connection_struct *conn,
2557 struct smb_request *req,
2558 char **pparams, int total_params,
2559 char **ppdata, int total_data,
2560 unsigned int max_data_bytes)
2562 char *pdata, *end_data;
2563 char *params = *pparams;
2564 uint16 info_level;
2565 int data_len, len;
2566 SMB_STRUCT_STAT st;
2567 const char *vname = volume_label(SNUM(conn));
2568 int snum = SNUM(conn);
2569 char *fstype = lp_fstype(SNUM(conn));
2570 uint32 additional_flags = 0;
2572 if (total_params < 2) {
2573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2574 return;
2577 info_level = SVAL(params,0);
2579 if (IS_IPC(conn)) {
2580 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2581 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2582 "info level (0x%x) on IPC$.\n",
2583 (unsigned int)info_level));
2584 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2585 return;
2589 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2590 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2591 DEBUG(0,("call_trans2qfsinfo: encryption required "
2592 "and info level 0x%x sent.\n",
2593 (unsigned int)info_level));
2594 exit_server_cleanly("encryption required "
2595 "on connection");
2596 return;
2600 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2602 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2603 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2604 reply_doserror(req, ERRSRV, ERRinvdevice);
2605 return;
2608 *ppdata = (char *)SMB_REALLOC(
2609 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2610 if (*ppdata == NULL ) {
2611 reply_nterror(req, NT_STATUS_NO_MEMORY);
2612 return;
2615 pdata = *ppdata;
2616 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2617 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2619 switch (info_level) {
2620 case SMB_INFO_ALLOCATION:
2622 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2623 data_len = 18;
2624 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2625 reply_unixerror(req, ERRHRD, ERRgeneral);
2626 return;
2629 block_size = lp_block_size(snum);
2630 if (bsize < block_size) {
2631 uint64_t factor = block_size/bsize;
2632 bsize = block_size;
2633 dsize /= factor;
2634 dfree /= factor;
2636 if (bsize > block_size) {
2637 uint64_t factor = bsize/block_size;
2638 bsize = block_size;
2639 dsize *= factor;
2640 dfree *= factor;
2642 bytes_per_sector = 512;
2643 sectors_per_unit = bsize/bytes_per_sector;
2645 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2647 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2649 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2650 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2651 SIVAL(pdata,l1_cUnit,dsize);
2652 SIVAL(pdata,l1_cUnitAvail,dfree);
2653 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2654 break;
2657 case SMB_INFO_VOLUME:
2658 /* Return volume name */
2660 * Add volume serial number - hash of a combination of
2661 * the called hostname and the service name.
2663 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2665 * Win2k3 and previous mess this up by sending a name length
2666 * one byte short. I believe only older clients (OS/2 Win9x) use
2667 * this call so try fixing this by adding a terminating null to
2668 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2670 len = srvstr_push(
2671 pdata, req->flags2,
2672 pdata+l2_vol_szVolLabel, vname,
2673 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2674 STR_NOALIGN|STR_TERMINATE);
2675 SCVAL(pdata,l2_vol_cch,len);
2676 data_len = l2_vol_szVolLabel + len;
2677 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2678 (unsigned)st.st_ctime, len, vname));
2679 break;
2681 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2682 case SMB_FS_ATTRIBUTE_INFORMATION:
2684 additional_flags = 0;
2685 #if defined(HAVE_SYS_QUOTAS)
2686 additional_flags |= FILE_VOLUME_QUOTAS;
2687 #endif
2689 if(lp_nt_acl_support(SNUM(conn))) {
2690 additional_flags |= FILE_PERSISTENT_ACLS;
2693 /* Capabilities are filled in at connection time through STATVFS call */
2694 additional_flags |= conn->fs_capabilities;
2696 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2697 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2698 additional_flags); /* FS ATTRIBUTES */
2700 SIVAL(pdata,4,255); /* Max filename component length */
2701 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2702 and will think we can't do long filenames */
2703 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2704 PTR_DIFF(end_data, pdata+12),
2705 STR_UNICODE);
2706 SIVAL(pdata,8,len);
2707 data_len = 12 + len;
2708 break;
2710 case SMB_QUERY_FS_LABEL_INFO:
2711 case SMB_FS_LABEL_INFORMATION:
2712 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2713 PTR_DIFF(end_data, pdata+4), 0);
2714 data_len = 4 + len;
2715 SIVAL(pdata,0,len);
2716 break;
2718 case SMB_QUERY_FS_VOLUME_INFO:
2719 case SMB_FS_VOLUME_INFORMATION:
2722 * Add volume serial number - hash of a combination of
2723 * the called hostname and the service name.
2725 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2726 (str_checksum(get_local_machine_name())<<16));
2728 /* Max label len is 32 characters. */
2729 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2730 PTR_DIFF(end_data, pdata+18),
2731 STR_UNICODE);
2732 SIVAL(pdata,12,len);
2733 data_len = 18+len;
2735 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2736 (int)strlen(vname),vname, lp_servicename(snum)));
2737 break;
2739 case SMB_QUERY_FS_SIZE_INFO:
2740 case SMB_FS_SIZE_INFORMATION:
2742 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2743 data_len = 24;
2744 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2745 reply_unixerror(req, ERRHRD, ERRgeneral);
2746 return;
2748 block_size = lp_block_size(snum);
2749 if (bsize < block_size) {
2750 uint64_t factor = block_size/bsize;
2751 bsize = block_size;
2752 dsize /= factor;
2753 dfree /= factor;
2755 if (bsize > block_size) {
2756 uint64_t factor = bsize/block_size;
2757 bsize = block_size;
2758 dsize *= factor;
2759 dfree *= factor;
2761 bytes_per_sector = 512;
2762 sectors_per_unit = bsize/bytes_per_sector;
2763 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2764 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2765 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2766 SBIG_UINT(pdata,0,dsize);
2767 SBIG_UINT(pdata,8,dfree);
2768 SIVAL(pdata,16,sectors_per_unit);
2769 SIVAL(pdata,20,bytes_per_sector);
2770 break;
2773 case SMB_FS_FULL_SIZE_INFORMATION:
2775 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2776 data_len = 32;
2777 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2778 reply_unixerror(req, ERRHRD, ERRgeneral);
2779 return;
2781 block_size = lp_block_size(snum);
2782 if (bsize < block_size) {
2783 uint64_t factor = block_size/bsize;
2784 bsize = block_size;
2785 dsize /= factor;
2786 dfree /= factor;
2788 if (bsize > block_size) {
2789 uint64_t factor = bsize/block_size;
2790 bsize = block_size;
2791 dsize *= factor;
2792 dfree *= factor;
2794 bytes_per_sector = 512;
2795 sectors_per_unit = bsize/bytes_per_sector;
2796 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2797 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2798 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2799 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2800 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2801 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2802 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2803 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2804 break;
2807 case SMB_QUERY_FS_DEVICE_INFO:
2808 case SMB_FS_DEVICE_INFORMATION:
2809 data_len = 8;
2810 SIVAL(pdata,0,0); /* dev type */
2811 SIVAL(pdata,4,0); /* characteristics */
2812 break;
2814 #ifdef HAVE_SYS_QUOTAS
2815 case SMB_FS_QUOTA_INFORMATION:
2817 * what we have to send --metze:
2819 * Unknown1: 24 NULL bytes
2820 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2821 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2822 * Quota Flags: 2 byte :
2823 * Unknown3: 6 NULL bytes
2825 * 48 bytes total
2827 * details for Quota Flags:
2829 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2830 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2831 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2832 * 0x0001 Enable Quotas: enable quota for this fs
2836 /* we need to fake up a fsp here,
2837 * because its not send in this call
2839 files_struct fsp;
2840 SMB_NTQUOTA_STRUCT quotas;
2842 ZERO_STRUCT(fsp);
2843 ZERO_STRUCT(quotas);
2845 fsp.conn = conn;
2846 fsp.fnum = -1;
2848 /* access check */
2849 if (conn->server_info->utok.uid != 0) {
2850 DEBUG(0,("set_user_quota: access_denied "
2851 "service [%s] user [%s]\n",
2852 lp_servicename(SNUM(conn)),
2853 conn->server_info->unix_name));
2854 reply_doserror(req, ERRDOS, ERRnoaccess);
2855 return;
2858 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2859 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2860 reply_doserror(req, ERRSRV, ERRerror);
2861 return;
2864 data_len = 48;
2866 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2868 /* Unknown1 24 NULL bytes*/
2869 SBIG_UINT(pdata,0,(uint64_t)0);
2870 SBIG_UINT(pdata,8,(uint64_t)0);
2871 SBIG_UINT(pdata,16,(uint64_t)0);
2873 /* Default Soft Quota 8 bytes */
2874 SBIG_UINT(pdata,24,quotas.softlim);
2876 /* Default Hard Quota 8 bytes */
2877 SBIG_UINT(pdata,32,quotas.hardlim);
2879 /* Quota flag 2 bytes */
2880 SSVAL(pdata,40,quotas.qflags);
2882 /* Unknown3 6 NULL bytes */
2883 SSVAL(pdata,42,0);
2884 SIVAL(pdata,44,0);
2886 break;
2888 #endif /* HAVE_SYS_QUOTAS */
2889 case SMB_FS_OBJECTID_INFORMATION:
2891 unsigned char objid[16];
2892 struct smb_extended_info extended_info;
2893 memcpy(pdata,create_volume_objectid(conn, objid),16);
2894 samba_extended_info_version (&extended_info);
2895 SIVAL(pdata,16,extended_info.samba_magic);
2896 SIVAL(pdata,20,extended_info.samba_version);
2897 SIVAL(pdata,24,extended_info.samba_subversion);
2898 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2899 memcpy(pdata+36,extended_info.samba_version_string,28);
2900 data_len = 64;
2901 break;
2905 * Query the version and capabilities of the CIFS UNIX extensions
2906 * in use.
2909 case SMB_QUERY_CIFS_UNIX_INFO:
2911 bool large_write = lp_min_receive_file_size() &&
2912 !srv_is_signing_active();
2913 bool large_read = !srv_is_signing_active();
2914 int encrypt_caps = 0;
2916 if (!lp_unix_extensions()) {
2917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2918 return;
2921 switch (conn->encrypt_level) {
2922 case 0:
2923 encrypt_caps = 0;
2924 break;
2925 case 1:
2926 case Auto:
2927 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2928 break;
2929 case Required:
2930 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2931 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2932 large_write = false;
2933 large_read = false;
2934 break;
2937 data_len = 12;
2938 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2939 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2941 /* We have POSIX ACLs, pathname, encryption,
2942 * large read/write, and locking capability. */
2944 SBIG_UINT(pdata,4,((uint64_t)(
2945 CIFS_UNIX_POSIX_ACLS_CAP|
2946 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2947 CIFS_UNIX_FCNTL_LOCKS_CAP|
2948 CIFS_UNIX_EXTATTR_CAP|
2949 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2950 encrypt_caps|
2951 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2952 (large_write ?
2953 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2954 break;
2957 case SMB_QUERY_POSIX_FS_INFO:
2959 int rc;
2960 vfs_statvfs_struct svfs;
2962 if (!lp_unix_extensions()) {
2963 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2964 return;
2967 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2969 if (!rc) {
2970 data_len = 56;
2971 SIVAL(pdata,0,svfs.OptimalTransferSize);
2972 SIVAL(pdata,4,svfs.BlockSize);
2973 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2974 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2975 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2976 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2977 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2978 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2979 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2980 #ifdef EOPNOTSUPP
2981 } else if (rc == EOPNOTSUPP) {
2982 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2983 return;
2984 #endif /* EOPNOTSUPP */
2985 } else {
2986 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2987 reply_doserror(req, ERRSRV, ERRerror);
2988 return;
2990 break;
2993 case SMB_QUERY_POSIX_WHOAMI:
2995 uint32_t flags = 0;
2996 uint32_t sid_bytes;
2997 int i;
2999 if (!lp_unix_extensions()) {
3000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3001 return;
3004 if (max_data_bytes < 40) {
3005 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3006 return;
3009 /* We ARE guest if global_sid_Builtin_Guests is
3010 * in our list of SIDs.
3012 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3013 conn->server_info->ptok)) {
3014 flags |= SMB_WHOAMI_GUEST;
3017 /* We are NOT guest if global_sid_Authenticated_Users
3018 * is in our list of SIDs.
3020 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3021 conn->server_info->ptok)) {
3022 flags &= ~SMB_WHOAMI_GUEST;
3025 /* NOTE: 8 bytes for UID/GID, irrespective of native
3026 * platform size. This matches
3027 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3029 data_len = 4 /* flags */
3030 + 4 /* flag mask */
3031 + 8 /* uid */
3032 + 8 /* gid */
3033 + 4 /* ngroups */
3034 + 4 /* num_sids */
3035 + 4 /* SID bytes */
3036 + 4 /* pad/reserved */
3037 + (conn->server_info->utok.ngroups * 8)
3038 /* groups list */
3039 + (conn->server_info->ptok->num_sids *
3040 SID_MAX_SIZE)
3041 /* SID list */;
3043 SIVAL(pdata, 0, flags);
3044 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3045 SBIG_UINT(pdata, 8,
3046 (uint64_t)conn->server_info->utok.uid);
3047 SBIG_UINT(pdata, 16,
3048 (uint64_t)conn->server_info->utok.gid);
3051 if (data_len >= max_data_bytes) {
3052 /* Potential overflow, skip the GIDs and SIDs. */
3054 SIVAL(pdata, 24, 0); /* num_groups */
3055 SIVAL(pdata, 28, 0); /* num_sids */
3056 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3057 SIVAL(pdata, 36, 0); /* reserved */
3059 data_len = 40;
3060 break;
3063 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3064 SIVAL(pdata, 28, conn->server_info->num_sids);
3066 /* We walk the SID list twice, but this call is fairly
3067 * infrequent, and I don't expect that it's performance
3068 * sensitive -- jpeach
3070 for (i = 0, sid_bytes = 0;
3071 i < conn->server_info->ptok->num_sids; ++i) {
3072 sid_bytes += ndr_size_dom_sid(
3073 &conn->server_info->ptok->user_sids[i],
3074 NULL,
3078 /* SID list byte count */
3079 SIVAL(pdata, 32, sid_bytes);
3081 /* 4 bytes pad/reserved - must be zero */
3082 SIVAL(pdata, 36, 0);
3083 data_len = 40;
3085 /* GID list */
3086 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3087 SBIG_UINT(pdata, data_len,
3088 (uint64_t)conn->server_info->utok.groups[i]);
3089 data_len += 8;
3092 /* SID list */
3093 for (i = 0;
3094 i < conn->server_info->ptok->num_sids; ++i) {
3095 int sid_len = ndr_size_dom_sid(
3096 &conn->server_info->ptok->user_sids[i],
3097 NULL,
3100 sid_linearize(pdata + data_len, sid_len,
3101 &conn->server_info->ptok->user_sids[i]);
3102 data_len += sid_len;
3105 break;
3108 case SMB_MAC_QUERY_FS_INFO:
3110 * Thursby MAC extension... ONLY on NTFS filesystems
3111 * once we do streams then we don't need this
3113 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3114 data_len = 88;
3115 SIVAL(pdata,84,0x100); /* Don't support mac... */
3116 break;
3118 /* drop through */
3119 default:
3120 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3121 return;
3125 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3126 max_data_bytes);
3128 DEBUG( 4, ( "%s info_level = %d\n",
3129 smb_fn_name(req->cmd), info_level) );
3131 return;
3134 /****************************************************************************
3135 Reply to a TRANS2_SETFSINFO (set filesystem info).
3136 ****************************************************************************/
3138 static void call_trans2setfsinfo(connection_struct *conn,
3139 struct smb_request *req,
3140 char **pparams, int total_params,
3141 char **ppdata, int total_data,
3142 unsigned int max_data_bytes)
3144 char *pdata = *ppdata;
3145 char *params = *pparams;
3146 uint16 info_level;
3148 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3150 /* */
3151 if (total_params < 4) {
3152 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3153 total_params));
3154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3155 return;
3158 info_level = SVAL(params,2);
3160 if (IS_IPC(conn)) {
3161 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3162 info_level != SMB_SET_CIFS_UNIX_INFO) {
3163 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3164 "info level (0x%x) on IPC$.\n",
3165 (unsigned int)info_level));
3166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3167 return;
3171 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3172 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3173 DEBUG(0,("call_trans2setfsinfo: encryption required "
3174 "and info level 0x%x sent.\n",
3175 (unsigned int)info_level));
3176 exit_server_cleanly("encryption required "
3177 "on connection");
3178 return;
3182 switch(info_level) {
3183 case SMB_SET_CIFS_UNIX_INFO:
3185 uint16 client_unix_major;
3186 uint16 client_unix_minor;
3187 uint32 client_unix_cap_low;
3188 uint32 client_unix_cap_high;
3190 if (!lp_unix_extensions()) {
3191 reply_nterror(req,
3192 NT_STATUS_INVALID_LEVEL);
3193 return;
3196 /* There should be 12 bytes of capabilities set. */
3197 if (total_data < 8) {
3198 reply_nterror(
3199 req,
3200 NT_STATUS_INVALID_PARAMETER);
3201 return;
3203 client_unix_major = SVAL(pdata,0);
3204 client_unix_minor = SVAL(pdata,2);
3205 client_unix_cap_low = IVAL(pdata,4);
3206 client_unix_cap_high = IVAL(pdata,8);
3207 /* Just print these values for now. */
3208 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3209 cap_low = 0x%x, cap_high = 0x%x\n",
3210 (unsigned int)client_unix_major,
3211 (unsigned int)client_unix_minor,
3212 (unsigned int)client_unix_cap_low,
3213 (unsigned int)client_unix_cap_high ));
3215 /* Here is where we must switch to posix pathname processing... */
3216 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3217 lp_set_posix_pathnames();
3218 mangle_change_to_posix();
3221 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3222 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3223 /* Client that knows how to do posix locks,
3224 * but not posix open/mkdir operations. Set a
3225 * default type for read/write checks. */
3227 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3230 break;
3233 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3235 NTSTATUS status;
3236 size_t param_len = 0;
3237 size_t data_len = total_data;
3239 if (!lp_unix_extensions()) {
3240 reply_nterror(
3241 req,
3242 NT_STATUS_INVALID_LEVEL);
3243 return;
3246 if (lp_smb_encrypt(SNUM(conn)) == false) {
3247 reply_nterror(
3248 req,
3249 NT_STATUS_NOT_SUPPORTED);
3250 return;
3253 DEBUG( 4,("call_trans2setfsinfo: "
3254 "request transport encryption.\n"));
3256 status = srv_request_encryption_setup(conn,
3257 (unsigned char **)ppdata,
3258 &data_len,
3259 (unsigned char **)pparams,
3260 &param_len);
3262 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3263 !NT_STATUS_IS_OK(status)) {
3264 reply_nterror(req, status);
3265 return;
3268 send_trans2_replies(conn, req,
3269 *pparams,
3270 param_len,
3271 *ppdata,
3272 data_len,
3273 max_data_bytes);
3275 if (NT_STATUS_IS_OK(status)) {
3276 /* Server-side transport
3277 * encryption is now *on*. */
3278 status = srv_encryption_start(conn);
3279 if (!NT_STATUS_IS_OK(status)) {
3280 exit_server_cleanly(
3281 "Failure in setting "
3282 "up encrypted transport");
3285 return;
3288 case SMB_FS_QUOTA_INFORMATION:
3290 files_struct *fsp = NULL;
3291 SMB_NTQUOTA_STRUCT quotas;
3293 ZERO_STRUCT(quotas);
3295 /* access check */
3296 if ((conn->server_info->utok.uid != 0)
3297 ||!CAN_WRITE(conn)) {
3298 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3299 lp_servicename(SNUM(conn)),
3300 conn->server_info->unix_name));
3301 reply_doserror(req, ERRSRV, ERRaccess);
3302 return;
3305 /* note: normaly there're 48 bytes,
3306 * but we didn't use the last 6 bytes for now
3307 * --metze
3309 fsp = file_fsp(req, SVAL(params,0));
3311 if (!check_fsp_ntquota_handle(conn, req,
3312 fsp)) {
3313 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3314 reply_nterror(
3315 req, NT_STATUS_INVALID_HANDLE);
3316 return;
3319 if (total_data < 42) {
3320 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3321 total_data));
3322 reply_nterror(
3323 req,
3324 NT_STATUS_INVALID_PARAMETER);
3325 return;
3328 /* unknown_1 24 NULL bytes in pdata*/
3330 /* the soft quotas 8 bytes (uint64_t)*/
3331 quotas.softlim = (uint64_t)IVAL(pdata,24);
3332 #ifdef LARGE_SMB_OFF_T
3333 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3334 #else /* LARGE_SMB_OFF_T */
3335 if ((IVAL(pdata,28) != 0)&&
3336 ((quotas.softlim != 0xFFFFFFFF)||
3337 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3338 /* more than 32 bits? */
3339 reply_nterror(
3340 req,
3341 NT_STATUS_INVALID_PARAMETER);
3342 return;
3344 #endif /* LARGE_SMB_OFF_T */
3346 /* the hard quotas 8 bytes (uint64_t)*/
3347 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3348 #ifdef LARGE_SMB_OFF_T
3349 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3350 #else /* LARGE_SMB_OFF_T */
3351 if ((IVAL(pdata,36) != 0)&&
3352 ((quotas.hardlim != 0xFFFFFFFF)||
3353 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3354 /* more than 32 bits? */
3355 reply_nterror(
3356 req,
3357 NT_STATUS_INVALID_PARAMETER);
3358 return;
3360 #endif /* LARGE_SMB_OFF_T */
3362 /* quota_flags 2 bytes **/
3363 quotas.qflags = SVAL(pdata,40);
3365 /* unknown_2 6 NULL bytes follow*/
3367 /* now set the quotas */
3368 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3369 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3370 reply_doserror(req, ERRSRV, ERRerror);
3371 return;
3374 break;
3376 default:
3377 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3378 info_level));
3379 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3380 return;
3381 break;
3385 * sending this reply works fine,
3386 * but I'm not sure it's the same
3387 * like windows do...
3388 * --metze
3390 reply_outbuf(req, 10, 0);
3393 #if defined(HAVE_POSIX_ACLS)
3394 /****************************************************************************
3395 Utility function to count the number of entries in a POSIX acl.
3396 ****************************************************************************/
3398 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3400 unsigned int ace_count = 0;
3401 int entry_id = SMB_ACL_FIRST_ENTRY;
3402 SMB_ACL_ENTRY_T entry;
3404 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3405 /* get_next... */
3406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3407 entry_id = SMB_ACL_NEXT_ENTRY;
3409 ace_count++;
3411 return ace_count;
3414 /****************************************************************************
3415 Utility function to marshall a POSIX acl into wire format.
3416 ****************************************************************************/
3418 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3420 int entry_id = SMB_ACL_FIRST_ENTRY;
3421 SMB_ACL_ENTRY_T entry;
3423 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3424 SMB_ACL_TAG_T tagtype;
3425 SMB_ACL_PERMSET_T permset;
3426 unsigned char perms = 0;
3427 unsigned int own_grp;
3429 /* get_next... */
3430 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3431 entry_id = SMB_ACL_NEXT_ENTRY;
3434 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3435 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3436 return False;
3439 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3440 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3441 return False;
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3446 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3448 SCVAL(pdata,1,perms);
3450 switch (tagtype) {
3451 case SMB_ACL_USER_OBJ:
3452 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3453 own_grp = (unsigned int)pst->st_uid;
3454 SIVAL(pdata,2,own_grp);
3455 SIVAL(pdata,6,0);
3456 break;
3457 case SMB_ACL_USER:
3459 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3460 if (!puid) {
3461 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3462 return False;
3464 own_grp = (unsigned int)*puid;
3465 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3466 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3467 SIVAL(pdata,2,own_grp);
3468 SIVAL(pdata,6,0);
3469 break;
3471 case SMB_ACL_GROUP_OBJ:
3472 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3473 own_grp = (unsigned int)pst->st_gid;
3474 SIVAL(pdata,2,own_grp);
3475 SIVAL(pdata,6,0);
3476 break;
3477 case SMB_ACL_GROUP:
3479 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3480 if (!pgid) {
3481 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3482 return False;
3484 own_grp = (unsigned int)*pgid;
3485 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3486 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3487 SIVAL(pdata,2,own_grp);
3488 SIVAL(pdata,6,0);
3489 break;
3491 case SMB_ACL_MASK:
3492 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3493 SIVAL(pdata,2,0xFFFFFFFF);
3494 SIVAL(pdata,6,0xFFFFFFFF);
3495 break;
3496 case SMB_ACL_OTHER:
3497 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3498 SIVAL(pdata,2,0xFFFFFFFF);
3499 SIVAL(pdata,6,0xFFFFFFFF);
3500 break;
3501 default:
3502 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3503 return False;
3505 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3508 return True;
3510 #endif
3512 /****************************************************************************
3513 Store the FILE_UNIX_BASIC info.
3514 ****************************************************************************/
3516 static char *store_file_unix_basic(connection_struct *conn,
3517 char *pdata,
3518 files_struct *fsp,
3519 const SMB_STRUCT_STAT *psbuf)
3521 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3522 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3524 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3525 pdata += 8;
3527 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3528 pdata += 8;
3530 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3531 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3532 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3533 pdata += 24;
3535 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3536 SIVAL(pdata,4,0);
3537 pdata += 8;
3539 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3540 SIVAL(pdata,4,0);
3541 pdata += 8;
3543 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3544 pdata += 4;
3546 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3547 SIVAL(pdata,4,0);
3548 pdata += 8;
3550 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3551 SIVAL(pdata,4,0);
3552 pdata += 8;
3554 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3555 pdata += 8;
3557 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3558 SIVAL(pdata,4,0);
3559 pdata += 8;
3561 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3562 SIVAL(pdata,4,0);
3563 pdata += 8;
3565 return pdata;
3568 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3569 * the chflags(2) (or equivalent) flags.
3571 * XXX: this really should be behind the VFS interface. To do this, we would
3572 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3573 * Each VFS module could then implement its own mapping as appropriate for the
3574 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3576 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3577 info2_flags_map[] =
3579 #ifdef UF_NODUMP
3580 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3581 #endif
3583 #ifdef UF_IMMUTABLE
3584 { UF_IMMUTABLE, EXT_IMMUTABLE },
3585 #endif
3587 #ifdef UF_APPEND
3588 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3589 #endif
3591 #ifdef UF_HIDDEN
3592 { UF_HIDDEN, EXT_HIDDEN },
3593 #endif
3595 /* Do not remove. We need to guarantee that this array has at least one
3596 * entry to build on HP-UX.
3598 { 0, 0 }
3602 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3603 uint32 *smb_fflags, uint32 *smb_fmask)
3605 #ifdef HAVE_STAT_ST_FLAGS
3606 int i;
3608 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3609 *smb_fmask |= info2_flags_map[i].smb_fflag;
3610 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3611 *smb_fflags |= info2_flags_map[i].smb_fflag;
3614 #endif /* HAVE_STAT_ST_FLAGS */
3617 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3618 const uint32 smb_fflags,
3619 const uint32 smb_fmask,
3620 int *stat_fflags)
3622 #ifdef HAVE_STAT_ST_FLAGS
3623 uint32 max_fmask = 0;
3624 int i;
3626 *stat_fflags = psbuf->st_flags;
3628 /* For each flags requested in smb_fmask, check the state of the
3629 * corresponding flag in smb_fflags and set or clear the matching
3630 * stat flag.
3633 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3634 max_fmask |= info2_flags_map[i].smb_fflag;
3635 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3636 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3637 *stat_fflags |= info2_flags_map[i].stat_fflag;
3638 } else {
3639 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3644 /* If smb_fmask is asking to set any bits that are not supported by
3645 * our flag mappings, we should fail.
3647 if ((smb_fmask & max_fmask) != smb_fmask) {
3648 return False;
3651 return True;
3652 #else
3653 return False;
3654 #endif /* HAVE_STAT_ST_FLAGS */
3658 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3659 * of file flags and birth (create) time.
3661 static char *store_file_unix_basic_info2(connection_struct *conn,
3662 char *pdata,
3663 files_struct *fsp,
3664 const SMB_STRUCT_STAT *psbuf)
3666 uint32 file_flags = 0;
3667 uint32 flags_mask = 0;
3669 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3671 /* Create (birth) time 64 bit */
3672 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3673 pdata += 8;
3675 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3676 SIVAL(pdata, 0, file_flags); /* flags */
3677 SIVAL(pdata, 4, flags_mask); /* mask */
3678 pdata += 8;
3680 return pdata;
3683 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3684 const struct stream_struct *streams,
3685 char *data,
3686 unsigned int max_data_bytes,
3687 unsigned int *data_size)
3689 unsigned int i;
3690 unsigned int ofs = 0;
3692 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3693 unsigned int next_offset;
3694 size_t namelen;
3695 smb_ucs2_t *namebuf;
3697 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3698 streams[i].name, &namelen) ||
3699 namelen <= 2)
3701 return NT_STATUS_INVALID_PARAMETER;
3705 * name_buf is now null-terminated, we need to marshall as not
3706 * terminated
3709 namelen -= 2;
3711 SIVAL(data, ofs+4, namelen);
3712 SOFF_T(data, ofs+8, streams[i].size);
3713 SOFF_T(data, ofs+16, streams[i].alloc_size);
3714 memcpy(data+ofs+24, namebuf, namelen);
3715 TALLOC_FREE(namebuf);
3717 next_offset = ofs + 24 + namelen;
3719 if (i == num_streams-1) {
3720 SIVAL(data, ofs, 0);
3722 else {
3723 unsigned int align = ndr_align_size(next_offset, 8);
3725 memset(data+next_offset, 0, align);
3726 next_offset += align;
3728 SIVAL(data, ofs, next_offset - ofs);
3729 ofs = next_offset;
3732 ofs = next_offset;
3735 *data_size = ofs;
3737 return NT_STATUS_OK;
3740 /****************************************************************************
3741 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3742 ****************************************************************************/
3744 static void call_trans2qpipeinfo(connection_struct *conn,
3745 struct smb_request *req,
3746 unsigned int tran_call,
3747 char **pparams, int total_params,
3748 char **ppdata, int total_data,
3749 unsigned int max_data_bytes)
3751 char *params = *pparams;
3752 char *pdata = *ppdata;
3753 unsigned int data_size = 0;
3754 unsigned int param_size = 2;
3755 uint16 info_level;
3756 files_struct *fsp;
3758 if (!params) {
3759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3760 return;
3763 if (total_params < 4) {
3764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3765 return;
3768 fsp = file_fsp(req, SVAL(params,0));
3769 if (!fsp_is_np(fsp)) {
3770 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3771 return;
3774 info_level = SVAL(params,2);
3776 *pparams = (char *)SMB_REALLOC(*pparams,2);
3777 if (*pparams == NULL) {
3778 reply_nterror(req, NT_STATUS_NO_MEMORY);
3779 return;
3781 params = *pparams;
3782 SSVAL(params,0,0);
3783 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3784 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3785 if (*ppdata == NULL ) {
3786 reply_nterror(req, NT_STATUS_NO_MEMORY);
3787 return;
3789 pdata = *ppdata;
3791 switch (info_level) {
3792 case SMB_FILE_STANDARD_INFORMATION:
3793 memset(pdata,0,24);
3794 SOFF_T(pdata,0,4096LL);
3795 SIVAL(pdata,16,1);
3796 SIVAL(pdata,20,1);
3797 data_size = 24;
3798 break;
3800 default:
3801 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3802 return;
3805 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3806 max_data_bytes);
3808 return;
3811 /****************************************************************************
3812 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3813 file name or file id).
3814 ****************************************************************************/
3816 static void call_trans2qfilepathinfo(connection_struct *conn,
3817 struct smb_request *req,
3818 unsigned int tran_call,
3819 char **pparams, int total_params,
3820 char **ppdata, int total_data,
3821 unsigned int max_data_bytes)
3823 char *params = *pparams;
3824 char *pdata = *ppdata;
3825 char *dstart, *dend;
3826 uint16 info_level;
3827 int mode=0;
3828 int nlink;
3829 SMB_OFF_T file_size=0;
3830 uint64_t allocation_size=0;
3831 unsigned int data_size = 0;
3832 unsigned int param_size = 2;
3833 SMB_STRUCT_STAT sbuf;
3834 char *dos_fname = NULL;
3835 char *fname = NULL;
3836 char *fullpathname;
3837 char *base_name;
3838 char *p;
3839 SMB_OFF_T pos = 0;
3840 bool delete_pending = False;
3841 int len;
3842 time_t create_time, mtime, atime;
3843 struct timespec create_time_ts, mtime_ts, atime_ts;
3844 struct timespec write_time_ts;
3845 files_struct *fsp = NULL;
3846 struct file_id fileid;
3847 struct ea_list *ea_list = NULL;
3848 char *lock_data = NULL;
3849 bool ms_dfs_link = false;
3850 TALLOC_CTX *ctx = talloc_tos();
3852 if (!params) {
3853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3854 return;
3857 ZERO_STRUCT(sbuf);
3858 ZERO_STRUCT(write_time_ts);
3860 if (tran_call == TRANSACT2_QFILEINFO) {
3861 if (total_params < 4) {
3862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3863 return;
3866 if (IS_IPC(conn)) {
3867 call_trans2qpipeinfo(conn, req, tran_call,
3868 pparams, total_params,
3869 ppdata, total_data,
3870 max_data_bytes);
3871 return;
3874 fsp = file_fsp(req, SVAL(params,0));
3875 info_level = SVAL(params,2);
3877 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3879 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3880 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3881 return;
3884 /* Initial check for valid fsp ptr. */
3885 if (!check_fsp_open(conn, req, fsp)) {
3886 return;
3889 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3890 if (!fname) {
3891 reply_nterror(req, NT_STATUS_NO_MEMORY);
3892 return;
3895 if(fsp->fake_file_handle) {
3897 * This is actually for the QUOTA_FAKE_FILE --metze
3900 /* We know this name is ok, it's already passed the checks. */
3902 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3904 * This is actually a QFILEINFO on a directory
3905 * handle (returned from an NT SMB). NT5.0 seems
3906 * to do this call. JRA.
3909 if (INFO_LEVEL_IS_UNIX(info_level)) {
3910 /* Always do lstat for UNIX calls. */
3911 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3912 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3913 reply_unixerror(req,ERRDOS,ERRbadpath);
3914 return;
3916 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3917 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3918 reply_unixerror(req, ERRDOS, ERRbadpath);
3919 return;
3922 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3923 get_file_infos(fileid, &delete_pending, &write_time_ts);
3924 } else {
3926 * Original code - this is an open file.
3928 if (!check_fsp(conn, req, fsp)) {
3929 return;
3932 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3933 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3934 reply_unixerror(req, ERRDOS, ERRbadfid);
3935 return;
3937 pos = fsp->fh->position_information;
3938 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3939 get_file_infos(fileid, &delete_pending, &write_time_ts);
3942 } else {
3943 NTSTATUS status = NT_STATUS_OK;
3945 /* qpathinfo */
3946 if (total_params < 7) {
3947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3948 return;
3951 info_level = SVAL(params,0);
3953 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3955 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3957 return;
3960 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3961 total_params - 6,
3962 STR_TERMINATE, &status);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 reply_nterror(req, status);
3965 return;
3968 status = resolve_dfspath(ctx,
3969 conn,
3970 req->flags2 & FLAGS2_DFS_PATHNAMES,
3971 fname,
3972 &fname);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3975 reply_botherror(req,
3976 NT_STATUS_PATH_NOT_COVERED,
3977 ERRSRV, ERRbadpath);
3979 reply_nterror(req, status);
3980 return;
3983 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 reply_nterror(req, status);
3986 return;
3988 status = check_name(conn, fname);
3989 if (!NT_STATUS_IS_OK(status)) {
3990 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3991 reply_nterror(req, status);
3992 return;
3995 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3996 && is_ntfs_stream_name(fname)) {
3997 char *base;
3998 SMB_STRUCT_STAT bsbuf;
4000 status = split_ntfs_stream_name(talloc_tos(), fname,
4001 &base, NULL);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 DEBUG(10, ("create_file_unixpath: "
4004 "split_ntfs_stream_name failed: %s\n",
4005 nt_errstr(status)));
4006 reply_nterror(req, status);
4007 return;
4010 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4012 if (INFO_LEVEL_IS_UNIX(info_level)) {
4013 /* Always do lstat for UNIX calls. */
4014 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4015 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4016 reply_unixerror(req,ERRDOS,ERRbadpath);
4017 return;
4019 } else {
4020 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4021 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4022 reply_unixerror(req,ERRDOS,ERRbadpath);
4023 return;
4027 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4028 get_file_infos(fileid, &delete_pending, NULL);
4029 if (delete_pending) {
4030 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4031 return;
4035 if (INFO_LEVEL_IS_UNIX(info_level)) {
4036 /* Always do lstat for UNIX calls. */
4037 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4038 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4039 reply_unixerror(req, ERRDOS, ERRbadpath);
4040 return;
4043 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4044 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4046 if (!ms_dfs_link) {
4047 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4048 reply_unixerror(req, ERRDOS, ERRbadpath);
4049 return;
4053 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4054 get_file_infos(fileid, &delete_pending, &write_time_ts);
4055 if (delete_pending) {
4056 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4057 return;
4061 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4062 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4063 return;
4066 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4067 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4069 p = strrchr_m(fname,'/');
4070 if (!p)
4071 base_name = fname;
4072 else
4073 base_name = p+1;
4075 if (ms_dfs_link) {
4076 mode = dos_mode_msdfs(conn,fname,&sbuf);
4077 } else {
4078 mode = dos_mode(conn,fname,&sbuf);
4080 if (!mode)
4081 mode = FILE_ATTRIBUTE_NORMAL;
4083 nlink = sbuf.st_nlink;
4085 if (nlink && (mode&aDIR)) {
4086 nlink = 1;
4089 if ((nlink > 0) && delete_pending) {
4090 nlink -= 1;
4093 fullpathname = fname;
4094 if (!(mode & aDIR))
4095 file_size = get_file_size(sbuf);
4097 /* Pull out any data sent here before we realloc. */
4098 switch (info_level) {
4099 case SMB_INFO_QUERY_EAS_FROM_LIST:
4101 /* Pull any EA list from the data portion. */
4102 uint32 ea_size;
4104 if (total_data < 4) {
4105 reply_nterror(
4106 req, NT_STATUS_INVALID_PARAMETER);
4107 return;
4109 ea_size = IVAL(pdata,0);
4111 if (total_data > 0 && ea_size != total_data) {
4112 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4113 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4114 reply_nterror(
4115 req, NT_STATUS_INVALID_PARAMETER);
4116 return;
4119 if (!lp_ea_support(SNUM(conn))) {
4120 reply_doserror(req, ERRDOS,
4121 ERReasnotsupported);
4122 return;
4125 /* Pull out the list of names. */
4126 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4127 if (!ea_list) {
4128 reply_nterror(
4129 req, NT_STATUS_INVALID_PARAMETER);
4130 return;
4132 break;
4135 case SMB_QUERY_POSIX_LOCK:
4137 if (fsp == NULL || fsp->fh->fd == -1) {
4138 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4139 return;
4142 if (total_data != POSIX_LOCK_DATA_SIZE) {
4143 reply_nterror(
4144 req, NT_STATUS_INVALID_PARAMETER);
4145 return;
4148 /* Copy the lock range data. */
4149 lock_data = (char *)TALLOC_MEMDUP(
4150 ctx, pdata, total_data);
4151 if (!lock_data) {
4152 reply_nterror(req, NT_STATUS_NO_MEMORY);
4153 return;
4156 default:
4157 break;
4160 *pparams = (char *)SMB_REALLOC(*pparams,2);
4161 if (*pparams == NULL) {
4162 reply_nterror(req, NT_STATUS_NO_MEMORY);
4163 return;
4165 params = *pparams;
4166 SSVAL(params,0,0);
4167 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4168 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4169 if (*ppdata == NULL ) {
4170 reply_nterror(req, NT_STATUS_NO_MEMORY);
4171 return;
4173 pdata = *ppdata;
4174 dstart = pdata;
4175 dend = dstart + data_size - 1;
4177 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4178 mtime_ts = get_mtimespec(&sbuf);
4179 atime_ts = get_atimespec(&sbuf);
4181 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4183 if (!fsp) {
4184 /* Do we have this path open ? */
4185 files_struct *fsp1;
4186 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4187 fsp1 = file_find_di_first(fileid);
4188 if (fsp1 && fsp1->initial_allocation_size) {
4189 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4193 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4194 mtime_ts = write_time_ts;
4197 if (lp_dos_filetime_resolution(SNUM(conn))) {
4198 dos_filetime_timespec(&create_time_ts);
4199 dos_filetime_timespec(&mtime_ts);
4200 dos_filetime_timespec(&atime_ts);
4203 create_time = convert_timespec_to_time_t(create_time_ts);
4204 mtime = convert_timespec_to_time_t(mtime_ts);
4205 atime = convert_timespec_to_time_t(atime_ts);
4207 /* NT expects the name to be in an exact form of the *full*
4208 filename. See the trans2 torture test */
4209 if (ISDOT(base_name)) {
4210 dos_fname = talloc_strdup(ctx, "\\");
4211 if (!dos_fname) {
4212 reply_nterror(req, NT_STATUS_NO_MEMORY);
4213 return;
4215 } else {
4216 dos_fname = talloc_asprintf(ctx,
4217 "\\%s",
4218 fname);
4219 if (!dos_fname) {
4220 reply_nterror(req, NT_STATUS_NO_MEMORY);
4221 return;
4223 string_replace(dos_fname, '/', '\\');
4226 switch (info_level) {
4227 case SMB_INFO_STANDARD:
4228 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4229 data_size = 22;
4230 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4231 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4232 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4233 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4234 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4235 SSVAL(pdata,l1_attrFile,mode);
4236 break;
4238 case SMB_INFO_QUERY_EA_SIZE:
4240 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4241 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4242 data_size = 26;
4243 srv_put_dos_date2(pdata,0,create_time);
4244 srv_put_dos_date2(pdata,4,atime);
4245 srv_put_dos_date2(pdata,8,mtime); /* write time */
4246 SIVAL(pdata,12,(uint32)file_size);
4247 SIVAL(pdata,16,(uint32)allocation_size);
4248 SSVAL(pdata,20,mode);
4249 SIVAL(pdata,22,ea_size);
4250 break;
4253 case SMB_INFO_IS_NAME_VALID:
4254 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4255 if (tran_call == TRANSACT2_QFILEINFO) {
4256 /* os/2 needs this ? really ?*/
4257 reply_doserror(req, ERRDOS, ERRbadfunc);
4258 return;
4260 data_size = 0;
4261 param_size = 0;
4262 break;
4264 case SMB_INFO_QUERY_EAS_FROM_LIST:
4266 size_t total_ea_len = 0;
4267 struct ea_list *ea_file_list = NULL;
4269 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4271 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4272 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4274 if (!ea_list || (total_ea_len > data_size)) {
4275 data_size = 4;
4276 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4277 break;
4280 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4281 break;
4284 case SMB_INFO_QUERY_ALL_EAS:
4286 /* We have data_size bytes to put EA's into. */
4287 size_t total_ea_len = 0;
4289 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4291 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4292 if (!ea_list || (total_ea_len > data_size)) {
4293 data_size = 4;
4294 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4295 break;
4298 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4299 break;
4302 case SMB_FILE_BASIC_INFORMATION:
4303 case SMB_QUERY_FILE_BASIC_INFO:
4305 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4306 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4307 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4308 } else {
4309 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4310 data_size = 40;
4311 SIVAL(pdata,36,0);
4313 put_long_date_timespec(pdata,create_time_ts);
4314 put_long_date_timespec(pdata+8,atime_ts);
4315 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4316 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4317 SIVAL(pdata,32,mode);
4319 DEBUG(5,("SMB_QFBI - "));
4320 DEBUG(5,("create: %s ", ctime(&create_time)));
4321 DEBUG(5,("access: %s ", ctime(&atime)));
4322 DEBUG(5,("write: %s ", ctime(&mtime)));
4323 DEBUG(5,("change: %s ", ctime(&mtime)));
4324 DEBUG(5,("mode: %x\n", mode));
4325 break;
4327 case SMB_FILE_STANDARD_INFORMATION:
4328 case SMB_QUERY_FILE_STANDARD_INFO:
4330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4331 data_size = 24;
4332 SOFF_T(pdata,0,allocation_size);
4333 SOFF_T(pdata,8,file_size);
4334 SIVAL(pdata,16,nlink);
4335 SCVAL(pdata,20,delete_pending?1:0);
4336 SCVAL(pdata,21,(mode&aDIR)?1:0);
4337 SSVAL(pdata,22,0); /* Padding. */
4338 break;
4340 case SMB_FILE_EA_INFORMATION:
4341 case SMB_QUERY_FILE_EA_INFO:
4343 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4344 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4345 data_size = 4;
4346 SIVAL(pdata,0,ea_size);
4347 break;
4350 /* Get the 8.3 name - used if NT SMB was negotiated. */
4351 case SMB_QUERY_FILE_ALT_NAME_INFO:
4352 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4354 char mangled_name[13];
4355 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4356 if (!name_to_8_3(base_name,mangled_name,
4357 True,conn->params)) {
4358 reply_nterror(
4359 req,
4360 NT_STATUS_NO_MEMORY);
4362 len = srvstr_push(dstart, req->flags2,
4363 pdata+4, mangled_name,
4364 PTR_DIFF(dend, pdata+4),
4365 STR_UNICODE);
4366 data_size = 4 + len;
4367 SIVAL(pdata,0,len);
4368 break;
4371 case SMB_QUERY_FILE_NAME_INFO:
4373 this must be *exactly* right for ACLs on mapped drives to work
4375 len = srvstr_push(dstart, req->flags2,
4376 pdata+4, dos_fname,
4377 PTR_DIFF(dend, pdata+4),
4378 STR_UNICODE);
4379 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4380 data_size = 4 + len;
4381 SIVAL(pdata,0,len);
4382 break;
4384 case SMB_FILE_ALLOCATION_INFORMATION:
4385 case SMB_QUERY_FILE_ALLOCATION_INFO:
4386 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4387 data_size = 8;
4388 SOFF_T(pdata,0,allocation_size);
4389 break;
4391 case SMB_FILE_END_OF_FILE_INFORMATION:
4392 case SMB_QUERY_FILE_END_OF_FILEINFO:
4393 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4394 data_size = 8;
4395 SOFF_T(pdata,0,file_size);
4396 break;
4398 case SMB_QUERY_FILE_ALL_INFO:
4399 case SMB_FILE_ALL_INFORMATION:
4401 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4403 put_long_date_timespec(pdata,create_time_ts);
4404 put_long_date_timespec(pdata+8,atime_ts);
4405 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4406 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4407 SIVAL(pdata,32,mode);
4408 SIVAL(pdata,36,0); /* padding. */
4409 pdata += 40;
4410 SOFF_T(pdata,0,allocation_size);
4411 SOFF_T(pdata,8,file_size);
4412 SIVAL(pdata,16,nlink);
4413 SCVAL(pdata,20,delete_pending);
4414 SCVAL(pdata,21,(mode&aDIR)?1:0);
4415 SSVAL(pdata,22,0);
4416 pdata += 24;
4417 SIVAL(pdata,0,ea_size);
4418 pdata += 4; /* EA info */
4419 len = srvstr_push(dstart, req->flags2,
4420 pdata+4, dos_fname,
4421 PTR_DIFF(dend, pdata+4),
4422 STR_UNICODE);
4423 SIVAL(pdata,0,len);
4424 pdata += 4 + len;
4425 data_size = PTR_DIFF(pdata,(*ppdata));
4426 break;
4428 case SMB_FILE_INTERNAL_INFORMATION:
4429 /* This should be an index number - looks like
4430 dev/ino to me :-)
4432 I think this causes us to fail the IFSKIT
4433 BasicFileInformationTest. -tpot */
4435 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4436 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4437 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4438 data_size = 8;
4439 break;
4441 case SMB_FILE_ACCESS_INFORMATION:
4442 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4443 if (fsp) {
4444 SIVAL(pdata,0,fsp->access_mask);
4445 } else {
4446 /* GENERIC_EXECUTE mapping from Windows */
4447 SIVAL(pdata,0,0x12019F);
4449 data_size = 4;
4450 break;
4452 case SMB_FILE_NAME_INFORMATION:
4453 /* Pathname with leading '\'. */
4455 size_t byte_len;
4456 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4457 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4458 SIVAL(pdata,0,byte_len);
4459 data_size = 4 + byte_len;
4460 break;
4463 case SMB_FILE_DISPOSITION_INFORMATION:
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4465 data_size = 1;
4466 SCVAL(pdata,0,delete_pending);
4467 break;
4469 case SMB_FILE_POSITION_INFORMATION:
4470 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4471 data_size = 8;
4472 SOFF_T(pdata,0,pos);
4473 break;
4475 case SMB_FILE_MODE_INFORMATION:
4476 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4477 SIVAL(pdata,0,mode);
4478 data_size = 4;
4479 break;
4481 case SMB_FILE_ALIGNMENT_INFORMATION:
4482 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4483 SIVAL(pdata,0,0); /* No alignment needed. */
4484 data_size = 4;
4485 break;
4488 * NT4 server just returns "invalid query" to this - if we try
4489 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4490 * want this. JRA.
4492 /* The first statement above is false - verified using Thursby
4493 * client against NT4 -- gcolley.
4495 case SMB_QUERY_FILE_STREAM_INFO:
4496 case SMB_FILE_STREAM_INFORMATION: {
4497 unsigned int num_streams;
4498 struct stream_struct *streams;
4499 NTSTATUS status;
4501 DEBUG(10,("call_trans2qfilepathinfo: "
4502 "SMB_FILE_STREAM_INFORMATION\n"));
4504 status = SMB_VFS_STREAMINFO(
4505 conn, fsp, fname, talloc_tos(),
4506 &num_streams, &streams);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 DEBUG(10, ("could not get stream info: %s\n",
4510 nt_errstr(status)));
4511 reply_nterror(req, status);
4512 return;
4515 status = marshall_stream_info(num_streams, streams,
4516 pdata, max_data_bytes,
4517 &data_size);
4519 if (!NT_STATUS_IS_OK(status)) {
4520 DEBUG(10, ("marshall_stream_info failed: %s\n",
4521 nt_errstr(status)));
4522 reply_nterror(req, status);
4523 return;
4526 TALLOC_FREE(streams);
4528 break;
4530 case SMB_QUERY_COMPRESSION_INFO:
4531 case SMB_FILE_COMPRESSION_INFORMATION:
4532 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4533 SOFF_T(pdata,0,file_size);
4534 SIVAL(pdata,8,0); /* ??? */
4535 SIVAL(pdata,12,0); /* ??? */
4536 data_size = 16;
4537 break;
4539 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4540 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4541 put_long_date_timespec(pdata,create_time_ts);
4542 put_long_date_timespec(pdata+8,atime_ts);
4543 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4544 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4545 SOFF_T(pdata,32,allocation_size);
4546 SOFF_T(pdata,40,file_size);
4547 SIVAL(pdata,48,mode);
4548 SIVAL(pdata,52,0); /* ??? */
4549 data_size = 56;
4550 break;
4552 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4554 SIVAL(pdata,0,mode);
4555 SIVAL(pdata,4,0);
4556 data_size = 8;
4557 break;
4560 * CIFS UNIX Extensions.
4563 case SMB_QUERY_FILE_UNIX_BASIC:
4565 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4566 data_size = PTR_DIFF(pdata,(*ppdata));
4569 int i;
4570 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4572 for (i=0; i<100; i++)
4573 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4574 DEBUG(4,("\n"));
4577 break;
4579 case SMB_QUERY_FILE_UNIX_INFO2:
4581 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4582 data_size = PTR_DIFF(pdata,(*ppdata));
4585 int i;
4586 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4588 for (i=0; i<100; i++)
4589 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4590 DEBUG(4,("\n"));
4593 break;
4595 case SMB_QUERY_FILE_UNIX_LINK:
4597 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4599 if (!buffer) {
4600 reply_nterror(req, NT_STATUS_NO_MEMORY);
4601 return;
4604 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4605 #ifdef S_ISLNK
4606 if(!S_ISLNK(sbuf.st_mode)) {
4607 reply_unixerror(req, ERRSRV,
4608 ERRbadlink);
4609 return;
4611 #else
4612 reply_unixerror(req, ERRDOS, ERRbadlink);
4613 return;
4614 #endif
4615 len = SMB_VFS_READLINK(conn,fullpathname,
4616 buffer, PATH_MAX);
4617 if (len == -1) {
4618 reply_unixerror(req, ERRDOS,
4619 ERRnoaccess);
4620 return;
4622 buffer[len] = 0;
4623 len = srvstr_push(dstart, req->flags2,
4624 pdata, buffer,
4625 PTR_DIFF(dend, pdata),
4626 STR_TERMINATE);
4627 pdata += len;
4628 data_size = PTR_DIFF(pdata,(*ppdata));
4630 break;
4633 #if defined(HAVE_POSIX_ACLS)
4634 case SMB_QUERY_POSIX_ACL:
4636 SMB_ACL_T file_acl = NULL;
4637 SMB_ACL_T def_acl = NULL;
4638 uint16 num_file_acls = 0;
4639 uint16 num_def_acls = 0;
4641 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4642 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4643 } else {
4644 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4647 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4648 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4649 fname ));
4650 reply_nterror(
4651 req,
4652 NT_STATUS_NOT_IMPLEMENTED);
4653 return;
4656 if (S_ISDIR(sbuf.st_mode)) {
4657 if (fsp && fsp->is_directory) {
4658 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4659 } else {
4660 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4662 def_acl = free_empty_sys_acl(conn, def_acl);
4665 num_file_acls = count_acl_entries(conn, file_acl);
4666 num_def_acls = count_acl_entries(conn, def_acl);
4668 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4669 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4670 data_size,
4671 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4672 SMB_POSIX_ACL_HEADER_SIZE) ));
4673 if (file_acl) {
4674 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4676 if (def_acl) {
4677 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4679 reply_nterror(
4680 req,
4681 NT_STATUS_BUFFER_TOO_SMALL);
4682 return;
4685 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4686 SSVAL(pdata,2,num_file_acls);
4687 SSVAL(pdata,4,num_def_acls);
4688 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4689 if (file_acl) {
4690 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692 if (def_acl) {
4693 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4695 reply_nterror(
4696 req, NT_STATUS_INTERNAL_ERROR);
4697 return;
4699 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4700 if (file_acl) {
4701 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4703 if (def_acl) {
4704 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4706 reply_nterror(
4707 req,
4708 NT_STATUS_INTERNAL_ERROR);
4709 return;
4712 if (file_acl) {
4713 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4715 if (def_acl) {
4716 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4718 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4719 break;
4721 #endif
4724 case SMB_QUERY_POSIX_LOCK:
4726 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4727 uint64_t count;
4728 uint64_t offset;
4729 uint32 lock_pid;
4730 enum brl_type lock_type;
4732 if (total_data != POSIX_LOCK_DATA_SIZE) {
4733 reply_nterror(
4734 req, NT_STATUS_INVALID_PARAMETER);
4735 return;
4738 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4739 case POSIX_LOCK_TYPE_READ:
4740 lock_type = READ_LOCK;
4741 break;
4742 case POSIX_LOCK_TYPE_WRITE:
4743 lock_type = WRITE_LOCK;
4744 break;
4745 case POSIX_LOCK_TYPE_UNLOCK:
4746 default:
4747 /* There's no point in asking for an unlock... */
4748 reply_nterror(
4749 req,
4750 NT_STATUS_INVALID_PARAMETER);
4751 return;
4754 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4755 #if defined(HAVE_LONGLONG)
4756 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4757 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4758 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4759 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4760 #else /* HAVE_LONGLONG */
4761 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4762 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4763 #endif /* HAVE_LONGLONG */
4765 status = query_lock(fsp,
4766 &lock_pid,
4767 &count,
4768 &offset,
4769 &lock_type,
4770 POSIX_LOCK);
4772 if (ERROR_WAS_LOCK_DENIED(status)) {
4773 /* Here we need to report who has it locked... */
4774 data_size = POSIX_LOCK_DATA_SIZE;
4776 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4777 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4778 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4779 #if defined(HAVE_LONGLONG)
4780 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4781 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4782 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4783 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4784 #else /* HAVE_LONGLONG */
4785 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4786 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4787 #endif /* HAVE_LONGLONG */
4789 } else if (NT_STATUS_IS_OK(status)) {
4790 /* For success we just return a copy of what we sent
4791 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4792 data_size = POSIX_LOCK_DATA_SIZE;
4793 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4794 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4795 } else {
4796 reply_nterror(req, status);
4797 return;
4799 break;
4802 default:
4803 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4804 return;
4807 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4808 max_data_bytes);
4810 return;
4813 /****************************************************************************
4814 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4815 code.
4816 ****************************************************************************/
4818 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4819 connection_struct *conn,
4820 const char *oldname_in,
4821 const char *newname_in)
4823 SMB_STRUCT_STAT sbuf1, sbuf2;
4824 char *last_component_oldname = NULL;
4825 char *last_component_newname = NULL;
4826 char *oldname = NULL;
4827 char *newname = NULL;
4828 NTSTATUS status = NT_STATUS_OK;
4830 ZERO_STRUCT(sbuf1);
4831 ZERO_STRUCT(sbuf2);
4833 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4834 &last_component_oldname, &sbuf1);
4835 if (!NT_STATUS_IS_OK(status)) {
4836 return status;
4839 status = check_name(conn, oldname);
4840 if (!NT_STATUS_IS_OK(status)) {
4841 return status;
4844 /* source must already exist. */
4845 if (!VALID_STAT(sbuf1)) {
4846 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4849 status = unix_convert(ctx, conn, newname_in, False, &newname,
4850 &last_component_newname, &sbuf2);
4851 if (!NT_STATUS_IS_OK(status)) {
4852 return status;
4855 status = check_name(conn, newname);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 return status;
4860 /* Disallow if newname already exists. */
4861 if (VALID_STAT(sbuf2)) {
4862 return NT_STATUS_OBJECT_NAME_COLLISION;
4865 /* No links from a directory. */
4866 if (S_ISDIR(sbuf1.st_mode)) {
4867 return NT_STATUS_FILE_IS_A_DIRECTORY;
4870 /* Ensure this is within the share. */
4871 status = check_reduced_name(conn, oldname);
4872 if (!NT_STATUS_IS_OK(status)) {
4873 return status;
4876 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4878 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4879 status = map_nt_error_from_unix(errno);
4880 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4881 nt_errstr(status), newname, oldname));
4884 return status;
4887 /****************************************************************************
4888 Deal with setting the time from any of the setfilepathinfo functions.
4889 ****************************************************************************/
4891 NTSTATUS smb_set_file_time(connection_struct *conn,
4892 files_struct *fsp,
4893 const char *fname,
4894 const SMB_STRUCT_STAT *psbuf,
4895 struct timespec ts[2],
4896 bool setting_write_time)
4898 uint32 action =
4899 FILE_NOTIFY_CHANGE_LAST_ACCESS
4900 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4902 if (!VALID_STAT(*psbuf)) {
4903 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4906 /* get some defaults (no modifications) if any info is zero or -1. */
4907 if (null_timespec(ts[0])) {
4908 ts[0] = get_atimespec(psbuf);
4909 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4912 if (null_timespec(ts[1])) {
4913 ts[1] = get_mtimespec(psbuf);
4914 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4917 if (!setting_write_time) {
4918 /* ts[1] comes from change time, not write time. */
4919 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4922 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4923 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4926 * Try and set the times of this file if
4927 * they are different from the current values.
4931 struct timespec mts = get_mtimespec(psbuf);
4932 struct timespec ats = get_atimespec(psbuf);
4933 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4934 return NT_STATUS_OK;
4938 if (setting_write_time) {
4940 * This was a setfileinfo on an open file.
4941 * NT does this a lot. We also need to
4942 * set the time here, as it can be read by
4943 * FindFirst/FindNext and with the patch for bug #2045
4944 * in smbd/fileio.c it ensures that this timestamp is
4945 * kept sticky even after a write. We save the request
4946 * away and will set it on file close and after a write. JRA.
4949 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4950 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4952 if (fsp != NULL) {
4953 if (fsp->base_fsp) {
4954 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4955 } else {
4956 set_sticky_write_time_fsp(fsp, ts[1]);
4958 } else {
4959 set_sticky_write_time_path(conn, fname,
4960 vfs_file_id_from_sbuf(conn, psbuf),
4961 ts[1]);
4965 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4967 if (fsp && fsp->base_fsp) {
4968 fname = fsp->base_fsp->fsp_name;
4971 if(file_ntimes(conn, fname, ts)!=0) {
4972 return map_nt_error_from_unix(errno);
4974 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4976 return NT_STATUS_OK;
4979 /****************************************************************************
4980 Deal with setting the dosmode from any of the setfilepathinfo functions.
4981 ****************************************************************************/
4983 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4984 const char *fname,
4985 SMB_STRUCT_STAT *psbuf,
4986 uint32 dosmode)
4988 if (!VALID_STAT(*psbuf)) {
4989 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4992 if (dosmode) {
4993 if (S_ISDIR(psbuf->st_mode)) {
4994 dosmode |= aDIR;
4995 } else {
4996 dosmode &= ~aDIR;
5000 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5002 /* check the mode isn't different, before changing it */
5003 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5005 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5006 fname, (unsigned int)dosmode ));
5008 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5009 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5010 fname, strerror(errno)));
5011 return map_nt_error_from_unix(errno);
5014 return NT_STATUS_OK;
5017 /****************************************************************************
5018 Deal with setting the size from any of the setfilepathinfo functions.
5019 ****************************************************************************/
5021 static NTSTATUS smb_set_file_size(connection_struct *conn,
5022 struct smb_request *req,
5023 files_struct *fsp,
5024 const char *fname,
5025 SMB_STRUCT_STAT *psbuf,
5026 SMB_OFF_T size)
5028 NTSTATUS status = NT_STATUS_OK;
5029 files_struct *new_fsp = NULL;
5031 if (!VALID_STAT(*psbuf)) {
5032 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5035 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5037 if (size == get_file_size(*psbuf)) {
5038 return NT_STATUS_OK;
5041 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5042 fname, (double)size ));
5044 if (fsp && fsp->fh->fd != -1) {
5045 /* Handle based call. */
5046 if (vfs_set_filelen(fsp, size) == -1) {
5047 return map_nt_error_from_unix(errno);
5049 trigger_write_time_update_immediate(fsp);
5050 return NT_STATUS_OK;
5053 status = SMB_VFS_CREATE_FILE(
5054 conn, /* conn */
5055 req, /* req */
5056 0, /* root_dir_fid */
5057 fname, /* fname */
5058 0, /* create_file_flags */
5059 FILE_WRITE_ATTRIBUTES, /* access_mask */
5060 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5061 FILE_SHARE_DELETE),
5062 FILE_OPEN, /* create_disposition*/
5063 0, /* create_options */
5064 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5065 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5066 0, /* allocation_size */
5067 NULL, /* sd */
5068 NULL, /* ea_list */
5069 &new_fsp, /* result */
5070 NULL, /* pinfo */
5071 psbuf); /* psbuf */
5073 if (!NT_STATUS_IS_OK(status)) {
5074 /* NB. We check for open_was_deferred in the caller. */
5075 return status;
5078 if (vfs_set_filelen(new_fsp, size) == -1) {
5079 status = map_nt_error_from_unix(errno);
5080 close_file(req, new_fsp,NORMAL_CLOSE);
5081 return status;
5084 trigger_write_time_update_immediate(new_fsp);
5085 close_file(req, new_fsp,NORMAL_CLOSE);
5086 return NT_STATUS_OK;
5089 /****************************************************************************
5090 Deal with SMB_INFO_SET_EA.
5091 ****************************************************************************/
5093 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5094 const char *pdata,
5095 int total_data,
5096 files_struct *fsp,
5097 const char *fname)
5099 struct ea_list *ea_list = NULL;
5100 TALLOC_CTX *ctx = NULL;
5101 NTSTATUS status = NT_STATUS_OK;
5103 if (total_data < 10) {
5105 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5106 length. They seem to have no effect. Bug #3212. JRA */
5108 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5109 /* We're done. We only get EA info in this call. */
5110 return NT_STATUS_OK;
5113 return NT_STATUS_INVALID_PARAMETER;
5116 if (IVAL(pdata,0) > total_data) {
5117 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5118 IVAL(pdata,0), (unsigned int)total_data));
5119 return NT_STATUS_INVALID_PARAMETER;
5122 ctx = talloc_tos();
5123 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5124 if (!ea_list) {
5125 return NT_STATUS_INVALID_PARAMETER;
5127 status = set_ea(conn, fsp, fname, ea_list);
5129 return status;
5132 /****************************************************************************
5133 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5134 ****************************************************************************/
5136 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5137 const char *pdata,
5138 int total_data,
5139 files_struct *fsp,
5140 const char *fname,
5141 SMB_STRUCT_STAT *psbuf)
5143 NTSTATUS status = NT_STATUS_OK;
5144 bool delete_on_close;
5145 uint32 dosmode = 0;
5147 if (total_data < 1) {
5148 return NT_STATUS_INVALID_PARAMETER;
5151 if (fsp == NULL) {
5152 return NT_STATUS_INVALID_HANDLE;
5155 delete_on_close = (CVAL(pdata,0) ? True : False);
5156 dosmode = dos_mode(conn, fname, psbuf);
5158 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5159 "delete_on_close = %u\n",
5160 fsp->fsp_name,
5161 (unsigned int)dosmode,
5162 (unsigned int)delete_on_close ));
5164 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 return status;
5170 /* The set is across all open files on this dev/inode pair. */
5171 if (!set_delete_on_close(fsp, delete_on_close,
5172 &conn->server_info->utok)) {
5173 return NT_STATUS_ACCESS_DENIED;
5175 return NT_STATUS_OK;
5178 /****************************************************************************
5179 Deal with SMB_FILE_POSITION_INFORMATION.
5180 ****************************************************************************/
5182 static NTSTATUS smb_file_position_information(connection_struct *conn,
5183 const char *pdata,
5184 int total_data,
5185 files_struct *fsp)
5187 uint64_t position_information;
5189 if (total_data < 8) {
5190 return NT_STATUS_INVALID_PARAMETER;
5193 if (fsp == NULL) {
5194 /* Ignore on pathname based set. */
5195 return NT_STATUS_OK;
5198 position_information = (uint64_t)IVAL(pdata,0);
5199 #ifdef LARGE_SMB_OFF_T
5200 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5201 #else /* LARGE_SMB_OFF_T */
5202 if (IVAL(pdata,4) != 0) {
5203 /* more than 32 bits? */
5204 return NT_STATUS_INVALID_PARAMETER;
5206 #endif /* LARGE_SMB_OFF_T */
5208 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5209 fsp->fsp_name, (double)position_information ));
5210 fsp->fh->position_information = position_information;
5211 return NT_STATUS_OK;
5214 /****************************************************************************
5215 Deal with SMB_FILE_MODE_INFORMATION.
5216 ****************************************************************************/
5218 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5219 const char *pdata,
5220 int total_data)
5222 uint32 mode;
5224 if (total_data < 4) {
5225 return NT_STATUS_INVALID_PARAMETER;
5227 mode = IVAL(pdata,0);
5228 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5229 return NT_STATUS_INVALID_PARAMETER;
5231 return NT_STATUS_OK;
5234 /****************************************************************************
5235 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5236 ****************************************************************************/
5238 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5239 struct smb_request *req,
5240 const char *pdata,
5241 int total_data,
5242 const char *fname)
5244 char *link_target = NULL;
5245 const char *newname = fname;
5246 NTSTATUS status = NT_STATUS_OK;
5247 TALLOC_CTX *ctx = talloc_tos();
5249 /* Set a symbolic link. */
5250 /* Don't allow this if follow links is false. */
5252 if (total_data == 0) {
5253 return NT_STATUS_INVALID_PARAMETER;
5256 if (!lp_symlinks(SNUM(conn))) {
5257 return NT_STATUS_ACCESS_DENIED;
5260 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5261 total_data, STR_TERMINATE);
5263 if (!link_target) {
5264 return NT_STATUS_INVALID_PARAMETER;
5267 /* !widelinks forces the target path to be within the share. */
5268 /* This means we can interpret the target as a pathname. */
5269 if (!lp_widelinks(SNUM(conn))) {
5270 char *rel_name = NULL;
5271 char *last_dirp = NULL;
5273 if (*link_target == '/') {
5274 /* No absolute paths allowed. */
5275 return NT_STATUS_ACCESS_DENIED;
5277 rel_name = talloc_strdup(ctx,newname);
5278 if (!rel_name) {
5279 return NT_STATUS_NO_MEMORY;
5281 last_dirp = strrchr_m(rel_name, '/');
5282 if (last_dirp) {
5283 last_dirp[1] = '\0';
5284 } else {
5285 rel_name = talloc_strdup(ctx,"./");
5286 if (!rel_name) {
5287 return NT_STATUS_NO_MEMORY;
5290 rel_name = talloc_asprintf_append(rel_name,
5291 "%s",
5292 link_target);
5293 if (!rel_name) {
5294 return NT_STATUS_NO_MEMORY;
5297 status = check_name(conn, rel_name);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 return status;
5303 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5304 newname, link_target ));
5306 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5307 return map_nt_error_from_unix(errno);
5310 return NT_STATUS_OK;
5313 /****************************************************************************
5314 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5315 ****************************************************************************/
5317 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5318 struct smb_request *req,
5319 const char *pdata, int total_data,
5320 const char *fname)
5322 char *oldname = NULL;
5323 TALLOC_CTX *ctx = talloc_tos();
5324 NTSTATUS status = NT_STATUS_OK;
5326 /* Set a hard link. */
5327 if (total_data == 0) {
5328 return NT_STATUS_INVALID_PARAMETER;
5331 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5332 total_data, STR_TERMINATE, &status);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 return status;
5337 status = resolve_dfspath(ctx, conn,
5338 req->flags2 & FLAGS2_DFS_PATHNAMES,
5339 oldname,
5340 &oldname);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 return status;
5345 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5346 fname, oldname));
5348 return hardlink_internals(ctx, conn, oldname, fname);
5351 /****************************************************************************
5352 Deal with SMB_FILE_RENAME_INFORMATION.
5353 ****************************************************************************/
5355 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5356 struct smb_request *req,
5357 const char *pdata,
5358 int total_data,
5359 files_struct *fsp,
5360 const char *fname)
5362 bool overwrite;
5363 uint32 root_fid;
5364 uint32 len;
5365 char *newname = NULL;
5366 char *base_name = NULL;
5367 bool dest_has_wcard = False;
5368 SMB_STRUCT_STAT sbuf;
5369 char *newname_last_component = NULL;
5370 NTSTATUS status = NT_STATUS_OK;
5371 char *p;
5372 TALLOC_CTX *ctx = talloc_tos();
5374 if (total_data < 13) {
5375 return NT_STATUS_INVALID_PARAMETER;
5378 ZERO_STRUCT(sbuf);
5380 overwrite = (CVAL(pdata,0) ? True : False);
5381 root_fid = IVAL(pdata,4);
5382 len = IVAL(pdata,8);
5384 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5385 return NT_STATUS_INVALID_PARAMETER;
5388 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5389 len, 0, &status,
5390 &dest_has_wcard);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 return status;
5395 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5396 newname));
5398 status = resolve_dfspath_wcard(ctx, conn,
5399 req->flags2 & FLAGS2_DFS_PATHNAMES,
5400 newname,
5401 &newname,
5402 &dest_has_wcard);
5403 if (!NT_STATUS_IS_OK(status)) {
5404 return status;
5407 /* Check the new name has no '/' characters. */
5408 if (strchr_m(newname, '/')) {
5409 return NT_STATUS_NOT_SUPPORTED;
5412 if (fsp && fsp->base_fsp) {
5413 /* newname must be a stream name. */
5414 if (newname[0] != ':') {
5415 return NT_STATUS_NOT_SUPPORTED;
5417 base_name = talloc_asprintf(ctx, "%s%s",
5418 fsp->base_fsp->fsp_name,
5419 newname);
5420 if (!base_name) {
5421 return NT_STATUS_NO_MEMORY;
5423 } else {
5424 /* newname must *not* be a stream name. */
5425 if (is_ntfs_stream_name(newname)) {
5426 return NT_STATUS_NOT_SUPPORTED;
5429 /* Create the base directory. */
5430 base_name = talloc_strdup(ctx, fname);
5431 if (!base_name) {
5432 return NT_STATUS_NO_MEMORY;
5434 p = strrchr_m(base_name, '/');
5435 if (p) {
5436 p[1] = '\0';
5437 } else {
5438 base_name = talloc_strdup(ctx, "./");
5439 if (!base_name) {
5440 return NT_STATUS_NO_MEMORY;
5443 /* Append the new name. */
5444 base_name = talloc_asprintf_append(base_name,
5445 "%s",
5446 newname);
5447 if (!base_name) {
5448 return NT_STATUS_NO_MEMORY;
5451 status = unix_convert(ctx, conn, newname, False,
5452 &newname,
5453 &newname_last_component,
5454 &sbuf);
5456 /* If an error we expect this to be
5457 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5459 if (!NT_STATUS_IS_OK(status)
5460 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5461 status)) {
5462 return status;
5466 if (fsp) {
5467 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5468 fsp->fnum, fsp->fsp_name, base_name ));
5469 status = rename_internals_fsp(conn, fsp, base_name,
5470 newname_last_component, 0,
5471 overwrite);
5472 } else {
5473 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5474 fname, base_name ));
5475 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5476 overwrite, False, dest_has_wcard,
5477 FILE_WRITE_ATTRIBUTES);
5480 return status;
5483 /****************************************************************************
5484 Deal with SMB_SET_POSIX_ACL.
5485 ****************************************************************************/
5487 #if defined(HAVE_POSIX_ACLS)
5488 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5489 const char *pdata,
5490 int total_data,
5491 files_struct *fsp,
5492 const char *fname,
5493 SMB_STRUCT_STAT *psbuf)
5495 uint16 posix_acl_version;
5496 uint16 num_file_acls;
5497 uint16 num_def_acls;
5498 bool valid_file_acls = True;
5499 bool valid_def_acls = True;
5501 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5502 return NT_STATUS_INVALID_PARAMETER;
5504 posix_acl_version = SVAL(pdata,0);
5505 num_file_acls = SVAL(pdata,2);
5506 num_def_acls = SVAL(pdata,4);
5508 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5509 valid_file_acls = False;
5510 num_file_acls = 0;
5513 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5514 valid_def_acls = False;
5515 num_def_acls = 0;
5518 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5519 return NT_STATUS_INVALID_PARAMETER;
5522 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5523 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5524 return NT_STATUS_INVALID_PARAMETER;
5527 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5528 fname ? fname : fsp->fsp_name,
5529 (unsigned int)num_file_acls,
5530 (unsigned int)num_def_acls));
5532 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5533 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5534 return map_nt_error_from_unix(errno);
5537 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5538 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5539 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5540 return map_nt_error_from_unix(errno);
5542 return NT_STATUS_OK;
5544 #endif
5546 /****************************************************************************
5547 Deal with SMB_SET_POSIX_LOCK.
5548 ****************************************************************************/
5550 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5551 struct smb_request *req,
5552 const char *pdata,
5553 int total_data,
5554 files_struct *fsp)
5556 uint64_t count;
5557 uint64_t offset;
5558 uint32 lock_pid;
5559 bool blocking_lock = False;
5560 enum brl_type lock_type;
5562 NTSTATUS status = NT_STATUS_OK;
5564 if (fsp == NULL || fsp->fh->fd == -1) {
5565 return NT_STATUS_INVALID_HANDLE;
5568 if (total_data != POSIX_LOCK_DATA_SIZE) {
5569 return NT_STATUS_INVALID_PARAMETER;
5572 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5573 case POSIX_LOCK_TYPE_READ:
5574 lock_type = READ_LOCK;
5575 break;
5576 case POSIX_LOCK_TYPE_WRITE:
5577 /* Return the right POSIX-mappable error code for files opened read-only. */
5578 if (!fsp->can_write) {
5579 return NT_STATUS_INVALID_HANDLE;
5581 lock_type = WRITE_LOCK;
5582 break;
5583 case POSIX_LOCK_TYPE_UNLOCK:
5584 lock_type = UNLOCK_LOCK;
5585 break;
5586 default:
5587 return NT_STATUS_INVALID_PARAMETER;
5590 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5591 blocking_lock = False;
5592 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5593 blocking_lock = True;
5594 } else {
5595 return NT_STATUS_INVALID_PARAMETER;
5598 if (!lp_blocking_locks(SNUM(conn))) {
5599 blocking_lock = False;
5602 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5603 #if defined(HAVE_LONGLONG)
5604 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5605 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5606 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5607 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5608 #else /* HAVE_LONGLONG */
5609 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5610 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5611 #endif /* HAVE_LONGLONG */
5613 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5614 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5615 fsp->fsp_name,
5616 (unsigned int)lock_type,
5617 (unsigned int)lock_pid,
5618 (double)count,
5619 (double)offset ));
5621 if (lock_type == UNLOCK_LOCK) {
5622 status = do_unlock(smbd_messaging_context(),
5623 fsp,
5624 lock_pid,
5625 count,
5626 offset,
5627 POSIX_LOCK);
5628 } else {
5629 uint32 block_smbpid;
5631 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5632 fsp,
5633 lock_pid,
5634 count,
5635 offset,
5636 lock_type,
5637 POSIX_LOCK,
5638 blocking_lock,
5639 &status,
5640 &block_smbpid);
5642 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5644 * A blocking lock was requested. Package up
5645 * this smb into a queued request and push it
5646 * onto the blocking lock queue.
5648 if(push_blocking_lock_request(br_lck,
5649 req,
5650 fsp,
5651 -1, /* infinite timeout. */
5653 lock_pid,
5654 lock_type,
5655 POSIX_LOCK,
5656 offset,
5657 count,
5658 block_smbpid)) {
5659 TALLOC_FREE(br_lck);
5660 return status;
5663 TALLOC_FREE(br_lck);
5666 return status;
5669 /****************************************************************************
5670 Deal with SMB_INFO_STANDARD.
5671 ****************************************************************************/
5673 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5674 const char *pdata,
5675 int total_data,
5676 files_struct *fsp,
5677 const char *fname,
5678 const SMB_STRUCT_STAT *psbuf)
5680 struct timespec ts[2];
5682 if (total_data < 12) {
5683 return NT_STATUS_INVALID_PARAMETER;
5686 /* access time */
5687 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5688 /* write time */
5689 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5691 DEBUG(10,("smb_set_info_standard: file %s\n",
5692 fname ? fname : fsp->fsp_name ));
5694 return smb_set_file_time(conn,
5695 fsp,
5696 fname,
5697 psbuf,
5699 true);
5702 /****************************************************************************
5703 Deal with SMB_SET_FILE_BASIC_INFO.
5704 ****************************************************************************/
5706 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5707 const char *pdata,
5708 int total_data,
5709 files_struct *fsp,
5710 const char *fname,
5711 SMB_STRUCT_STAT *psbuf)
5713 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5714 struct timespec write_time;
5715 struct timespec changed_time;
5716 uint32 dosmode = 0;
5717 struct timespec ts[2];
5718 NTSTATUS status = NT_STATUS_OK;
5719 bool setting_write_time = true;
5721 if (total_data < 36) {
5722 return NT_STATUS_INVALID_PARAMETER;
5725 /* Set the attributes */
5726 dosmode = IVAL(pdata,32);
5727 status = smb_set_file_dosmode(conn,
5728 fname,
5729 psbuf,
5730 dosmode);
5731 if (!NT_STATUS_IS_OK(status)) {
5732 return status;
5735 /* Ignore create time at offset pdata. */
5737 /* access time */
5738 ts[0] = interpret_long_date(pdata+8);
5740 write_time = interpret_long_date(pdata+16);
5741 changed_time = interpret_long_date(pdata+24);
5743 /* mtime */
5744 ts[1] = timespec_min(&write_time, &changed_time);
5746 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5747 ts[1] = write_time;
5750 /* Prefer a defined time to an undefined one. */
5751 if (null_timespec(ts[1])) {
5752 if (null_timespec(write_time)) {
5753 ts[1] = changed_time;
5754 setting_write_time = false;
5755 } else {
5756 ts[1] = write_time;
5760 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5761 fname ? fname : fsp->fsp_name ));
5763 return smb_set_file_time(conn,
5764 fsp,
5765 fname,
5766 psbuf,
5768 setting_write_time);
5771 /****************************************************************************
5772 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5773 ****************************************************************************/
5775 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5776 struct smb_request *req,
5777 const char *pdata,
5778 int total_data,
5779 files_struct *fsp,
5780 const char *fname,
5781 SMB_STRUCT_STAT *psbuf)
5783 uint64_t allocation_size = 0;
5784 NTSTATUS status = NT_STATUS_OK;
5785 files_struct *new_fsp = NULL;
5787 if (!VALID_STAT(*psbuf)) {
5788 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5791 if (total_data < 8) {
5792 return NT_STATUS_INVALID_PARAMETER;
5795 allocation_size = (uint64_t)IVAL(pdata,0);
5796 #ifdef LARGE_SMB_OFF_T
5797 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5798 #else /* LARGE_SMB_OFF_T */
5799 if (IVAL(pdata,4) != 0) {
5800 /* more than 32 bits? */
5801 return NT_STATUS_INVALID_PARAMETER;
5803 #endif /* LARGE_SMB_OFF_T */
5805 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5806 fname, (double)allocation_size ));
5808 if (allocation_size) {
5809 allocation_size = smb_roundup(conn, allocation_size);
5812 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5813 fname, (double)allocation_size ));
5815 if (fsp && fsp->fh->fd != -1) {
5816 /* Open file handle. */
5817 /* Only change if needed. */
5818 if (allocation_size != get_file_size(*psbuf)) {
5819 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5820 return map_nt_error_from_unix(errno);
5823 /* But always update the time. */
5825 * This is equivalent to a write. Ensure it's seen immediately
5826 * if there are no pending writes.
5828 trigger_write_time_update_immediate(fsp);
5829 return NT_STATUS_OK;
5832 /* Pathname or stat or directory file. */
5834 status = SMB_VFS_CREATE_FILE(
5835 conn, /* conn */
5836 req, /* req */
5837 0, /* root_dir_fid */
5838 fname, /* fname */
5839 0, /* create_file_flags */
5840 FILE_WRITE_DATA, /* access_mask */
5841 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5842 FILE_SHARE_DELETE),
5843 FILE_OPEN, /* create_disposition*/
5844 0, /* create_options */
5845 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5846 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5847 0, /* allocation_size */
5848 NULL, /* sd */
5849 NULL, /* ea_list */
5850 &new_fsp, /* result */
5851 NULL, /* pinfo */
5852 psbuf); /* psbuf */
5854 if (!NT_STATUS_IS_OK(status)) {
5855 /* NB. We check for open_was_deferred in the caller. */
5856 return status;
5859 /* Only change if needed. */
5860 if (allocation_size != get_file_size(*psbuf)) {
5861 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5862 status = map_nt_error_from_unix(errno);
5863 close_file(req, new_fsp, NORMAL_CLOSE);
5864 return status;
5868 /* Changing the allocation size should set the last mod time. */
5870 * This is equivalent to a write. Ensure it's seen immediately
5871 * if there are no pending writes.
5873 trigger_write_time_update_immediate(new_fsp);
5875 close_file(req, new_fsp, NORMAL_CLOSE);
5876 return NT_STATUS_OK;
5879 /****************************************************************************
5880 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5881 ****************************************************************************/
5883 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5884 struct smb_request *req,
5885 const char *pdata,
5886 int total_data,
5887 files_struct *fsp,
5888 const char *fname,
5889 SMB_STRUCT_STAT *psbuf)
5891 SMB_OFF_T size;
5893 if (total_data < 8) {
5894 return NT_STATUS_INVALID_PARAMETER;
5897 size = IVAL(pdata,0);
5898 #ifdef LARGE_SMB_OFF_T
5899 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5900 #else /* LARGE_SMB_OFF_T */
5901 if (IVAL(pdata,4) != 0) {
5902 /* more than 32 bits? */
5903 return NT_STATUS_INVALID_PARAMETER;
5905 #endif /* LARGE_SMB_OFF_T */
5906 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5907 "file %s to %.0f\n", fname, (double)size ));
5909 return smb_set_file_size(conn, req,
5910 fsp,
5911 fname,
5912 psbuf,
5913 size);
5916 /****************************************************************************
5917 Allow a UNIX info mknod.
5918 ****************************************************************************/
5920 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5921 const char *pdata,
5922 int total_data,
5923 const char *fname,
5924 SMB_STRUCT_STAT *psbuf)
5926 uint32 file_type = IVAL(pdata,56);
5927 #if defined(HAVE_MAKEDEV)
5928 uint32 dev_major = IVAL(pdata,60);
5929 uint32 dev_minor = IVAL(pdata,68);
5930 #endif
5931 SMB_DEV_T dev = (SMB_DEV_T)0;
5932 uint32 raw_unixmode = IVAL(pdata,84);
5933 NTSTATUS status;
5934 mode_t unixmode;
5936 if (total_data < 100) {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5941 if (!NT_STATUS_IS_OK(status)) {
5942 return status;
5945 #if defined(HAVE_MAKEDEV)
5946 dev = makedev(dev_major, dev_minor);
5947 #endif
5949 switch (file_type) {
5950 #if defined(S_IFIFO)
5951 case UNIX_TYPE_FIFO:
5952 unixmode |= S_IFIFO;
5953 break;
5954 #endif
5955 #if defined(S_IFSOCK)
5956 case UNIX_TYPE_SOCKET:
5957 unixmode |= S_IFSOCK;
5958 break;
5959 #endif
5960 #if defined(S_IFCHR)
5961 case UNIX_TYPE_CHARDEV:
5962 unixmode |= S_IFCHR;
5963 break;
5964 #endif
5965 #if defined(S_IFBLK)
5966 case UNIX_TYPE_BLKDEV:
5967 unixmode |= S_IFBLK;
5968 break;
5969 #endif
5970 default:
5971 return NT_STATUS_INVALID_PARAMETER;
5974 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5975 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5977 /* Ok - do the mknod. */
5978 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5979 return map_nt_error_from_unix(errno);
5982 /* If any of the other "set" calls fail we
5983 * don't want to end up with a half-constructed mknod.
5986 if (lp_inherit_perms(SNUM(conn))) {
5987 char *parent;
5988 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5989 return NT_STATUS_NO_MEMORY;
5991 inherit_access_posix_acl(conn, parent, fname, unixmode);
5992 TALLOC_FREE(parent);
5995 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5996 status = map_nt_error_from_unix(errno);
5997 SMB_VFS_UNLINK(conn,fname);
5998 return status;
6000 return NT_STATUS_OK;
6003 /****************************************************************************
6004 Deal with SMB_SET_FILE_UNIX_BASIC.
6005 ****************************************************************************/
6007 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6008 struct smb_request *req,
6009 const char *pdata,
6010 int total_data,
6011 files_struct *fsp,
6012 const char *fname,
6013 SMB_STRUCT_STAT *psbuf)
6015 struct timespec ts[2];
6016 uint32 raw_unixmode;
6017 mode_t unixmode;
6018 SMB_OFF_T size = 0;
6019 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6020 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6021 NTSTATUS status = NT_STATUS_OK;
6022 bool delete_on_fail = False;
6023 enum perm_type ptype;
6025 if (total_data < 100) {
6026 return NT_STATUS_INVALID_PARAMETER;
6029 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6030 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6031 size=IVAL(pdata,0); /* first 8 Bytes are size */
6032 #ifdef LARGE_SMB_OFF_T
6033 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6034 #else /* LARGE_SMB_OFF_T */
6035 if (IVAL(pdata,4) != 0) {
6036 /* more than 32 bits? */
6037 return NT_STATUS_INVALID_PARAMETER;
6039 #endif /* LARGE_SMB_OFF_T */
6042 ts[0] = interpret_long_date(pdata+24); /* access_time */
6043 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6044 set_owner = (uid_t)IVAL(pdata,40);
6045 set_grp = (gid_t)IVAL(pdata,48);
6046 raw_unixmode = IVAL(pdata,84);
6048 if (VALID_STAT(*psbuf)) {
6049 if (S_ISDIR(psbuf->st_mode)) {
6050 ptype = PERM_EXISTING_DIR;
6051 } else {
6052 ptype = PERM_EXISTING_FILE;
6054 } else {
6055 ptype = PERM_NEW_FILE;
6058 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 return status;
6063 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6064 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6065 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6067 if (!VALID_STAT(*psbuf)) {
6069 * The only valid use of this is to create character and block
6070 * devices, and named pipes. This is deprecated (IMHO) and
6071 * a new info level should be used for mknod. JRA.
6074 status = smb_unix_mknod(conn,
6075 pdata,
6076 total_data,
6077 fname,
6078 psbuf);
6079 if (!NT_STATUS_IS_OK(status)) {
6080 return status;
6083 /* Ensure we don't try and change anything else. */
6084 raw_unixmode = SMB_MODE_NO_CHANGE;
6085 size = get_file_size(*psbuf);
6086 ts[0] = get_atimespec(psbuf);
6087 ts[1] = get_mtimespec(psbuf);
6089 * We continue here as we might want to change the
6090 * owner uid/gid.
6092 delete_on_fail = True;
6095 #if 1
6096 /* Horrible backwards compatibility hack as an old server bug
6097 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6098 * */
6100 if (!size) {
6101 size = get_file_size(*psbuf);
6103 #endif
6106 * Deal with the UNIX specific mode set.
6109 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6110 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6111 (unsigned int)unixmode, fname ));
6112 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6113 return map_nt_error_from_unix(errno);
6118 * Deal with the UNIX specific uid set.
6121 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6122 int ret;
6124 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6125 (unsigned int)set_owner, fname ));
6127 if (S_ISLNK(psbuf->st_mode)) {
6128 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6129 } else {
6130 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6133 if (ret != 0) {
6134 status = map_nt_error_from_unix(errno);
6135 if (delete_on_fail) {
6136 SMB_VFS_UNLINK(conn,fname);
6138 return status;
6143 * Deal with the UNIX specific gid set.
6146 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6147 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6148 (unsigned int)set_owner, fname ));
6149 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6150 status = map_nt_error_from_unix(errno);
6151 if (delete_on_fail) {
6152 SMB_VFS_UNLINK(conn,fname);
6154 return status;
6158 /* Deal with any size changes. */
6160 status = smb_set_file_size(conn, req,
6161 fsp,
6162 fname,
6163 psbuf,
6164 size);
6165 if (!NT_STATUS_IS_OK(status)) {
6166 return status;
6169 /* Deal with any time changes. */
6171 return smb_set_file_time(conn,
6172 fsp,
6173 fname,
6174 psbuf,
6176 true);
6179 /****************************************************************************
6180 Deal with SMB_SET_FILE_UNIX_INFO2.
6181 ****************************************************************************/
6183 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6184 struct smb_request *req,
6185 const char *pdata,
6186 int total_data,
6187 files_struct *fsp,
6188 const char *fname,
6189 SMB_STRUCT_STAT *psbuf)
6191 NTSTATUS status;
6192 uint32 smb_fflags;
6193 uint32 smb_fmask;
6195 if (total_data < 116) {
6196 return NT_STATUS_INVALID_PARAMETER;
6199 /* Start by setting all the fields that are common between UNIX_BASIC
6200 * and UNIX_INFO2.
6202 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6203 fsp, fname, psbuf);
6204 if (!NT_STATUS_IS_OK(status)) {
6205 return status;
6208 smb_fflags = IVAL(pdata, 108);
6209 smb_fmask = IVAL(pdata, 112);
6211 /* NB: We should only attempt to alter the file flags if the client
6212 * sends a non-zero mask.
6214 if (smb_fmask != 0) {
6215 int stat_fflags = 0;
6217 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6218 &stat_fflags)) {
6219 /* Client asked to alter a flag we don't understand. */
6220 return NT_STATUS_INVALID_PARAMETER;
6223 if (fsp && fsp->fh->fd != -1) {
6224 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6225 return NT_STATUS_NOT_SUPPORTED;
6226 } else {
6227 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6228 return map_nt_error_from_unix(errno);
6233 /* XXX: need to add support for changing the create_time here. You
6234 * can do this for paths on Darwin with setattrlist(2). The right way
6235 * to hook this up is probably by extending the VFS utimes interface.
6238 return NT_STATUS_OK;
6241 /****************************************************************************
6242 Create a directory with POSIX semantics.
6243 ****************************************************************************/
6245 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6246 struct smb_request *req,
6247 char **ppdata,
6248 int total_data,
6249 const char *fname,
6250 SMB_STRUCT_STAT *psbuf,
6251 int *pdata_return_size)
6253 NTSTATUS status = NT_STATUS_OK;
6254 uint32 raw_unixmode = 0;
6255 uint32 mod_unixmode = 0;
6256 mode_t unixmode = (mode_t)0;
6257 files_struct *fsp = NULL;
6258 uint16 info_level_return = 0;
6259 int info;
6260 char *pdata = *ppdata;
6262 if (total_data < 18) {
6263 return NT_STATUS_INVALID_PARAMETER;
6266 raw_unixmode = IVAL(pdata,8);
6267 /* Next 4 bytes are not yet defined. */
6269 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6270 if (!NT_STATUS_IS_OK(status)) {
6271 return status;
6274 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6276 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6277 fname, (unsigned int)unixmode ));
6279 status = SMB_VFS_CREATE_FILE(
6280 conn, /* conn */
6281 req, /* req */
6282 0, /* root_dir_fid */
6283 fname, /* fname */
6284 0, /* create_file_flags */
6285 FILE_READ_ATTRIBUTES, /* access_mask */
6286 FILE_SHARE_NONE, /* share_access */
6287 FILE_CREATE, /* create_disposition*/
6288 FILE_DIRECTORY_FILE, /* create_options */
6289 mod_unixmode, /* file_attributes */
6290 0, /* oplock_request */
6291 0, /* allocation_size */
6292 NULL, /* sd */
6293 NULL, /* ea_list */
6294 &fsp, /* result */
6295 &info, /* pinfo */
6296 psbuf); /* psbuf */
6298 if (NT_STATUS_IS_OK(status)) {
6299 close_file(req, fsp, NORMAL_CLOSE);
6302 info_level_return = SVAL(pdata,16);
6304 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6305 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6306 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6307 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6308 } else {
6309 *pdata_return_size = 12;
6312 /* Realloc the data size */
6313 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6314 if (*ppdata == NULL) {
6315 *pdata_return_size = 0;
6316 return NT_STATUS_NO_MEMORY;
6318 pdata = *ppdata;
6320 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6321 SSVAL(pdata,2,0); /* No fnum. */
6322 SIVAL(pdata,4,info); /* Was directory created. */
6324 switch (info_level_return) {
6325 case SMB_QUERY_FILE_UNIX_BASIC:
6326 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6327 SSVAL(pdata,10,0); /* Padding. */
6328 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6329 break;
6330 case SMB_QUERY_FILE_UNIX_INFO2:
6331 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6332 SSVAL(pdata,10,0); /* Padding. */
6333 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6334 break;
6335 default:
6336 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6337 SSVAL(pdata,10,0); /* Padding. */
6338 break;
6341 return status;
6344 /****************************************************************************
6345 Open/Create a file with POSIX semantics.
6346 ****************************************************************************/
6348 static NTSTATUS smb_posix_open(connection_struct *conn,
6349 struct smb_request *req,
6350 char **ppdata,
6351 int total_data,
6352 const char *fname,
6353 SMB_STRUCT_STAT *psbuf,
6354 int *pdata_return_size)
6356 bool extended_oplock_granted = False;
6357 char *pdata = *ppdata;
6358 uint32 flags = 0;
6359 uint32 wire_open_mode = 0;
6360 uint32 raw_unixmode = 0;
6361 uint32 mod_unixmode = 0;
6362 uint32 create_disp = 0;
6363 uint32 access_mask = 0;
6364 uint32 create_options = 0;
6365 NTSTATUS status = NT_STATUS_OK;
6366 mode_t unixmode = (mode_t)0;
6367 files_struct *fsp = NULL;
6368 int oplock_request = 0;
6369 int info = 0;
6370 uint16 info_level_return = 0;
6372 if (total_data < 18) {
6373 return NT_STATUS_INVALID_PARAMETER;
6376 flags = IVAL(pdata,0);
6377 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6378 if (oplock_request) {
6379 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6382 wire_open_mode = IVAL(pdata,4);
6384 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6385 return smb_posix_mkdir(conn, req,
6386 ppdata,
6387 total_data,
6388 fname,
6389 psbuf,
6390 pdata_return_size);
6393 switch (wire_open_mode & SMB_ACCMODE) {
6394 case SMB_O_RDONLY:
6395 access_mask = FILE_READ_DATA;
6396 break;
6397 case SMB_O_WRONLY:
6398 access_mask = FILE_WRITE_DATA;
6399 break;
6400 case SMB_O_RDWR:
6401 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6402 break;
6403 default:
6404 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6405 (unsigned int)wire_open_mode ));
6406 return NT_STATUS_INVALID_PARAMETER;
6409 wire_open_mode &= ~SMB_ACCMODE;
6411 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6412 create_disp = FILE_CREATE;
6413 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6414 create_disp = FILE_OVERWRITE_IF;
6415 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6416 create_disp = FILE_OPEN_IF;
6417 } else {
6418 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6419 (unsigned int)wire_open_mode ));
6420 return NT_STATUS_INVALID_PARAMETER;
6423 raw_unixmode = IVAL(pdata,8);
6424 /* Next 4 bytes are not yet defined. */
6426 status = unix_perms_from_wire(conn,
6427 psbuf,
6428 raw_unixmode,
6429 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6430 &unixmode);
6432 if (!NT_STATUS_IS_OK(status)) {
6433 return status;
6436 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6438 if (wire_open_mode & SMB_O_SYNC) {
6439 create_options |= FILE_WRITE_THROUGH;
6441 if (wire_open_mode & SMB_O_APPEND) {
6442 access_mask |= FILE_APPEND_DATA;
6444 if (wire_open_mode & SMB_O_DIRECT) {
6445 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6448 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6449 fname,
6450 (unsigned int)wire_open_mode,
6451 (unsigned int)unixmode ));
6453 status = SMB_VFS_CREATE_FILE(
6454 conn, /* conn */
6455 req, /* req */
6456 0, /* root_dir_fid */
6457 fname, /* fname */
6458 0, /* create_file_flags */
6459 access_mask, /* access_mask */
6460 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6461 FILE_SHARE_DELETE),
6462 create_disp, /* create_disposition*/
6463 0, /* create_options */
6464 mod_unixmode, /* file_attributes */
6465 oplock_request, /* oplock_request */
6466 0, /* allocation_size */
6467 NULL, /* sd */
6468 NULL, /* ea_list */
6469 &fsp, /* result */
6470 &info, /* pinfo */
6471 psbuf); /* psbuf */
6473 if (!NT_STATUS_IS_OK(status)) {
6474 return status;
6477 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6478 extended_oplock_granted = True;
6481 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6482 extended_oplock_granted = True;
6485 info_level_return = SVAL(pdata,16);
6487 /* Allocate the correct return size. */
6489 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6490 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6491 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6492 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6493 } else {
6494 *pdata_return_size = 12;
6497 /* Realloc the data size */
6498 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6499 if (*ppdata == NULL) {
6500 close_file(req, fsp, ERROR_CLOSE);
6501 *pdata_return_size = 0;
6502 return NT_STATUS_NO_MEMORY;
6504 pdata = *ppdata;
6506 if (extended_oplock_granted) {
6507 if (flags & REQUEST_BATCH_OPLOCK) {
6508 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6509 } else {
6510 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6512 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6513 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6514 } else {
6515 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6518 SSVAL(pdata,2,fsp->fnum);
6519 SIVAL(pdata,4,info); /* Was file created etc. */
6521 switch (info_level_return) {
6522 case SMB_QUERY_FILE_UNIX_BASIC:
6523 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6524 SSVAL(pdata,10,0); /* padding. */
6525 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6526 break;
6527 case SMB_QUERY_FILE_UNIX_INFO2:
6528 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6529 SSVAL(pdata,10,0); /* padding. */
6530 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6531 break;
6532 default:
6533 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6534 SSVAL(pdata,10,0); /* padding. */
6535 break;
6537 return NT_STATUS_OK;
6540 /****************************************************************************
6541 Delete a file with POSIX semantics.
6542 ****************************************************************************/
6544 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6545 struct smb_request *req,
6546 const char *pdata,
6547 int total_data,
6548 const char *fname,
6549 SMB_STRUCT_STAT *psbuf)
6551 NTSTATUS status = NT_STATUS_OK;
6552 files_struct *fsp = NULL;
6553 uint16 flags = 0;
6554 char del = 1;
6555 int info = 0;
6556 int create_options = 0;
6557 int i;
6558 struct share_mode_lock *lck = NULL;
6560 if (total_data < 2) {
6561 return NT_STATUS_INVALID_PARAMETER;
6564 flags = SVAL(pdata,0);
6566 if (!VALID_STAT(*psbuf)) {
6567 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6570 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6571 !VALID_STAT_OF_DIR(*psbuf)) {
6572 return NT_STATUS_NOT_A_DIRECTORY;
6575 DEBUG(10,("smb_posix_unlink: %s %s\n",
6576 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6577 fname));
6579 if (VALID_STAT_OF_DIR(*psbuf)) {
6580 create_options |= FILE_DIRECTORY_FILE;
6583 status = SMB_VFS_CREATE_FILE(
6584 conn, /* conn */
6585 req, /* req */
6586 0, /* root_dir_fid */
6587 fname, /* fname */
6588 0, /* create_file_flags */
6589 DELETE_ACCESS, /* access_mask */
6590 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6591 FILE_SHARE_DELETE),
6592 FILE_OPEN, /* create_disposition*/
6593 create_options, /* create_options */
6594 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6595 0, /* oplock_request */
6596 0, /* allocation_size */
6597 NULL, /* sd */
6598 NULL, /* ea_list */
6599 &fsp, /* result */
6600 &info, /* pinfo */
6601 psbuf); /* psbuf */
6603 if (!NT_STATUS_IS_OK(status)) {
6604 return status;
6608 * Don't lie to client. If we can't really delete due to
6609 * non-POSIX opens return SHARING_VIOLATION.
6612 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6613 NULL);
6614 if (lck == NULL) {
6615 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6616 "lock for file %s\n", fsp->fsp_name));
6617 close_file(req, fsp, NORMAL_CLOSE);
6618 return NT_STATUS_INVALID_PARAMETER;
6622 * See if others still have the file open. If this is the case, then
6623 * don't delete. If all opens are POSIX delete we can set the delete
6624 * on close disposition.
6626 for (i=0; i<lck->num_share_modes; i++) {
6627 struct share_mode_entry *e = &lck->share_modes[i];
6628 if (is_valid_share_mode_entry(e)) {
6629 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6630 continue;
6632 /* Fail with sharing violation. */
6633 close_file(req, fsp, NORMAL_CLOSE);
6634 TALLOC_FREE(lck);
6635 return NT_STATUS_SHARING_VIOLATION;
6640 * Set the delete on close.
6642 status = smb_set_file_disposition_info(conn,
6643 &del,
6645 fsp,
6646 fname,
6647 psbuf);
6649 if (!NT_STATUS_IS_OK(status)) {
6650 close_file(req, fsp, NORMAL_CLOSE);
6651 TALLOC_FREE(lck);
6652 return status;
6654 TALLOC_FREE(lck);
6655 return close_file(req, fsp, NORMAL_CLOSE);
6658 /****************************************************************************
6659 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6660 ****************************************************************************/
6662 static void call_trans2setfilepathinfo(connection_struct *conn,
6663 struct smb_request *req,
6664 unsigned int tran_call,
6665 char **pparams, int total_params,
6666 char **ppdata, int total_data,
6667 unsigned int max_data_bytes)
6669 char *params = *pparams;
6670 char *pdata = *ppdata;
6671 uint16 info_level;
6672 SMB_STRUCT_STAT sbuf;
6673 char *fname = NULL;
6674 files_struct *fsp = NULL;
6675 NTSTATUS status = NT_STATUS_OK;
6676 int data_return_size = 0;
6677 TALLOC_CTX *ctx = talloc_tos();
6679 if (!params) {
6680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6681 return;
6684 ZERO_STRUCT(sbuf);
6686 if (tran_call == TRANSACT2_SETFILEINFO) {
6687 if (total_params < 4) {
6688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6689 return;
6692 fsp = file_fsp(req, SVAL(params,0));
6693 /* Basic check for non-null fsp. */
6694 if (!check_fsp_open(conn, req, fsp)) {
6695 return;
6697 info_level = SVAL(params,2);
6699 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6700 if (!fname) {
6701 reply_nterror(req, NT_STATUS_NO_MEMORY);
6702 return;
6705 if(fsp->is_directory || fsp->fh->fd == -1) {
6707 * This is actually a SETFILEINFO on a directory
6708 * handle (returned from an NT SMB). NT5.0 seems
6709 * to do this call. JRA.
6711 if (INFO_LEVEL_IS_UNIX(info_level)) {
6712 /* Always do lstat for UNIX calls. */
6713 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6714 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6715 reply_unixerror(req,ERRDOS,ERRbadpath);
6716 return;
6718 } else {
6719 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6720 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6721 reply_unixerror(req,ERRDOS,ERRbadpath);
6722 return;
6725 } else if (fsp->print_file) {
6727 * Doing a DELETE_ON_CLOSE should cancel a print job.
6729 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6730 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6732 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6734 SSVAL(params,0,0);
6735 send_trans2_replies(conn, req, params, 2,
6736 *ppdata, 0,
6737 max_data_bytes);
6738 return;
6739 } else {
6740 reply_unixerror(req, ERRDOS, ERRbadpath);
6741 return;
6743 } else {
6745 * Original code - this is an open file.
6747 if (!check_fsp(conn, req, fsp)) {
6748 return;
6751 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6752 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6753 reply_unixerror(req, ERRDOS, ERRbadfid);
6754 return;
6757 } else {
6758 /* set path info */
6759 if (total_params < 7) {
6760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6761 return;
6764 info_level = SVAL(params,0);
6765 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6766 total_params - 6, STR_TERMINATE,
6767 &status);
6768 if (!NT_STATUS_IS_OK(status)) {
6769 reply_nterror(req, status);
6770 return;
6773 status = resolve_dfspath(ctx, conn,
6774 req->flags2 & FLAGS2_DFS_PATHNAMES,
6775 fname,
6776 &fname);
6777 if (!NT_STATUS_IS_OK(status)) {
6778 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6779 reply_botherror(req,
6780 NT_STATUS_PATH_NOT_COVERED,
6781 ERRSRV, ERRbadpath);
6782 return;
6784 reply_nterror(req, status);
6785 return;
6788 status = unix_convert(ctx, conn, fname, False,
6789 &fname, NULL, &sbuf);
6790 if (!NT_STATUS_IS_OK(status)) {
6791 reply_nterror(req, status);
6792 return;
6795 status = check_name(conn, fname);
6796 if (!NT_STATUS_IS_OK(status)) {
6797 reply_nterror(req, status);
6798 return;
6801 if (INFO_LEVEL_IS_UNIX(info_level)) {
6803 * For CIFS UNIX extensions the target name may not exist.
6806 /* Always do lstat for UNIX calls. */
6807 SMB_VFS_LSTAT(conn,fname,&sbuf);
6809 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6810 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6811 reply_unixerror(req, ERRDOS, ERRbadpath);
6812 return;
6816 if (!CAN_WRITE(conn)) {
6817 reply_doserror(req, ERRSRV, ERRaccess);
6818 return;
6821 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6822 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6823 return;
6826 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6827 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6829 /* Realloc the parameter size */
6830 *pparams = (char *)SMB_REALLOC(*pparams,2);
6831 if (*pparams == NULL) {
6832 reply_nterror(req, NT_STATUS_NO_MEMORY);
6833 return;
6835 params = *pparams;
6837 SSVAL(params,0,0);
6839 switch (info_level) {
6841 case SMB_INFO_STANDARD:
6843 status = smb_set_info_standard(conn,
6844 pdata,
6845 total_data,
6846 fsp,
6847 fname,
6848 &sbuf);
6849 break;
6852 case SMB_INFO_SET_EA:
6854 status = smb_info_set_ea(conn,
6855 pdata,
6856 total_data,
6857 fsp,
6858 fname);
6859 break;
6862 case SMB_SET_FILE_BASIC_INFO:
6863 case SMB_FILE_BASIC_INFORMATION:
6865 status = smb_set_file_basic_info(conn,
6866 pdata,
6867 total_data,
6868 fsp,
6869 fname,
6870 &sbuf);
6871 break;
6874 case SMB_FILE_ALLOCATION_INFORMATION:
6875 case SMB_SET_FILE_ALLOCATION_INFO:
6877 status = smb_set_file_allocation_info(conn, req,
6878 pdata,
6879 total_data,
6880 fsp,
6881 fname,
6882 &sbuf);
6883 break;
6886 case SMB_FILE_END_OF_FILE_INFORMATION:
6887 case SMB_SET_FILE_END_OF_FILE_INFO:
6889 status = smb_set_file_end_of_file_info(conn, req,
6890 pdata,
6891 total_data,
6892 fsp,
6893 fname,
6894 &sbuf);
6895 break;
6898 case SMB_FILE_DISPOSITION_INFORMATION:
6899 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6901 #if 0
6902 /* JRA - We used to just ignore this on a path ?
6903 * Shouldn't this be invalid level on a pathname
6904 * based call ?
6906 if (tran_call != TRANSACT2_SETFILEINFO) {
6907 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6909 #endif
6910 status = smb_set_file_disposition_info(conn,
6911 pdata,
6912 total_data,
6913 fsp,
6914 fname,
6915 &sbuf);
6916 break;
6919 case SMB_FILE_POSITION_INFORMATION:
6921 status = smb_file_position_information(conn,
6922 pdata,
6923 total_data,
6924 fsp);
6925 break;
6928 /* From tridge Samba4 :
6929 * MODE_INFORMATION in setfileinfo (I have no
6930 * idea what "mode information" on a file is - it takes a value of 0,
6931 * 2, 4 or 6. What could it be?).
6934 case SMB_FILE_MODE_INFORMATION:
6936 status = smb_file_mode_information(conn,
6937 pdata,
6938 total_data);
6939 break;
6943 * CIFS UNIX extensions.
6946 case SMB_SET_FILE_UNIX_BASIC:
6948 status = smb_set_file_unix_basic(conn, req,
6949 pdata,
6950 total_data,
6951 fsp,
6952 fname,
6953 &sbuf);
6954 break;
6957 case SMB_SET_FILE_UNIX_INFO2:
6959 status = smb_set_file_unix_info2(conn, req,
6960 pdata,
6961 total_data,
6962 fsp,
6963 fname,
6964 &sbuf);
6965 break;
6968 case SMB_SET_FILE_UNIX_LINK:
6970 if (tran_call != TRANSACT2_SETPATHINFO) {
6971 /* We must have a pathname for this. */
6972 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6973 return;
6975 status = smb_set_file_unix_link(conn, req, pdata,
6976 total_data, fname);
6977 break;
6980 case SMB_SET_FILE_UNIX_HLINK:
6982 if (tran_call != TRANSACT2_SETPATHINFO) {
6983 /* We must have a pathname for this. */
6984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6985 return;
6987 status = smb_set_file_unix_hlink(conn, req,
6988 pdata, total_data,
6989 fname);
6990 break;
6993 case SMB_FILE_RENAME_INFORMATION:
6995 status = smb_file_rename_information(conn, req,
6996 pdata, total_data,
6997 fsp, fname);
6998 break;
7001 #if defined(HAVE_POSIX_ACLS)
7002 case SMB_SET_POSIX_ACL:
7004 status = smb_set_posix_acl(conn,
7005 pdata,
7006 total_data,
7007 fsp,
7008 fname,
7009 &sbuf);
7010 break;
7012 #endif
7014 case SMB_SET_POSIX_LOCK:
7016 if (tran_call != TRANSACT2_SETFILEINFO) {
7017 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7018 return;
7020 status = smb_set_posix_lock(conn, req,
7021 pdata, total_data, fsp);
7022 break;
7025 case SMB_POSIX_PATH_OPEN:
7027 if (tran_call != TRANSACT2_SETPATHINFO) {
7028 /* We must have a pathname for this. */
7029 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7030 return;
7033 status = smb_posix_open(conn, req,
7034 ppdata,
7035 total_data,
7036 fname,
7037 &sbuf,
7038 &data_return_size);
7039 break;
7042 case SMB_POSIX_PATH_UNLINK:
7044 if (tran_call != TRANSACT2_SETPATHINFO) {
7045 /* We must have a pathname for this. */
7046 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7047 return;
7050 status = smb_posix_unlink(conn, req,
7051 pdata,
7052 total_data,
7053 fname,
7054 &sbuf);
7055 break;
7058 default:
7059 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7060 return;
7064 if (!NT_STATUS_IS_OK(status)) {
7065 if (open_was_deferred(req->mid)) {
7066 /* We have re-scheduled this call. */
7067 return;
7069 if (blocking_lock_was_deferred(req->mid)) {
7070 /* We have re-scheduled this call. */
7071 return;
7073 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7074 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7075 ERRSRV, ERRbadpath);
7076 return;
7078 if (info_level == SMB_POSIX_PATH_OPEN) {
7079 reply_openerror(req, status);
7080 return;
7083 reply_nterror(req, status);
7084 return;
7087 SSVAL(params,0,0);
7088 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7089 max_data_bytes);
7091 return;
7094 /****************************************************************************
7095 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7096 ****************************************************************************/
7098 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7099 char **pparams, int total_params,
7100 char **ppdata, int total_data,
7101 unsigned int max_data_bytes)
7103 char *params = *pparams;
7104 char *pdata = *ppdata;
7105 char *directory = NULL;
7106 SMB_STRUCT_STAT sbuf;
7107 NTSTATUS status = NT_STATUS_OK;
7108 struct ea_list *ea_list = NULL;
7109 TALLOC_CTX *ctx = talloc_tos();
7111 if (!CAN_WRITE(conn)) {
7112 reply_doserror(req, ERRSRV, ERRaccess);
7113 return;
7116 if (total_params < 5) {
7117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7118 return;
7121 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7122 total_params - 4, STR_TERMINATE,
7123 &status);
7124 if (!NT_STATUS_IS_OK(status)) {
7125 reply_nterror(req, status);
7126 return;
7129 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7131 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7132 if (!NT_STATUS_IS_OK(status)) {
7133 reply_nterror(req, status);
7134 return;
7137 status = check_name(conn, directory);
7138 if (!NT_STATUS_IS_OK(status)) {
7139 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7140 reply_nterror(req, status);
7141 return;
7144 /* Any data in this call is an EA list. */
7145 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7146 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7147 return;
7151 * OS/2 workplace shell seems to send SET_EA requests of "null"
7152 * length (4 bytes containing IVAL 4).
7153 * They seem to have no effect. Bug #3212. JRA.
7156 if (total_data != 4) {
7157 if (total_data < 10) {
7158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7159 return;
7162 if (IVAL(pdata,0) > total_data) {
7163 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7164 IVAL(pdata,0), (unsigned int)total_data));
7165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7166 return;
7169 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7170 total_data - 4);
7171 if (!ea_list) {
7172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7173 return;
7176 /* If total_data == 4 Windows doesn't care what values
7177 * are placed in that field, it just ignores them.
7178 * The System i QNTC IBM SMB client puts bad values here,
7179 * so ignore them. */
7181 status = create_directory(conn, req, directory);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 reply_nterror(req, status);
7185 return;
7188 /* Try and set any given EA. */
7189 if (ea_list) {
7190 status = set_ea(conn, NULL, directory, ea_list);
7191 if (!NT_STATUS_IS_OK(status)) {
7192 reply_nterror(req, status);
7193 return;
7197 /* Realloc the parameter and data sizes */
7198 *pparams = (char *)SMB_REALLOC(*pparams,2);
7199 if(*pparams == NULL) {
7200 reply_nterror(req, NT_STATUS_NO_MEMORY);
7201 return;
7203 params = *pparams;
7205 SSVAL(params,0,0);
7207 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7209 return;
7212 /****************************************************************************
7213 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7214 We don't actually do this - we just send a null response.
7215 ****************************************************************************/
7217 static void call_trans2findnotifyfirst(connection_struct *conn,
7218 struct smb_request *req,
7219 char **pparams, int total_params,
7220 char **ppdata, int total_data,
7221 unsigned int max_data_bytes)
7223 char *params = *pparams;
7224 uint16 info_level;
7226 if (total_params < 6) {
7227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7228 return;
7231 info_level = SVAL(params,4);
7232 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7234 switch (info_level) {
7235 case 1:
7236 case 2:
7237 break;
7238 default:
7239 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7240 return;
7243 /* Realloc the parameter and data sizes */
7244 *pparams = (char *)SMB_REALLOC(*pparams,6);
7245 if (*pparams == NULL) {
7246 reply_nterror(req, NT_STATUS_NO_MEMORY);
7247 return;
7249 params = *pparams;
7251 SSVAL(params,0,fnf_handle);
7252 SSVAL(params,2,0); /* No changes */
7253 SSVAL(params,4,0); /* No EA errors */
7255 fnf_handle++;
7257 if(fnf_handle == 0)
7258 fnf_handle = 257;
7260 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7262 return;
7265 /****************************************************************************
7266 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7267 changes). Currently this does nothing.
7268 ****************************************************************************/
7270 static void call_trans2findnotifynext(connection_struct *conn,
7271 struct smb_request *req,
7272 char **pparams, int total_params,
7273 char **ppdata, int total_data,
7274 unsigned int max_data_bytes)
7276 char *params = *pparams;
7278 DEBUG(3,("call_trans2findnotifynext\n"));
7280 /* Realloc the parameter and data sizes */
7281 *pparams = (char *)SMB_REALLOC(*pparams,4);
7282 if (*pparams == NULL) {
7283 reply_nterror(req, NT_STATUS_NO_MEMORY);
7284 return;
7286 params = *pparams;
7288 SSVAL(params,0,0); /* No changes */
7289 SSVAL(params,2,0); /* No EA errors */
7291 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7293 return;
7296 /****************************************************************************
7297 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7298 ****************************************************************************/
7300 static void call_trans2getdfsreferral(connection_struct *conn,
7301 struct smb_request *req,
7302 char **pparams, int total_params,
7303 char **ppdata, int total_data,
7304 unsigned int max_data_bytes)
7306 char *params = *pparams;
7307 char *pathname = NULL;
7308 int reply_size = 0;
7309 int max_referral_level;
7310 NTSTATUS status = NT_STATUS_OK;
7311 TALLOC_CTX *ctx = talloc_tos();
7313 DEBUG(10,("call_trans2getdfsreferral\n"));
7315 if (total_params < 3) {
7316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7317 return;
7320 max_referral_level = SVAL(params,0);
7322 if(!lp_host_msdfs()) {
7323 reply_doserror(req, ERRDOS, ERRbadfunc);
7324 return;
7327 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7328 total_params - 2, STR_TERMINATE);
7329 if (!pathname) {
7330 reply_nterror(req, NT_STATUS_NOT_FOUND);
7331 return;
7333 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7334 ppdata,&status)) < 0) {
7335 reply_nterror(req, status);
7336 return;
7339 SSVAL(req->inbuf, smb_flg2,
7340 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7341 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7343 return;
7346 #define LMCAT_SPL 0x53
7347 #define LMFUNC_GETJOBID 0x60
7349 /****************************************************************************
7350 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7351 ****************************************************************************/
7353 static void call_trans2ioctl(connection_struct *conn,
7354 struct smb_request *req,
7355 char **pparams, int total_params,
7356 char **ppdata, int total_data,
7357 unsigned int max_data_bytes)
7359 char *pdata = *ppdata;
7360 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7362 /* check for an invalid fid before proceeding */
7364 if (!fsp) {
7365 reply_doserror(req, ERRDOS, ERRbadfid);
7366 return;
7369 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7370 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7371 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7372 if (*ppdata == NULL) {
7373 reply_nterror(req, NT_STATUS_NO_MEMORY);
7374 return;
7376 pdata = *ppdata;
7378 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7379 CAN ACCEPT THIS IN UNICODE. JRA. */
7381 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7382 srvstr_push(pdata, req->flags2, pdata + 2,
7383 global_myname(), 15,
7384 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7385 srvstr_push(pdata, req->flags2, pdata+18,
7386 lp_servicename(SNUM(conn)), 13,
7387 STR_ASCII|STR_TERMINATE); /* Service name */
7388 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7389 max_data_bytes);
7390 return;
7393 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7394 reply_doserror(req, ERRSRV, ERRerror);
7397 /****************************************************************************
7398 Reply to a SMBfindclose (stop trans2 directory search).
7399 ****************************************************************************/
7401 void reply_findclose(struct smb_request *req)
7403 int dptr_num;
7405 START_PROFILE(SMBfindclose);
7407 if (req->wct < 1) {
7408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7409 END_PROFILE(SMBfindclose);
7410 return;
7413 dptr_num = SVALS(req->vwv+0, 0);
7415 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7417 dptr_close(&dptr_num);
7419 reply_outbuf(req, 0, 0);
7421 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7423 END_PROFILE(SMBfindclose);
7424 return;
7427 /****************************************************************************
7428 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7429 ****************************************************************************/
7431 void reply_findnclose(struct smb_request *req)
7433 int dptr_num;
7435 START_PROFILE(SMBfindnclose);
7437 if (req->wct < 1) {
7438 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7439 END_PROFILE(SMBfindnclose);
7440 return;
7443 dptr_num = SVAL(req->vwv+0, 0);
7445 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7447 /* We never give out valid handles for a
7448 findnotifyfirst - so any dptr_num is ok here.
7449 Just ignore it. */
7451 reply_outbuf(req, 0, 0);
7453 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7455 END_PROFILE(SMBfindnclose);
7456 return;
7459 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7460 struct trans_state *state)
7462 if (Protocol >= PROTOCOL_NT1) {
7463 req->flags2 |= 0x40; /* IS_LONG_NAME */
7464 SSVAL(req->inbuf,smb_flg2,req->flags2);
7467 if (conn->encrypt_level == Required && !req->encrypted) {
7468 if (state->call != TRANSACT2_QFSINFO &&
7469 state->call != TRANSACT2_SETFSINFO) {
7470 DEBUG(0,("handle_trans2: encryption required "
7471 "with call 0x%x\n",
7472 (unsigned int)state->call));
7473 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7474 return;
7478 /* Now we must call the relevant TRANS2 function */
7479 switch(state->call) {
7480 case TRANSACT2_OPEN:
7482 START_PROFILE(Trans2_open);
7483 call_trans2open(conn, req,
7484 &state->param, state->total_param,
7485 &state->data, state->total_data,
7486 state->max_data_return);
7487 END_PROFILE(Trans2_open);
7488 break;
7491 case TRANSACT2_FINDFIRST:
7493 START_PROFILE(Trans2_findfirst);
7494 call_trans2findfirst(conn, req,
7495 &state->param, state->total_param,
7496 &state->data, state->total_data,
7497 state->max_data_return);
7498 END_PROFILE(Trans2_findfirst);
7499 break;
7502 case TRANSACT2_FINDNEXT:
7504 START_PROFILE(Trans2_findnext);
7505 call_trans2findnext(conn, req,
7506 &state->param, state->total_param,
7507 &state->data, state->total_data,
7508 state->max_data_return);
7509 END_PROFILE(Trans2_findnext);
7510 break;
7513 case TRANSACT2_QFSINFO:
7515 START_PROFILE(Trans2_qfsinfo);
7516 call_trans2qfsinfo(conn, req,
7517 &state->param, state->total_param,
7518 &state->data, state->total_data,
7519 state->max_data_return);
7520 END_PROFILE(Trans2_qfsinfo);
7521 break;
7524 case TRANSACT2_SETFSINFO:
7526 START_PROFILE(Trans2_setfsinfo);
7527 call_trans2setfsinfo(conn, req,
7528 &state->param, state->total_param,
7529 &state->data, state->total_data,
7530 state->max_data_return);
7531 END_PROFILE(Trans2_setfsinfo);
7532 break;
7535 case TRANSACT2_QPATHINFO:
7536 case TRANSACT2_QFILEINFO:
7538 START_PROFILE(Trans2_qpathinfo);
7539 call_trans2qfilepathinfo(conn, req, state->call,
7540 &state->param, state->total_param,
7541 &state->data, state->total_data,
7542 state->max_data_return);
7543 END_PROFILE(Trans2_qpathinfo);
7544 break;
7547 case TRANSACT2_SETPATHINFO:
7548 case TRANSACT2_SETFILEINFO:
7550 START_PROFILE(Trans2_setpathinfo);
7551 call_trans2setfilepathinfo(conn, req, state->call,
7552 &state->param, state->total_param,
7553 &state->data, state->total_data,
7554 state->max_data_return);
7555 END_PROFILE(Trans2_setpathinfo);
7556 break;
7559 case TRANSACT2_FINDNOTIFYFIRST:
7561 START_PROFILE(Trans2_findnotifyfirst);
7562 call_trans2findnotifyfirst(conn, req,
7563 &state->param, state->total_param,
7564 &state->data, state->total_data,
7565 state->max_data_return);
7566 END_PROFILE(Trans2_findnotifyfirst);
7567 break;
7570 case TRANSACT2_FINDNOTIFYNEXT:
7572 START_PROFILE(Trans2_findnotifynext);
7573 call_trans2findnotifynext(conn, req,
7574 &state->param, state->total_param,
7575 &state->data, state->total_data,
7576 state->max_data_return);
7577 END_PROFILE(Trans2_findnotifynext);
7578 break;
7581 case TRANSACT2_MKDIR:
7583 START_PROFILE(Trans2_mkdir);
7584 call_trans2mkdir(conn, req,
7585 &state->param, state->total_param,
7586 &state->data, state->total_data,
7587 state->max_data_return);
7588 END_PROFILE(Trans2_mkdir);
7589 break;
7592 case TRANSACT2_GET_DFS_REFERRAL:
7594 START_PROFILE(Trans2_get_dfs_referral);
7595 call_trans2getdfsreferral(conn, req,
7596 &state->param, state->total_param,
7597 &state->data, state->total_data,
7598 state->max_data_return);
7599 END_PROFILE(Trans2_get_dfs_referral);
7600 break;
7603 case TRANSACT2_IOCTL:
7605 START_PROFILE(Trans2_ioctl);
7606 call_trans2ioctl(conn, req,
7607 &state->param, state->total_param,
7608 &state->data, state->total_data,
7609 state->max_data_return);
7610 END_PROFILE(Trans2_ioctl);
7611 break;
7614 default:
7615 /* Error in request */
7616 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7617 reply_doserror(req, ERRSRV,ERRerror);
7621 /****************************************************************************
7622 Reply to a SMBtrans2.
7623 ****************************************************************************/
7625 void reply_trans2(struct smb_request *req)
7627 connection_struct *conn = req->conn;
7628 unsigned int dsoff;
7629 unsigned int dscnt;
7630 unsigned int psoff;
7631 unsigned int pscnt;
7632 unsigned int tran_call;
7633 struct trans_state *state;
7634 NTSTATUS result;
7636 START_PROFILE(SMBtrans2);
7638 if (req->wct < 14) {
7639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7640 END_PROFILE(SMBtrans2);
7641 return;
7644 dsoff = SVAL(req->vwv+12, 0);
7645 dscnt = SVAL(req->vwv+11, 0);
7646 psoff = SVAL(req->vwv+10, 0);
7647 pscnt = SVAL(req->vwv+9, 0);
7648 tran_call = SVAL(req->vwv+14, 0);
7650 result = allow_new_trans(conn->pending_trans, req->mid);
7651 if (!NT_STATUS_IS_OK(result)) {
7652 DEBUG(2, ("Got invalid trans2 request: %s\n",
7653 nt_errstr(result)));
7654 reply_nterror(req, result);
7655 END_PROFILE(SMBtrans2);
7656 return;
7659 if (IS_IPC(conn)) {
7660 switch (tran_call) {
7661 /* List the allowed trans2 calls on IPC$ */
7662 case TRANSACT2_OPEN:
7663 case TRANSACT2_GET_DFS_REFERRAL:
7664 case TRANSACT2_QFILEINFO:
7665 case TRANSACT2_QFSINFO:
7666 case TRANSACT2_SETFSINFO:
7667 break;
7668 default:
7669 reply_doserror(req, ERRSRV, ERRaccess);
7670 END_PROFILE(SMBtrans2);
7671 return;
7675 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7676 DEBUG(0, ("talloc failed\n"));
7677 reply_nterror(req, NT_STATUS_NO_MEMORY);
7678 END_PROFILE(SMBtrans2);
7679 return;
7682 state->cmd = SMBtrans2;
7684 state->mid = req->mid;
7685 state->vuid = req->vuid;
7686 state->setup_count = SVAL(req->vwv+13, 0);
7687 state->setup = NULL;
7688 state->total_param = SVAL(req->vwv+0, 0);
7689 state->param = NULL;
7690 state->total_data = SVAL(req->vwv+1, 0);
7691 state->data = NULL;
7692 state->max_param_return = SVAL(req->vwv+2, 0);
7693 state->max_data_return = SVAL(req->vwv+3, 0);
7694 state->max_setup_return = SVAL(req->vwv+4, 0);
7695 state->close_on_completion = BITSETW(req->vwv+5, 0);
7696 state->one_way = BITSETW(req->vwv+5, 1);
7698 state->call = tran_call;
7700 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7701 is so as a sanity check */
7702 if (state->setup_count != 1) {
7704 * Need to have rc=0 for ioctl to get job id for OS/2.
7705 * Network printing will fail if function is not successful.
7706 * Similar function in reply.c will be used if protocol
7707 * is LANMAN1.0 instead of LM1.2X002.
7708 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7709 * outbuf doesn't have to be set(only job id is used).
7711 if ( (state->setup_count == 4)
7712 && (tran_call == TRANSACT2_IOCTL)
7713 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7714 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7715 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7716 } else {
7717 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7718 DEBUG(2,("Transaction is %d\n",tran_call));
7719 TALLOC_FREE(state);
7720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7721 END_PROFILE(SMBtrans2);
7722 return;
7726 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7727 goto bad_param;
7729 if (state->total_data) {
7731 if (trans_oob(state->total_data, 0, dscnt)
7732 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7733 goto bad_param;
7736 /* Can't use talloc here, the core routines do realloc on the
7737 * params and data. */
7738 state->data = (char *)SMB_MALLOC(state->total_data);
7739 if (state->data == NULL) {
7740 DEBUG(0,("reply_trans2: data malloc fail for %u "
7741 "bytes !\n", (unsigned int)state->total_data));
7742 TALLOC_FREE(state);
7743 reply_nterror(req, NT_STATUS_NO_MEMORY);
7744 END_PROFILE(SMBtrans2);
7745 return;
7748 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7751 if (state->total_param) {
7753 if (trans_oob(state->total_param, 0, pscnt)
7754 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7755 goto bad_param;
7758 /* Can't use talloc here, the core routines do realloc on the
7759 * params and data. */
7760 state->param = (char *)SMB_MALLOC(state->total_param);
7761 if (state->param == NULL) {
7762 DEBUG(0,("reply_trans: param malloc fail for %u "
7763 "bytes !\n", (unsigned int)state->total_param));
7764 SAFE_FREE(state->data);
7765 TALLOC_FREE(state);
7766 reply_nterror(req, NT_STATUS_NO_MEMORY);
7767 END_PROFILE(SMBtrans2);
7768 return;
7771 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7774 state->received_data = dscnt;
7775 state->received_param = pscnt;
7777 if ((state->received_param == state->total_param) &&
7778 (state->received_data == state->total_data)) {
7780 handle_trans2(conn, req, state);
7782 SAFE_FREE(state->data);
7783 SAFE_FREE(state->param);
7784 TALLOC_FREE(state);
7785 END_PROFILE(SMBtrans2);
7786 return;
7789 DLIST_ADD(conn->pending_trans, state);
7791 /* We need to send an interim response then receive the rest
7792 of the parameter/data bytes */
7793 reply_outbuf(req, 0, 0);
7794 show_msg((char *)req->outbuf);
7795 END_PROFILE(SMBtrans2);
7796 return;
7798 bad_param:
7800 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7801 SAFE_FREE(state->data);
7802 SAFE_FREE(state->param);
7803 TALLOC_FREE(state);
7804 END_PROFILE(SMBtrans2);
7805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7809 /****************************************************************************
7810 Reply to a SMBtranss2
7811 ****************************************************************************/
7813 void reply_transs2(struct smb_request *req)
7815 connection_struct *conn = req->conn;
7816 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7817 struct trans_state *state;
7819 START_PROFILE(SMBtranss2);
7821 show_msg((char *)req->inbuf);
7823 if (req->wct < 8) {
7824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7825 END_PROFILE(SMBtranss2);
7826 return;
7829 for (state = conn->pending_trans; state != NULL;
7830 state = state->next) {
7831 if (state->mid == req->mid) {
7832 break;
7836 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7838 END_PROFILE(SMBtranss2);
7839 return;
7842 /* Revise state->total_param and state->total_data in case they have
7843 changed downwards */
7845 if (SVAL(req->vwv+0, 0) < state->total_param)
7846 state->total_param = SVAL(req->vwv+0, 0);
7847 if (SVAL(req->vwv+1, 0) < state->total_data)
7848 state->total_data = SVAL(req->vwv+1, 0);
7850 pcnt = SVAL(req->vwv+2, 0);
7851 poff = SVAL(req->vwv+3, 0);
7852 pdisp = SVAL(req->vwv+4, 0);
7854 dcnt = SVAL(req->vwv+5, 0);
7855 doff = SVAL(req->vwv+6, 0);
7856 ddisp = SVAL(req->vwv+7, 0);
7858 state->received_param += pcnt;
7859 state->received_data += dcnt;
7861 if ((state->received_data > state->total_data) ||
7862 (state->received_param > state->total_param))
7863 goto bad_param;
7865 if (pcnt) {
7866 if (trans_oob(state->total_param, pdisp, pcnt)
7867 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7868 goto bad_param;
7870 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7873 if (dcnt) {
7874 if (trans_oob(state->total_data, ddisp, dcnt)
7875 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7876 goto bad_param;
7878 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7881 if ((state->received_param < state->total_param) ||
7882 (state->received_data < state->total_data)) {
7883 END_PROFILE(SMBtranss2);
7884 return;
7887 handle_trans2(conn, req, state);
7889 DLIST_REMOVE(conn->pending_trans, state);
7890 SAFE_FREE(state->data);
7891 SAFE_FREE(state->param);
7892 TALLOC_FREE(state);
7894 END_PROFILE(SMBtranss2);
7895 return;
7897 bad_param:
7899 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7900 DLIST_REMOVE(conn->pending_trans, state);
7901 SAFE_FREE(state->data);
7902 SAFE_FREE(state->param);
7903 TALLOC_FREE(state);
7904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7905 END_PROFILE(SMBtranss2);
7906 return;