Fix bug 6867 - trans2findnext returns reply_nterror(req, ntstatus) In a directory...
[Samba.git] / source / smbd / trans2.c
blob21f70d015fbcee78caec28840e59506f4b62f8ed
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
52 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
64 account sparse files.
65 ********************************************************************/
67 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
69 SMB_BIG_UINT ret;
71 if(S_ISDIR(sbuf->st_mode)) {
72 return 0;
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
77 #else
78 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
79 #endif
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char *prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 NULL
103 int i;
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
107 return true;
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 return true;
113 return false;
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
126 char *val = NULL;
127 ssize_t sizeret;
129 again:
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (!val) {
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 } else {
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 attr_size = 65536;
144 goto again;
147 if (sizeret == -1) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
154 pea->flags = 0;
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 } else {
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
161 TALLOC_FREE(val);
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
166 return NT_STATUS_OK;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
177 char *p;
178 char **names, **tmp;
179 size_t num_names;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
183 *pnames = NULL;
184 *pnum_names = 0;
185 return NT_STATUS_OK;
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
193 if (names == NULL) {
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
204 TALLOC_FREE(names);
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
210 ea_namelist_size);
211 } else {
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
213 ea_namelist_size);
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
219 else {
220 break;
224 if (sizeret == -1) {
225 TALLOC_FREE(names);
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
232 if (sizeret == 0) {
233 TALLOC_FREE(names);
234 *pnames = NULL;
235 *pnum_names = 0;
236 return NT_STATUS_OK;
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
244 TALLOC_FREE(names);
245 return NT_STATUS_INTERNAL_ERROR;
249 * count the names
251 num_names = 0;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
254 num_names += 1;
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 if (tmp == NULL) {
259 DEBUG(0, ("talloc failed\n"));
260 TALLOC_FREE(names);
261 return NT_STATUS_NO_MEMORY;
264 names = tmp;
265 num_names = 0;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
271 *pnames = names;
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
401 return 0;
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
405 return total_ea_len;
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
414 size_t total_ea_len;
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
423 break;
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
439 int ret;
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
460 } else {
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
465 #ifdef ENOATTR
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
469 unix_ea_name));
470 ret = 0;
472 #endif
473 } else {
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
479 } else {
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
487 if (ret == -1) {
488 #ifdef ENOTSUP
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
492 #endif
493 return map_nt_error_from_unix(errno);
497 return NT_STATUS_OK;
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
518 break;
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
522 return NULL;
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
525 &converted_size)) {
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
529 if (!eal->ea.name) {
530 return NULL;
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 return ea_list_head;
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
548 uint16 val_len;
549 unsigned int namelen;
550 size_t converted_size;
552 if (!eal) {
553 return NULL;
556 if (data_size < 6) {
557 return NULL;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
565 return NULL;
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
570 return NULL;
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
574 strerror(errno)));
576 if (!eal->ea.name) {
577 return NULL;
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
582 return NULL;
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
592 if (pbytes_used) {
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
599 return eal;
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
609 size_t offset = 0;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
615 if (!eal) {
616 return NULL;
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
623 return ea_list_head;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
632 fstring dos_ea_name;
633 struct ea_list *listp;
634 size_t ret = 0;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
641 if (ret) {
642 ret += 4;
645 return ret;
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
661 break;
665 if (flistp) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
669 } else {
670 /* Null entry. */
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
677 return name_list;
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
689 const char *params,
690 int paramsize,
691 const char *pdata,
692 int datasize,
693 int max_data_bytes)
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
703 int useable_space;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
714 for OS/2. */
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
720 overflow = True;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
728 return;
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
743 + 2 * 10 /* wct */
744 + alignment_offset
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
771 /* Set total params and data to be sent */
772 SSVAL(req->outbuf,smb_tprcnt,paramsize);
773 SSVAL(req->outbuf,smb_tdrcnt,datasize);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime = MIN(params_to_send,useable_space);
780 data_sent_thistime = useable_space - params_sent_thistime;
781 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
783 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req->outbuf,smb_proff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf)));
794 if(params_sent_thistime == 0)
795 SSVAL(req->outbuf,smb_prdisp,0);
796 else
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req->outbuf,smb_prdisp,pp - params);
800 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
801 if(data_sent_thistime == 0) {
802 SSVAL(req->outbuf,smb_droff,0);
803 SSVAL(req->outbuf,smb_drdisp, 0);
804 } else {
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req->outbuf, smb_droff,
808 ((smb_buf(req->outbuf)+alignment_offset)
809 - smb_base(req->outbuf))
810 + params_sent_thistime + data_alignment_offset);
811 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
814 /* Initialize the padding for alignment */
816 if (alignment_offset != 0) {
817 memset(smb_buf(req->outbuf), 0, alignment_offset);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime) {
823 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
824 params_sent_thistime);
827 /* Copy in the data bytes */
828 if(data_sent_thistime) {
829 if (data_alignment_offset != 0) {
830 memset((smb_buf(req->outbuf)+alignment_offset+
831 params_sent_thistime), 0,
832 data_alignment_offset);
834 memcpy(smb_buf(req->outbuf)+alignment_offset
835 +params_sent_thistime+data_alignment_offset,
836 pd,data_sent_thistime);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime, data_sent_thistime, useable_space));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send, data_to_send, paramsize, datasize));
844 if (overflow) {
845 error_packet_set((char *)req->outbuf,
846 ERRDOS,ERRbufferoverflow,
847 STATUS_BUFFER_OVERFLOW,
848 __LINE__,__FILE__);
851 /* Send the packet */
852 show_msg((char *)req->outbuf);
853 if (!srv_send_smb(smbd_server_fd(),
854 (char *)req->outbuf,
855 IS_CONN_ENCRYPTED(conn)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req->outbuf);
860 pp += params_sent_thistime;
861 pd += data_sent_thistime;
863 params_to_send -= params_sent_thistime;
864 data_to_send -= data_sent_thistime;
866 /* Sanity check */
867 if(params_to_send < 0 || data_to_send < 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send, data_to_send));
870 return;
874 return;
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct *conn,
882 struct smb_request *req,
883 char **pparams, int total_params,
884 char **ppdata, int total_data,
885 unsigned int max_data_bytes)
887 char *params = *pparams;
888 char *pdata = *ppdata;
889 int deny_mode;
890 int32 open_attr;
891 bool oplock_request;
892 #if 0
893 bool return_additional_info;
894 int16 open_sattr;
895 time_t open_time;
896 #endif
897 int open_ofun;
898 uint32 open_size;
899 char *pname;
900 char *fname = NULL;
901 SMB_OFF_T size=0;
902 int fattr=0,mtime=0;
903 SMB_INO_T inode = 0;
904 SMB_STRUCT_STAT sbuf;
905 int smb_action = 0;
906 files_struct *fsp;
907 struct ea_list *ea_list = NULL;
908 uint16 flags = 0;
909 NTSTATUS status;
910 uint32 access_mask;
911 uint32 share_mode;
912 uint32 create_disposition;
913 uint32 create_options = 0;
914 TALLOC_CTX *ctx = talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params < 29) {
921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
922 return;
925 flags = SVAL(params, 0);
926 deny_mode = SVAL(params, 2);
927 open_attr = SVAL(params,6);
928 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
929 if (oplock_request) {
930 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
933 #if 0
934 return_additional_info = BITSETW(params,0);
935 open_sattr = SVAL(params, 4);
936 open_time = make_unix_date3(params+8);
937 #endif
938 open_ofun = SVAL(params,12);
939 open_size = IVAL(params,14);
940 pname = &params[28];
942 if (IS_IPC(conn)) {
943 reply_doserror(req, ERRSRV, ERRaccess);
944 return;
947 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
948 total_params - 28, STR_TERMINATE,
949 &status);
950 if (!NT_STATUS_IS_OK(status)) {
951 reply_nterror(req, status);
952 return;
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
957 (unsigned int)open_ofun, open_size));
959 if (open_ofun == 0) {
960 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
961 return;
964 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
965 &access_mask,
966 &share_mode,
967 &create_disposition,
968 &create_options)) {
969 reply_doserror(req, ERRDOS, ERRbadaccess);
970 return;
973 /* Any data in this call is an EA list. */
974 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
975 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
976 return;
979 if (total_data != 4) {
980 if (total_data < 10) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 return;
985 if (IVAL(pdata,0) > total_data) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata,0), (unsigned int)total_data));
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 return;
992 ea_list = read_ea_list(talloc_tos(), pdata + 4,
993 total_data - 4);
994 if (!ea_list) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 return;
998 } else if (IVAL(pdata,0) != 4) {
999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1000 return;
1003 status = create_file(conn, /* conn */
1004 req, /* req */
1005 0, /* root_dir_fid */
1006 fname, /* fname */
1007 access_mask, /* access_mask */
1008 share_mode, /* share_access */
1009 create_disposition, /* create_disposition*/
1010 create_options, /* create_options */
1011 open_attr, /* file_attributes */
1012 oplock_request, /* oplock_request */
1013 open_size, /* allocation_size */
1014 NULL, /* sd */
1015 ea_list, /* ea_list */
1016 &fsp, /* result */
1017 &smb_action, /* pinfo */
1018 &sbuf); /* psbuf */
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (open_was_deferred(req->mid)) {
1022 /* We have re-scheduled this call. */
1023 return;
1025 reply_openerror(req, status);
1026 return;
1029 size = get_file_size(sbuf);
1030 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1031 mtime = sbuf.st_mtime;
1032 inode = sbuf.st_ino;
1033 if (fattr & aDIR) {
1034 close_file(fsp,ERROR_CLOSE);
1035 reply_doserror(req, ERRDOS,ERRnoaccess);
1036 return;
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1041 if(*pparams == NULL ) {
1042 reply_nterror(req, NT_STATUS_NO_MEMORY);
1043 return;
1045 params = *pparams;
1047 SSVAL(params,0,fsp->fnum);
1048 SSVAL(params,2,fattr);
1049 srv_put_dos_date2(params,4, mtime);
1050 SIVAL(params,8, (uint32)size);
1051 SSVAL(params,12,deny_mode);
1052 SSVAL(params,14,0); /* open_type - file or directory. */
1053 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1059 SSVAL(params,18,smb_action);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params,20,inode);
1065 SSVAL(params,24,0); /* Padding. */
1066 if (flags & 8) {
1067 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1068 SIVAL(params, 26, ea_size);
1069 } else {
1070 SIVAL(params, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct *conn,
1085 const char *str,
1086 const char *mask)
1088 if (mask[0] == '.' && mask[1] == 0)
1089 return False;
1090 if (dptr_has_wild(conn->dirptr)) {
1091 return False;
1093 if (conn->case_sensitive)
1094 return strcmp(str,mask)==0;
1095 else
1096 return StrCaseCmp(str,mask) == 0;
1099 /****************************************************************************
1100 Return the filetype for UNIX extensions.
1101 ****************************************************************************/
1103 static uint32 unix_filetype(mode_t mode)
1105 if(S_ISREG(mode))
1106 return UNIX_TYPE_FILE;
1107 else if(S_ISDIR(mode))
1108 return UNIX_TYPE_DIR;
1109 #ifdef S_ISLNK
1110 else if(S_ISLNK(mode))
1111 return UNIX_TYPE_SYMLINK;
1112 #endif
1113 #ifdef S_ISCHR
1114 else if(S_ISCHR(mode))
1115 return UNIX_TYPE_CHARDEV;
1116 #endif
1117 #ifdef S_ISBLK
1118 else if(S_ISBLK(mode))
1119 return UNIX_TYPE_BLKDEV;
1120 #endif
1121 #ifdef S_ISFIFO
1122 else if(S_ISFIFO(mode))
1123 return UNIX_TYPE_FIFO;
1124 #endif
1125 #ifdef S_ISSOCK
1126 else if(S_ISSOCK(mode))
1127 return UNIX_TYPE_SOCKET;
1128 #endif
1130 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1131 return UNIX_TYPE_UNKNOWN;
1134 /****************************************************************************
1135 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1136 ****************************************************************************/
1138 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1140 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1141 SMB_STRUCT_STAT *psbuf,
1142 uint32 perms,
1143 enum perm_type ptype,
1144 mode_t *ret_perms)
1146 mode_t ret = 0;
1148 if (perms == SMB_MODE_NO_CHANGE) {
1149 if (!VALID_STAT(*psbuf)) {
1150 return NT_STATUS_INVALID_PARAMETER;
1151 } else {
1152 *ret_perms = psbuf->st_mode;
1153 return NT_STATUS_OK;
1157 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1158 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1159 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1160 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1161 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1162 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1163 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1164 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1165 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1166 #ifdef S_ISVTX
1167 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1168 #endif
1169 #ifdef S_ISGID
1170 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1171 #endif
1172 #ifdef S_ISUID
1173 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1174 #endif
1176 switch (ptype) {
1177 case PERM_NEW_FILE:
1178 /* Apply mode mask */
1179 ret &= lp_create_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_create_mode(SNUM(conn));
1182 break;
1183 case PERM_NEW_DIR:
1184 ret &= lp_dir_mask(SNUM(conn));
1185 /* Add in force bits */
1186 ret |= lp_force_dir_mode(SNUM(conn));
1187 break;
1188 case PERM_EXISTING_FILE:
1189 /* Apply mode mask */
1190 ret &= lp_security_mask(SNUM(conn));
1191 /* Add in force bits */
1192 ret |= lp_force_security_mode(SNUM(conn));
1193 break;
1194 case PERM_EXISTING_DIR:
1195 /* Apply mode mask */
1196 ret &= lp_dir_security_mask(SNUM(conn));
1197 /* Add in force bits */
1198 ret |= lp_force_dir_security_mode(SNUM(conn));
1199 break;
1202 *ret_perms = ret;
1203 return NT_STATUS_OK;
1206 /****************************************************************************
1207 Needed to show the msdfs symlinks as directories. Modifies psbuf
1208 to be a directory if it's a msdfs link.
1209 ****************************************************************************/
1211 static bool check_msdfs_link(connection_struct *conn,
1212 const char *pathname,
1213 SMB_STRUCT_STAT *psbuf)
1215 int saved_errno = errno;
1216 if(lp_host_msdfs() &&
1217 lp_msdfs_root(SNUM(conn)) &&
1218 is_msdfs_link(conn, pathname, psbuf)) {
1220 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1221 "as a directory\n",
1222 pathname));
1223 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1224 errno = saved_errno;
1225 return true;
1227 errno = saved_errno;
1228 return false;
1232 /****************************************************************************
1233 Get a level dependent lanman2 dir entry.
1234 ****************************************************************************/
1236 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1237 connection_struct *conn,
1238 uint16 flags2,
1239 const char *path_mask,
1240 uint32 dirtype,
1241 int info_level,
1242 int requires_resume_key,
1243 bool dont_descend,
1244 bool ask_sharemode,
1245 char **ppdata,
1246 char *base_data,
1247 char *end_data,
1248 int space_remaining,
1249 bool *out_of_space,
1250 bool *got_exact_match,
1251 int *last_entry_off,
1252 struct ea_list *name_list)
1254 const char *dname;
1255 bool found = False;
1256 SMB_STRUCT_STAT sbuf;
1257 const char *mask = NULL;
1258 char *pathreal = NULL;
1259 const char *fname = NULL;
1260 char *p, *q, *pdata = *ppdata;
1261 uint32 reskey=0;
1262 long prev_dirpos=0;
1263 uint32 mode=0;
1264 SMB_OFF_T file_size = 0;
1265 SMB_BIG_UINT allocation_size = 0;
1266 uint32 len;
1267 struct timespec mdate_ts, adate_ts, create_date_ts;
1268 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1269 char *nameptr;
1270 char *last_entry_ptr;
1271 bool was_8_3;
1272 uint32 nt_extmode; /* Used for NT connections instead of mode */
1273 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1274 bool check_mangled_names = lp_manglednames(conn->params);
1275 char mangled_name[13]; /* mangled 8.3 name. */
1277 *out_of_space = False;
1278 *got_exact_match = False;
1280 ZERO_STRUCT(mdate_ts);
1281 ZERO_STRUCT(adate_ts);
1282 ZERO_STRUCT(create_date_ts);
1284 if (!conn->dirptr) {
1285 return(False);
1288 p = strrchr_m(path_mask,'/');
1289 if(p != NULL) {
1290 if(p[1] == '\0') {
1291 mask = talloc_strdup(ctx,"*.*");
1292 } else {
1293 mask = p+1;
1295 } else {
1296 mask = path_mask;
1299 while (!found) {
1300 bool got_match;
1301 bool ms_dfs_link = False;
1303 /* Needed if we run out of space */
1304 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1305 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1308 * Due to bugs in NT client redirectors we are not using
1309 * resume keys any more - set them to zero.
1310 * Check out the related comments in findfirst/findnext.
1311 * JRA.
1314 reskey = 0;
1316 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1317 (long)conn->dirptr,curr_dirpos));
1319 if (!dname) {
1320 return(False);
1324 * fname may get mangled, dname is never mangled.
1325 * Whenever we're accessing the filesystem we use
1326 * pathreal which is composed from dname.
1329 pathreal = NULL;
1330 fname = dname;
1332 /* Mangle fname if it's an illegal name. */
1333 if (mangle_must_mangle(dname,conn->params)) {
1334 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1335 continue; /* Error - couldn't mangle. */
1337 fname = mangled_name;
1340 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1341 got_match = mask_match(fname, mask, conn->case_sensitive);
1344 if(!got_match && check_mangled_names &&
1345 !mangle_is_8_3(fname, False, conn->params)) {
1347 * It turns out that NT matches wildcards against
1348 * both long *and* short names. This may explain some
1349 * of the wildcard wierdness from old DOS clients
1350 * that some people have been seeing.... JRA.
1352 /* Force the mangling into 8.3. */
1353 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1354 continue; /* Error - couldn't mangle. */
1357 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1358 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1362 if (got_match) {
1363 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1365 if (dont_descend && !isdots) {
1366 continue;
1369 if (needslash) {
1370 pathreal = NULL;
1371 pathreal = talloc_asprintf(ctx,
1372 "%s/%s",
1373 conn->dirpath,
1374 dname);
1375 } else {
1376 pathreal = talloc_asprintf(ctx,
1377 "%s%s",
1378 conn->dirpath,
1379 dname);
1382 if (!pathreal) {
1383 return False;
1386 if (INFO_LEVEL_IS_UNIX(info_level)) {
1387 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1388 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1389 pathreal,strerror(errno)));
1390 TALLOC_FREE(pathreal);
1391 continue;
1393 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1394 /* Needed to show the msdfs symlinks as
1395 * directories */
1397 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1398 if (!ms_dfs_link) {
1399 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1400 pathreal,strerror(errno)));
1401 TALLOC_FREE(pathreal);
1402 continue;
1406 if (ms_dfs_link) {
1407 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1408 } else {
1409 mode = dos_mode(conn,pathreal,&sbuf);
1412 if (!dir_check_ftype(conn,mode,dirtype)) {
1413 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1414 TALLOC_FREE(pathreal);
1415 continue;
1418 if (!(mode & aDIR)) {
1419 file_size = get_file_size(sbuf);
1421 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1423 mdate_ts = get_mtimespec(&sbuf);
1424 adate_ts = get_atimespec(&sbuf);
1425 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1427 if (ask_sharemode) {
1428 struct timespec write_time_ts;
1429 struct file_id fileid;
1431 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1432 get_file_infos(fileid, NULL, &write_time_ts);
1433 if (!null_timespec(write_time_ts)) {
1434 mdate_ts = write_time_ts;
1438 if (lp_dos_filetime_resolution(SNUM(conn))) {
1439 dos_filetime_timespec(&create_date_ts);
1440 dos_filetime_timespec(&mdate_ts);
1441 dos_filetime_timespec(&adate_ts);
1444 create_date = convert_timespec_to_time_t(create_date_ts);
1445 mdate = convert_timespec_to_time_t(mdate_ts);
1446 adate = convert_timespec_to_time_t(adate_ts);
1448 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1450 found = True;
1452 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1456 p = pdata;
1457 last_entry_ptr = p;
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1465 SIVAL(p,0,reskey);
1466 p += 4;
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1473 SSVAL(p,20,mode);
1474 p += 23;
1475 nameptr = p;
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1481 STR_TERMINATE);
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483 if (len > 2) {
1484 SCVAL(nameptr, -1, len - 2);
1485 } else {
1486 SCVAL(nameptr, -1, 0);
1488 } else {
1489 if (len > 1) {
1490 SCVAL(nameptr, -1, len - 1);
1491 } else {
1492 SCVAL(nameptr, -1, 0);
1495 p += len;
1496 break;
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1501 SIVAL(p,0,reskey);
1502 p += 4;
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1509 SSVAL(p,20,mode);
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1514 p += 27;
1515 nameptr = p - 1;
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 if (len > 2) {
1521 len -= 2;
1522 } else {
1523 len = 0;
1525 } else {
1526 if (len > 1) {
1527 len -= 1;
1528 } else {
1529 len = 0;
1532 SCVAL(nameptr,0,len);
1533 p += len;
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535 break;
1537 case SMB_FIND_EA_LIST:
1539 struct ea_list *file_list = NULL;
1540 size_t ea_len = 0;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if (!name_list) {
1544 return False;
1546 if(requires_resume_key) {
1547 SIVAL(p,0,reskey);
1548 p += 4;
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1555 SSVAL(p,20,mode);
1556 p += 22; /* p now points to the EA area. */
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573 nameptr = p;
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 if (len > 2) {
1579 len -= 2;
1580 } else {
1581 len = 0;
1583 } else {
1584 if (len > 1) {
1585 len -= 1;
1586 } else {
1587 len = 0;
1590 SCVAL(nameptr,0,len);
1591 p += len + 1;
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 break;
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599 p += 4;
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(p,create_date_ts); p += 8;
1602 put_long_date_timespec(p,adate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1612 p += 4;
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1620 conn->params)) {
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1628 if (len < 24) {
1629 memset(p + 2 + len,'\0',24 - len);
1631 SSVAL(p, 0, len);
1632 } else {
1633 memset(p,'\0',26);
1635 p += 2 + 24;
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1639 SIVAL(q,0,len);
1640 p += len;
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1644 SIVAL(pdata,0,len);
1645 p = pdata + len;
1646 break;
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650 p += 4;
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(p,create_date_ts); p += 8;
1653 put_long_date_timespec(p,adate_ts); p += 8;
1654 put_long_date_timespec(p,mdate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,len);
1663 p += 4 + len;
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1667 SIVAL(pdata,0,len);
1668 p = pdata + len;
1669 break;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673 p += 4;
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(p,create_date_ts); p += 8;
1676 put_long_date_timespec(p,adate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1686 p +=4;
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1691 SIVAL(q, 0, len);
1692 p += len;
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len);
1698 p = pdata + len;
1699 break;
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703 p += 4;
1704 SIVAL(p,0,reskey); p += 4;
1705 p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1711 SIVAL(p, -4, len);
1712 p += len;
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len);
1717 p = pdata + len;
1718 break;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722 p += 4;
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(p,create_date_ts); p += 8;
1725 put_long_date_timespec(p,adate_ts); p += 8;
1726 put_long_date_timespec(p,mdate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p +=4;
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q, 0, len);
1744 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(p,create_date_ts); p += 8;
1758 put_long_date_timespec(p,adate_ts); p += 8;
1759 put_long_date_timespec(p,mdate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p +=4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 SSVAL(p, 0, len);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 26;
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(q,0,len);
1800 p += len;
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1804 SIVAL(pdata,0,len);
1805 p = pdata + len;
1806 break;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1812 p+= 4;
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1820 NULL, &sbuf);
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE);
1824 } else {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1827 NULL, &sbuf);
1828 nameptr = p;
1829 p += 4;
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1835 p += len;
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1841 p = pdata + len;
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1844 break;
1846 default:
1847 return(False);
1851 if (PTR_DIFF(p,pdata) > space_remaining) {
1852 /* Move the dirptr back to prev_dirpos */
1853 dptr_SeekDir(conn->dirptr, prev_dirpos);
1854 *out_of_space = True;
1855 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1856 return False; /* Not finished - just out of space */
1859 /* Setup the last entry pointer, as an offset from base_data */
1860 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1861 /* Advance the data pointer to the next slot */
1862 *ppdata = p;
1864 return(found);
1867 /****************************************************************************
1868 Reply to a TRANS2_FINDFIRST.
1869 ****************************************************************************/
1871 static void call_trans2findfirst(connection_struct *conn,
1872 struct smb_request *req,
1873 char **pparams, int total_params,
1874 char **ppdata, int total_data,
1875 unsigned int max_data_bytes)
1877 /* We must be careful here that we don't return more than the
1878 allowed number of data bytes. If this means returning fewer than
1879 maxentries then so be it. We assume that the redirector has
1880 enough room for the fixed number of parameter bytes it has
1881 requested. */
1882 char *params = *pparams;
1883 char *pdata = *ppdata;
1884 char *data_end;
1885 uint32 dirtype;
1886 int maxentries;
1887 uint16 findfirst_flags;
1888 bool close_after_first;
1889 bool close_if_end;
1890 bool requires_resume_key;
1891 int info_level;
1892 char *directory = NULL;
1893 char *mask = NULL;
1894 char *p;
1895 int last_entry_off=0;
1896 int dptr_num = -1;
1897 int numentries = 0;
1898 int i;
1899 bool finished = False;
1900 bool dont_descend = False;
1901 bool out_of_space = False;
1902 int space_remaining;
1903 bool mask_contains_wcard = False;
1904 SMB_STRUCT_STAT sbuf;
1905 struct ea_list *ea_list = NULL;
1906 NTSTATUS ntstatus = NT_STATUS_OK;
1907 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1908 TALLOC_CTX *ctx = talloc_tos();
1910 if (total_params < 13) {
1911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1912 return;
1915 dirtype = SVAL(params,0);
1916 maxentries = SVAL(params,2);
1917 findfirst_flags = SVAL(params,4);
1918 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1919 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1920 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1921 info_level = SVAL(params,6);
1923 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1924 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1925 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1926 info_level, max_data_bytes));
1928 if (!maxentries) {
1929 /* W2K3 seems to treat zero as 1. */
1930 maxentries = 1;
1933 switch (info_level) {
1934 case SMB_FIND_INFO_STANDARD:
1935 case SMB_FIND_EA_SIZE:
1936 case SMB_FIND_EA_LIST:
1937 case SMB_FIND_FILE_DIRECTORY_INFO:
1938 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_NAMES_INFO:
1940 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1941 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1942 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1943 break;
1944 case SMB_FIND_FILE_UNIX:
1945 case SMB_FIND_FILE_UNIX_INFO2:
1946 /* Always use filesystem for UNIX mtime query. */
1947 ask_sharemode = false;
1948 if (!lp_unix_extensions()) {
1949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1950 return;
1952 break;
1953 default:
1954 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1955 return;
1958 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1959 params+12, total_params - 12,
1960 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1961 if (!NT_STATUS_IS_OK(ntstatus)) {
1962 reply_nterror(req, ntstatus);
1963 return;
1966 ntstatus = resolve_dfspath_wcard(ctx, conn,
1967 req->flags2 & FLAGS2_DFS_PATHNAMES,
1968 directory,
1969 &directory,
1970 &mask_contains_wcard);
1971 if (!NT_STATUS_IS_OK(ntstatus)) {
1972 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1973 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1974 ERRSRV, ERRbadpath);
1975 return;
1977 reply_nterror(req, ntstatus);
1978 return;
1981 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1982 if (!NT_STATUS_IS_OK(ntstatus)) {
1983 reply_nterror(req, ntstatus);
1984 return;
1987 ntstatus = check_name(conn, directory);
1988 if (!NT_STATUS_IS_OK(ntstatus)) {
1989 reply_nterror(req, ntstatus);
1990 return;
1993 p = strrchr_m(directory,'/');
1994 if(p == NULL) {
1995 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1996 if((directory[0] == '.') && (directory[1] == '\0')) {
1997 mask = talloc_strdup(ctx,"*");
1998 if (!mask) {
1999 reply_nterror(req, NT_STATUS_NO_MEMORY);
2000 return;
2002 mask_contains_wcard = True;
2004 directory = talloc_strdup(talloc_tos(), "./");
2005 if (!directory) {
2006 reply_nterror(req, NT_STATUS_NO_MEMORY);
2007 return;
2009 } else {
2010 *p = 0;
2013 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2015 if (info_level == SMB_FIND_EA_LIST) {
2016 uint32 ea_size;
2018 if (total_data < 4) {
2019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2020 return;
2023 ea_size = IVAL(pdata,0);
2024 if (ea_size != total_data) {
2025 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2026 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 return;
2031 if (!lp_ea_support(SNUM(conn))) {
2032 reply_doserror(req, ERRDOS, ERReasnotsupported);
2033 return;
2036 /* Pull out the list of names. */
2037 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2038 if (!ea_list) {
2039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 return;
2044 *ppdata = (char *)SMB_REALLOC(
2045 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2046 if(*ppdata == NULL ) {
2047 reply_nterror(req, NT_STATUS_NO_MEMORY);
2048 return;
2050 pdata = *ppdata;
2051 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2053 /* Realloc the params space */
2054 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2055 if (*pparams == NULL) {
2056 reply_nterror(req, NT_STATUS_NO_MEMORY);
2057 return;
2059 params = *pparams;
2061 /* Save the wildcard match and attribs we are using on this directory -
2062 needed as lanman2 assumes these are being saved between calls */
2064 ntstatus = dptr_create(conn,
2065 directory,
2066 False,
2067 True,
2068 req->smbpid,
2069 mask,
2070 mask_contains_wcard,
2071 dirtype,
2072 &conn->dirptr);
2074 if (!NT_STATUS_IS_OK(ntstatus)) {
2075 reply_nterror(req, ntstatus);
2076 return;
2079 dptr_num = dptr_dnum(conn->dirptr);
2080 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2082 /* We don't need to check for VOL here as this is returned by
2083 a different TRANS2 call. */
2085 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2086 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2087 dont_descend = True;
2089 p = pdata;
2090 space_remaining = max_data_bytes;
2091 out_of_space = False;
2093 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2094 bool got_exact_match = False;
2096 /* this is a heuristic to avoid seeking the dirptr except when
2097 absolutely necessary. It allows for a filename of about 40 chars */
2098 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2099 out_of_space = True;
2100 finished = False;
2101 } else {
2102 finished = !get_lanman2_dir_entry(ctx,
2103 conn,
2104 req->flags2,
2105 mask,dirtype,info_level,
2106 requires_resume_key,dont_descend,
2107 ask_sharemode,
2108 &p,pdata,data_end,
2109 space_remaining, &out_of_space,
2110 &got_exact_match,
2111 &last_entry_off, ea_list);
2114 if (finished && out_of_space)
2115 finished = False;
2117 if (!finished && !out_of_space)
2118 numentries++;
2121 * As an optimisation if we know we aren't looking
2122 * for a wildcard name (ie. the name matches the wildcard exactly)
2123 * then we can finish on any (first) match.
2124 * This speeds up large directory searches. JRA.
2127 if(got_exact_match)
2128 finished = True;
2130 /* Ensure space_remaining never goes -ve. */
2131 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2132 space_remaining = 0;
2133 out_of_space = true;
2134 } else {
2135 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2139 /* Check if we can close the dirptr */
2140 if(close_after_first || (finished && close_if_end)) {
2141 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2142 dptr_close(&dptr_num);
2146 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2147 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2148 * the protocol level is less than NT1. Tested with smbclient. JRA.
2149 * This should fix the OS/2 client bug #2335.
2152 if(numentries == 0) {
2153 dptr_close(&dptr_num);
2154 if (Protocol < PROTOCOL_NT1) {
2155 reply_doserror(req, ERRDOS, ERRnofiles);
2156 return;
2157 } else {
2158 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2159 ERRDOS, ERRbadfile);
2160 return;
2164 /* At this point pdata points to numentries directory entries. */
2166 /* Set up the return parameter block */
2167 SSVAL(params,0,dptr_num);
2168 SSVAL(params,2,numentries);
2169 SSVAL(params,4,finished);
2170 SSVAL(params,6,0); /* Never an EA error */
2171 SSVAL(params,8,last_entry_off);
2173 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2174 max_data_bytes);
2176 if ((! *directory) && dptr_path(dptr_num)) {
2177 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2178 if (!directory) {
2179 reply_nterror(req, NT_STATUS_NO_MEMORY);
2183 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2184 smb_fn_name(CVAL(req->inbuf,smb_com)),
2185 mask, directory, dirtype, numentries ) );
2188 * Force a name mangle here to ensure that the
2189 * mask as an 8.3 name is top of the mangled cache.
2190 * The reasons for this are subtle. Don't remove
2191 * this code unless you know what you are doing
2192 * (see PR#13758). JRA.
2195 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2196 char mangled_name[13];
2197 name_to_8_3(mask, mangled_name, True, conn->params);
2200 return;
2203 /****************************************************************************
2204 Reply to a TRANS2_FINDNEXT.
2205 ****************************************************************************/
2207 static void call_trans2findnext(connection_struct *conn,
2208 struct smb_request *req,
2209 char **pparams, int total_params,
2210 char **ppdata, int total_data,
2211 unsigned int max_data_bytes)
2213 /* We must be careful here that we don't return more than the
2214 allowed number of data bytes. If this means returning fewer than
2215 maxentries then so be it. We assume that the redirector has
2216 enough room for the fixed number of parameter bytes it has
2217 requested. */
2218 char *params = *pparams;
2219 char *pdata = *ppdata;
2220 char *data_end;
2221 int dptr_num;
2222 int maxentries;
2223 uint16 info_level;
2224 uint32 resume_key;
2225 uint16 findnext_flags;
2226 bool close_after_request;
2227 bool close_if_end;
2228 bool requires_resume_key;
2229 bool continue_bit;
2230 bool mask_contains_wcard = False;
2231 char *resume_name = NULL;
2232 const char *mask = NULL;
2233 const char *directory = NULL;
2234 char *p = NULL;
2235 uint16 dirtype;
2236 int numentries = 0;
2237 int i, last_entry_off=0;
2238 bool finished = False;
2239 bool dont_descend = False;
2240 bool out_of_space = False;
2241 int space_remaining;
2242 struct ea_list *ea_list = NULL;
2243 NTSTATUS ntstatus = NT_STATUS_OK;
2244 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2245 TALLOC_CTX *ctx = talloc_tos();
2247 if (total_params < 13) {
2248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2249 return;
2252 dptr_num = SVAL(params,0);
2253 maxentries = SVAL(params,2);
2254 info_level = SVAL(params,4);
2255 resume_key = IVAL(params,6);
2256 findnext_flags = SVAL(params,10);
2257 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2258 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2259 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2260 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2262 if (!continue_bit) {
2263 /* We only need resume_name if continue_bit is zero. */
2264 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2265 params+12,
2266 total_params - 12, STR_TERMINATE, &ntstatus,
2267 &mask_contains_wcard);
2268 if (!NT_STATUS_IS_OK(ntstatus)) {
2269 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2270 complain (it thinks we're asking for the directory above the shared
2271 path or an invalid name). Catch this as the resume name is only compared, never used in
2272 a file access. JRA. */
2273 srvstr_pull_talloc(ctx, params, req->flags2,
2274 &resume_name, params+12,
2275 total_params - 12,
2276 STR_TERMINATE);
2278 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2279 reply_nterror(req, ntstatus);
2280 return;
2285 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2286 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2287 resume_key = %d resume name = %s continue=%d level = %d\n",
2288 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2289 requires_resume_key, resume_key,
2290 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2292 if (!maxentries) {
2293 /* W2K3 seems to treat zero as 1. */
2294 maxentries = 1;
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307 break;
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2314 return;
2316 break;
2317 default:
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 return;
2322 if (info_level == SMB_FIND_EA_LIST) {
2323 uint32 ea_size;
2325 if (total_data < 4) {
2326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2327 return;
2330 ea_size = IVAL(pdata,0);
2331 if (ea_size != total_data) {
2332 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335 return;
2338 if (!lp_ea_support(SNUM(conn))) {
2339 reply_doserror(req, ERRDOS, ERReasnotsupported);
2340 return;
2343 /* Pull out the list of names. */
2344 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2345 if (!ea_list) {
2346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2347 return;
2351 *ppdata = (char *)SMB_REALLOC(
2352 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2353 if(*ppdata == NULL) {
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2355 return;
2358 pdata = *ppdata;
2359 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2361 /* Realloc the params space */
2362 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2363 if(*pparams == NULL ) {
2364 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365 return;
2368 params = *pparams;
2370 /* Check that the dptr is valid */
2371 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2373 return;
2376 string_set(&conn->dirpath,dptr_path(dptr_num));
2378 /* Get the wildcard mask from the dptr */
2379 if((p = dptr_wcard(dptr_num))== NULL) {
2380 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2381 reply_doserror(req, ERRDOS, ERRnofiles);
2382 return;
2385 mask = p;
2386 directory = conn->dirpath;
2388 /* Get the attr mask from the dptr */
2389 dirtype = dptr_attr(dptr_num);
2391 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2392 dptr_num, mask, dirtype,
2393 (long)conn->dirptr,
2394 dptr_TellDir(conn->dirptr)));
2396 /* We don't need to check for VOL here as this is returned by
2397 a different TRANS2 call. */
2399 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2400 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2401 dont_descend = True;
2403 p = pdata;
2404 space_remaining = max_data_bytes;
2405 out_of_space = False;
2408 * Seek to the correct position. We no longer use the resume key but
2409 * depend on the last file name instead.
2412 if(!continue_bit && resume_name && *resume_name) {
2413 SMB_STRUCT_STAT st;
2415 long current_pos = 0;
2417 * Remember, name_to_8_3 is called by
2418 * get_lanman2_dir_entry(), so the resume name
2419 * could be mangled. Ensure we check the unmangled name.
2422 if (mangle_is_mangled(resume_name, conn->params)) {
2423 char *new_resume_name = NULL;
2424 mangle_lookup_name_from_8_3(ctx,
2425 resume_name,
2426 &new_resume_name,
2427 conn->params);
2428 if (new_resume_name) {
2429 resume_name = new_resume_name;
2434 * Fix for NT redirector problem triggered by resume key indexes
2435 * changing between directory scans. We now return a resume key of 0
2436 * and instead look for the filename to continue from (also given
2437 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2438 * findfirst/findnext (as is usual) then the directory pointer
2439 * should already be at the correct place.
2442 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2443 } /* end if resume_name && !continue_bit */
2445 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2446 bool got_exact_match = False;
2448 /* this is a heuristic to avoid seeking the dirptr except when
2449 absolutely necessary. It allows for a filename of about 40 chars */
2450 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2451 out_of_space = True;
2452 finished = False;
2453 } else {
2454 finished = !get_lanman2_dir_entry(ctx,
2455 conn,
2456 req->flags2,
2457 mask,dirtype,info_level,
2458 requires_resume_key,dont_descend,
2459 ask_sharemode,
2460 &p,pdata,data_end,
2461 space_remaining, &out_of_space,
2462 &got_exact_match,
2463 &last_entry_off, ea_list);
2466 if (finished && out_of_space)
2467 finished = False;
2469 if (!finished && !out_of_space)
2470 numentries++;
2473 * As an optimisation if we know we aren't looking
2474 * for a wildcard name (ie. the name matches the wildcard exactly)
2475 * then we can finish on any (first) match.
2476 * This speeds up large directory searches. JRA.
2479 if(got_exact_match)
2480 finished = True;
2482 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2485 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2486 smb_fn_name(CVAL(req->inbuf,smb_com)),
2487 mask, directory, dirtype, numentries ) );
2489 /* Check if we can close the dirptr */
2490 if(close_after_request || (finished && close_if_end)) {
2491 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2492 dptr_close(&dptr_num); /* This frees up the saved mask */
2495 /* Set up the return parameter block */
2496 SSVAL(params,0,numentries);
2497 SSVAL(params,2,finished);
2498 SSVAL(params,4,0); /* Never an EA error */
2499 SSVAL(params,6,last_entry_off);
2501 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2502 max_data_bytes);
2504 return;
2507 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2509 E_md4hash(lp_servicename(SNUM(conn)),objid);
2510 return objid;
2513 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2515 SMB_ASSERT(extended_info != NULL);
2517 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2518 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2519 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2520 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2521 #ifdef SAMBA_VERSION_REVISION
2522 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2523 #endif
2524 extended_info->samba_subversion = 0;
2525 #ifdef SAMBA_VERSION_RC_RELEASE
2526 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2527 #else
2528 #ifdef SAMBA_VERSION_PRE_RELEASE
2529 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2530 #endif
2531 #endif
2532 #ifdef SAMBA_VERSION_VENDOR_PATCH
2533 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2534 #endif
2535 extended_info->samba_gitcommitdate = 0;
2536 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2537 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2538 #endif
2540 memset(extended_info->samba_version_string, 0,
2541 sizeof(extended_info->samba_version_string));
2543 snprintf (extended_info->samba_version_string,
2544 sizeof(extended_info->samba_version_string),
2545 "%s", samba_version_string());
2548 /****************************************************************************
2549 Reply to a TRANS2_QFSINFO (query filesystem info).
2550 ****************************************************************************/
2552 static void call_trans2qfsinfo(connection_struct *conn,
2553 struct smb_request *req,
2554 char **pparams, int total_params,
2555 char **ppdata, int total_data,
2556 unsigned int max_data_bytes)
2558 char *pdata, *end_data;
2559 char *params = *pparams;
2560 uint16 info_level;
2561 int data_len, len;
2562 SMB_STRUCT_STAT st;
2563 const char *vname = volume_label(SNUM(conn));
2564 int snum = SNUM(conn);
2565 char *fstype = lp_fstype(SNUM(conn));
2566 uint32 additional_flags = 0;
2568 if (total_params < 2) {
2569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2570 return;
2573 info_level = SVAL(params,0);
2575 if (IS_IPC(conn)) {
2576 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2577 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2578 "info level (0x%x) on IPC$.\n",
2579 (unsigned int)info_level));
2580 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2581 return;
2585 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2586 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2587 DEBUG(0,("call_trans2qfsinfo: encryption required "
2588 "and info level 0x%x sent.\n",
2589 (unsigned int)info_level));
2590 exit_server_cleanly("encryption required "
2591 "on connection");
2592 return;
2596 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2598 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2599 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2600 reply_doserror(req, ERRSRV, ERRinvdevice);
2601 return;
2604 *ppdata = (char *)SMB_REALLOC(
2605 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2606 if (*ppdata == NULL ) {
2607 reply_nterror(req, NT_STATUS_NO_MEMORY);
2608 return;
2611 pdata = *ppdata;
2612 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2613 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2615 switch (info_level) {
2616 case SMB_INFO_ALLOCATION:
2618 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2619 data_len = 18;
2620 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2621 reply_unixerror(req, ERRHRD, ERRgeneral);
2622 return;
2625 block_size = lp_block_size(snum);
2626 if (bsize < block_size) {
2627 SMB_BIG_UINT factor = block_size/bsize;
2628 bsize = block_size;
2629 dsize /= factor;
2630 dfree /= factor;
2632 if (bsize > block_size) {
2633 SMB_BIG_UINT factor = bsize/block_size;
2634 bsize = block_size;
2635 dsize *= factor;
2636 dfree *= factor;
2638 bytes_per_sector = 512;
2639 sectors_per_unit = bsize/bytes_per_sector;
2641 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2642 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2643 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2645 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2646 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2647 SIVAL(pdata,l1_cUnit,dsize);
2648 SIVAL(pdata,l1_cUnitAvail,dfree);
2649 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2650 break;
2653 case SMB_INFO_VOLUME:
2654 /* Return volume name */
2656 * Add volume serial number - hash of a combination of
2657 * the called hostname and the service name.
2659 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2661 * Win2k3 and previous mess this up by sending a name length
2662 * one byte short. I believe only older clients (OS/2 Win9x) use
2663 * this call so try fixing this by adding a terminating null to
2664 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2666 len = srvstr_push(
2667 pdata, req->flags2,
2668 pdata+l2_vol_szVolLabel, vname,
2669 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2670 STR_NOALIGN|STR_TERMINATE);
2671 SCVAL(pdata,l2_vol_cch,len);
2672 data_len = l2_vol_szVolLabel + len;
2673 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2674 (unsigned)st.st_ctime, len, vname));
2675 break;
2677 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2678 case SMB_FS_ATTRIBUTE_INFORMATION:
2680 additional_flags = 0;
2681 #if defined(HAVE_SYS_QUOTAS)
2682 additional_flags |= FILE_VOLUME_QUOTAS;
2683 #endif
2685 if(lp_nt_acl_support(SNUM(conn))) {
2686 additional_flags |= FILE_PERSISTENT_ACLS;
2689 /* Capabilities are filled in at connection time through STATVFS call */
2690 additional_flags |= conn->fs_capabilities;
2692 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2693 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2694 additional_flags); /* FS ATTRIBUTES */
2696 SIVAL(pdata,4,255); /* Max filename component length */
2697 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2698 and will think we can't do long filenames */
2699 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2700 PTR_DIFF(end_data, pdata+12),
2701 STR_UNICODE);
2702 SIVAL(pdata,8,len);
2703 data_len = 12 + len;
2704 break;
2706 case SMB_QUERY_FS_LABEL_INFO:
2707 case SMB_FS_LABEL_INFORMATION:
2708 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2709 PTR_DIFF(end_data, pdata+4), 0);
2710 data_len = 4 + len;
2711 SIVAL(pdata,0,len);
2712 break;
2714 case SMB_QUERY_FS_VOLUME_INFO:
2715 case SMB_FS_VOLUME_INFORMATION:
2718 * Add volume serial number - hash of a combination of
2719 * the called hostname and the service name.
2721 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2722 (str_checksum(get_local_machine_name())<<16));
2724 /* Max label len is 32 characters. */
2725 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2726 PTR_DIFF(end_data, pdata+18),
2727 STR_UNICODE);
2728 SIVAL(pdata,12,len);
2729 data_len = 18+len;
2731 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2732 (int)strlen(vname),vname, lp_servicename(snum)));
2733 break;
2735 case SMB_QUERY_FS_SIZE_INFO:
2736 case SMB_FS_SIZE_INFORMATION:
2738 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2739 data_len = 24;
2740 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2741 reply_unixerror(req, ERRHRD, ERRgeneral);
2742 return;
2744 block_size = lp_block_size(snum);
2745 if (bsize < block_size) {
2746 SMB_BIG_UINT factor = block_size/bsize;
2747 bsize = block_size;
2748 dsize /= factor;
2749 dfree /= factor;
2751 if (bsize > block_size) {
2752 SMB_BIG_UINT factor = bsize/block_size;
2753 bsize = block_size;
2754 dsize *= factor;
2755 dfree *= factor;
2757 bytes_per_sector = 512;
2758 sectors_per_unit = bsize/bytes_per_sector;
2759 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2760 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2761 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2762 SBIG_UINT(pdata,0,dsize);
2763 SBIG_UINT(pdata,8,dfree);
2764 SIVAL(pdata,16,sectors_per_unit);
2765 SIVAL(pdata,20,bytes_per_sector);
2766 break;
2769 case SMB_FS_FULL_SIZE_INFORMATION:
2771 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2772 data_len = 32;
2773 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2774 reply_unixerror(req, ERRHRD, ERRgeneral);
2775 return;
2777 block_size = lp_block_size(snum);
2778 if (bsize < block_size) {
2779 SMB_BIG_UINT factor = block_size/bsize;
2780 bsize = block_size;
2781 dsize /= factor;
2782 dfree /= factor;
2784 if (bsize > block_size) {
2785 SMB_BIG_UINT factor = bsize/block_size;
2786 bsize = block_size;
2787 dsize *= factor;
2788 dfree *= factor;
2790 bytes_per_sector = 512;
2791 sectors_per_unit = bsize/bytes_per_sector;
2792 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2793 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2794 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2795 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2796 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2797 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2798 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2799 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2800 break;
2803 case SMB_QUERY_FS_DEVICE_INFO:
2804 case SMB_FS_DEVICE_INFORMATION:
2805 data_len = 8;
2806 SIVAL(pdata,0,0); /* dev type */
2807 SIVAL(pdata,4,0); /* characteristics */
2808 break;
2810 #ifdef HAVE_SYS_QUOTAS
2811 case SMB_FS_QUOTA_INFORMATION:
2813 * what we have to send --metze:
2815 * Unknown1: 24 NULL bytes
2816 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2817 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2818 * Quota Flags: 2 byte :
2819 * Unknown3: 6 NULL bytes
2821 * 48 bytes total
2823 * details for Quota Flags:
2825 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2826 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2827 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2828 * 0x0001 Enable Quotas: enable quota for this fs
2832 /* we need to fake up a fsp here,
2833 * because its not send in this call
2835 files_struct fsp;
2836 SMB_NTQUOTA_STRUCT quotas;
2838 ZERO_STRUCT(fsp);
2839 ZERO_STRUCT(quotas);
2841 fsp.conn = conn;
2842 fsp.fnum = -1;
2844 /* access check */
2845 if (conn->server_info->utok.uid != 0) {
2846 DEBUG(0,("set_user_quota: access_denied "
2847 "service [%s] user [%s]\n",
2848 lp_servicename(SNUM(conn)),
2849 conn->server_info->unix_name));
2850 reply_doserror(req, ERRDOS, ERRnoaccess);
2851 return;
2854 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2855 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2856 reply_doserror(req, ERRSRV, ERRerror);
2857 return;
2860 data_len = 48;
2862 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2864 /* Unknown1 24 NULL bytes*/
2865 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2866 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2867 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2869 /* Default Soft Quota 8 bytes */
2870 SBIG_UINT(pdata,24,quotas.softlim);
2872 /* Default Hard Quota 8 bytes */
2873 SBIG_UINT(pdata,32,quotas.hardlim);
2875 /* Quota flag 2 bytes */
2876 SSVAL(pdata,40,quotas.qflags);
2878 /* Unknown3 6 NULL bytes */
2879 SSVAL(pdata,42,0);
2880 SIVAL(pdata,44,0);
2882 break;
2884 #endif /* HAVE_SYS_QUOTAS */
2885 case SMB_FS_OBJECTID_INFORMATION:
2887 unsigned char objid[16];
2888 struct smb_extended_info extended_info;
2889 memcpy(pdata,create_volume_objectid(conn, objid),16);
2890 samba_extended_info_version (&extended_info);
2891 SIVAL(pdata,16,extended_info.samba_magic);
2892 SIVAL(pdata,20,extended_info.samba_version);
2893 SIVAL(pdata,24,extended_info.samba_subversion);
2894 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2895 memcpy(pdata+36,extended_info.samba_version_string,28);
2896 data_len = 64;
2897 break;
2901 * Query the version and capabilities of the CIFS UNIX extensions
2902 * in use.
2905 case SMB_QUERY_CIFS_UNIX_INFO:
2907 bool large_write = lp_min_receive_file_size() &&
2908 !srv_is_signing_active();
2909 bool large_read = !srv_is_signing_active();
2910 int encrypt_caps = 0;
2912 if (!lp_unix_extensions()) {
2913 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2914 return;
2917 switch (conn->encrypt_level) {
2918 case 0:
2919 encrypt_caps = 0;
2920 break;
2921 case 1:
2922 case Auto:
2923 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2924 break;
2925 case Required:
2926 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2927 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2928 large_write = false;
2929 large_read = false;
2930 break;
2933 data_len = 12;
2934 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2935 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2937 /* We have POSIX ACLs, pathname, encryption,
2938 * large read/write, and locking capability. */
2940 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2941 CIFS_UNIX_POSIX_ACLS_CAP|
2942 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2943 CIFS_UNIX_FCNTL_LOCKS_CAP|
2944 CIFS_UNIX_EXTATTR_CAP|
2945 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2946 encrypt_caps|
2947 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2948 (large_write ?
2949 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2950 break;
2953 case SMB_QUERY_POSIX_FS_INFO:
2955 int rc;
2956 vfs_statvfs_struct svfs;
2958 if (!lp_unix_extensions()) {
2959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2960 return;
2963 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2965 if (!rc) {
2966 data_len = 56;
2967 SIVAL(pdata,0,svfs.OptimalTransferSize);
2968 SIVAL(pdata,4,svfs.BlockSize);
2969 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2970 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2971 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2972 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2973 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2974 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2975 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2976 #ifdef EOPNOTSUPP
2977 } else if (rc == EOPNOTSUPP) {
2978 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2979 return;
2980 #endif /* EOPNOTSUPP */
2981 } else {
2982 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2983 reply_doserror(req, ERRSRV, ERRerror);
2984 return;
2986 break;
2989 case SMB_QUERY_POSIX_WHOAMI:
2991 uint32_t flags = 0;
2992 uint32_t sid_bytes;
2993 int i;
2995 if (!lp_unix_extensions()) {
2996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2997 return;
3000 if (max_data_bytes < 40) {
3001 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3002 return;
3005 /* We ARE guest if global_sid_Builtin_Guests is
3006 * in our list of SIDs.
3008 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3009 conn->server_info->ptok)) {
3010 flags |= SMB_WHOAMI_GUEST;
3013 /* We are NOT guest if global_sid_Authenticated_Users
3014 * is in our list of SIDs.
3016 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3017 conn->server_info->ptok)) {
3018 flags &= ~SMB_WHOAMI_GUEST;
3021 /* NOTE: 8 bytes for UID/GID, irrespective of native
3022 * platform size. This matches
3023 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3025 data_len = 4 /* flags */
3026 + 4 /* flag mask */
3027 + 8 /* uid */
3028 + 8 /* gid */
3029 + 4 /* ngroups */
3030 + 4 /* num_sids */
3031 + 4 /* SID bytes */
3032 + 4 /* pad/reserved */
3033 + (conn->server_info->utok.ngroups * 8)
3034 /* groups list */
3035 + (conn->server_info->ptok->num_sids *
3036 SID_MAX_SIZE)
3037 /* SID list */;
3039 SIVAL(pdata, 0, flags);
3040 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3041 SBIG_UINT(pdata, 8,
3042 (SMB_BIG_UINT)conn->server_info->utok.uid);
3043 SBIG_UINT(pdata, 16,
3044 (SMB_BIG_UINT)conn->server_info->utok.gid);
3047 if (data_len >= max_data_bytes) {
3048 /* Potential overflow, skip the GIDs and SIDs. */
3050 SIVAL(pdata, 24, 0); /* num_groups */
3051 SIVAL(pdata, 28, 0); /* num_sids */
3052 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3053 SIVAL(pdata, 36, 0); /* reserved */
3055 data_len = 40;
3056 break;
3059 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3060 SIVAL(pdata, 28, conn->server_info->num_sids);
3062 /* We walk the SID list twice, but this call is fairly
3063 * infrequent, and I don't expect that it's performance
3064 * sensitive -- jpeach
3066 for (i = 0, sid_bytes = 0;
3067 i < conn->server_info->ptok->num_sids; ++i) {
3068 sid_bytes += ndr_size_dom_sid(
3069 &conn->server_info->ptok->user_sids[i],
3073 /* SID list byte count */
3074 SIVAL(pdata, 32, sid_bytes);
3076 /* 4 bytes pad/reserved - must be zero */
3077 SIVAL(pdata, 36, 0);
3078 data_len = 40;
3080 /* GID list */
3081 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3082 SBIG_UINT(pdata, data_len,
3083 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3084 data_len += 8;
3087 /* SID list */
3088 for (i = 0;
3089 i < conn->server_info->ptok->num_sids; ++i) {
3090 int sid_len = ndr_size_dom_sid(
3091 &conn->server_info->ptok->user_sids[i],
3094 sid_linearize(pdata + data_len, sid_len,
3095 &conn->server_info->ptok->user_sids[i]);
3096 data_len += sid_len;
3099 break;
3102 case SMB_MAC_QUERY_FS_INFO:
3104 * Thursby MAC extension... ONLY on NTFS filesystems
3105 * once we do streams then we don't need this
3107 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3108 data_len = 88;
3109 SIVAL(pdata,84,0x100); /* Don't support mac... */
3110 break;
3112 /* drop through */
3113 default:
3114 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3115 return;
3119 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3120 max_data_bytes);
3122 DEBUG( 4, ( "%s info_level = %d\n",
3123 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3125 return;
3128 /****************************************************************************
3129 Reply to a TRANS2_SETFSINFO (set filesystem info).
3130 ****************************************************************************/
3132 static void call_trans2setfsinfo(connection_struct *conn,
3133 struct smb_request *req,
3134 char **pparams, int total_params,
3135 char **ppdata, int total_data,
3136 unsigned int max_data_bytes)
3138 char *pdata = *ppdata;
3139 char *params = *pparams;
3140 uint16 info_level;
3142 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3144 /* */
3145 if (total_params < 4) {
3146 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3147 total_params));
3148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3149 return;
3152 info_level = SVAL(params,2);
3154 if (IS_IPC(conn)) {
3155 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3156 info_level != SMB_SET_CIFS_UNIX_INFO) {
3157 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3158 "info level (0x%x) on IPC$.\n",
3159 (unsigned int)info_level));
3160 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3161 return;
3165 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3166 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3167 DEBUG(0,("call_trans2setfsinfo: encryption required "
3168 "and info level 0x%x sent.\n",
3169 (unsigned int)info_level));
3170 exit_server_cleanly("encryption required "
3171 "on connection");
3172 return;
3176 switch(info_level) {
3177 case SMB_SET_CIFS_UNIX_INFO:
3179 uint16 client_unix_major;
3180 uint16 client_unix_minor;
3181 uint32 client_unix_cap_low;
3182 uint32 client_unix_cap_high;
3184 if (!lp_unix_extensions()) {
3185 reply_nterror(req,
3186 NT_STATUS_INVALID_LEVEL);
3187 return;
3190 /* There should be 12 bytes of capabilities set. */
3191 if (total_data < 8) {
3192 reply_nterror(
3193 req,
3194 NT_STATUS_INVALID_PARAMETER);
3195 return;
3197 client_unix_major = SVAL(pdata,0);
3198 client_unix_minor = SVAL(pdata,2);
3199 client_unix_cap_low = IVAL(pdata,4);
3200 client_unix_cap_high = IVAL(pdata,8);
3201 /* Just print these values for now. */
3202 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3203 cap_low = 0x%x, cap_high = 0x%x\n",
3204 (unsigned int)client_unix_major,
3205 (unsigned int)client_unix_minor,
3206 (unsigned int)client_unix_cap_low,
3207 (unsigned int)client_unix_cap_high ));
3209 /* Here is where we must switch to posix pathname processing... */
3210 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3211 lp_set_posix_pathnames();
3212 mangle_change_to_posix();
3215 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3216 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3217 /* Client that knows how to do posix locks,
3218 * but not posix open/mkdir operations. Set a
3219 * default type for read/write checks. */
3221 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3224 break;
3227 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3229 NTSTATUS status;
3230 size_t param_len = 0;
3231 size_t data_len = total_data;
3233 if (!lp_unix_extensions()) {
3234 reply_nterror(
3235 req,
3236 NT_STATUS_INVALID_LEVEL);
3237 return;
3240 if (lp_smb_encrypt(SNUM(conn)) == false) {
3241 reply_nterror(
3242 req,
3243 NT_STATUS_NOT_SUPPORTED);
3244 return;
3247 DEBUG( 4,("call_trans2setfsinfo: "
3248 "request transport encryption.\n"));
3250 status = srv_request_encryption_setup(conn,
3251 (unsigned char **)ppdata,
3252 &data_len,
3253 (unsigned char **)pparams,
3254 &param_len);
3256 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3257 !NT_STATUS_IS_OK(status)) {
3258 reply_nterror(req, status);
3259 return;
3262 send_trans2_replies(conn, req,
3263 *pparams,
3264 param_len,
3265 *ppdata,
3266 data_len,
3267 max_data_bytes);
3269 if (NT_STATUS_IS_OK(status)) {
3270 /* Server-side transport
3271 * encryption is now *on*. */
3272 status = srv_encryption_start(conn);
3273 if (!NT_STATUS_IS_OK(status)) {
3274 exit_server_cleanly(
3275 "Failure in setting "
3276 "up encrypted transport");
3279 return;
3282 case SMB_FS_QUOTA_INFORMATION:
3284 files_struct *fsp = NULL;
3285 SMB_NTQUOTA_STRUCT quotas;
3287 ZERO_STRUCT(quotas);
3289 /* access check */
3290 if ((conn->server_info->utok.uid != 0)
3291 ||!CAN_WRITE(conn)) {
3292 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3293 lp_servicename(SNUM(conn)),
3294 conn->server_info->unix_name));
3295 reply_doserror(req, ERRSRV, ERRaccess);
3296 return;
3299 /* note: normaly there're 48 bytes,
3300 * but we didn't use the last 6 bytes for now
3301 * --metze
3303 fsp = file_fsp(SVAL(params,0));
3305 if (!check_fsp_ntquota_handle(conn, req,
3306 fsp)) {
3307 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3308 reply_nterror(
3309 req, NT_STATUS_INVALID_HANDLE);
3310 return;
3313 if (total_data < 42) {
3314 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3315 total_data));
3316 reply_nterror(
3317 req,
3318 NT_STATUS_INVALID_PARAMETER);
3319 return;
3322 /* unknown_1 24 NULL bytes in pdata*/
3324 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3325 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3326 #ifdef LARGE_SMB_OFF_T
3327 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3328 #else /* LARGE_SMB_OFF_T */
3329 if ((IVAL(pdata,28) != 0)&&
3330 ((quotas.softlim != 0xFFFFFFFF)||
3331 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3332 /* more than 32 bits? */
3333 reply_nterror(
3334 req,
3335 NT_STATUS_INVALID_PARAMETER);
3336 return;
3338 #endif /* LARGE_SMB_OFF_T */
3340 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3341 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3342 #ifdef LARGE_SMB_OFF_T
3343 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3344 #else /* LARGE_SMB_OFF_T */
3345 if ((IVAL(pdata,36) != 0)&&
3346 ((quotas.hardlim != 0xFFFFFFFF)||
3347 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3348 /* more than 32 bits? */
3349 reply_nterror(
3350 req,
3351 NT_STATUS_INVALID_PARAMETER);
3352 return;
3354 #endif /* LARGE_SMB_OFF_T */
3356 /* quota_flags 2 bytes **/
3357 quotas.qflags = SVAL(pdata,40);
3359 /* unknown_2 6 NULL bytes follow*/
3361 /* now set the quotas */
3362 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3363 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3364 reply_doserror(req, ERRSRV, ERRerror);
3365 return;
3368 break;
3370 default:
3371 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3372 info_level));
3373 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3374 return;
3375 break;
3379 * sending this reply works fine,
3380 * but I'm not sure it's the same
3381 * like windows do...
3382 * --metze
3384 reply_outbuf(req, 10, 0);
3387 #if defined(HAVE_POSIX_ACLS)
3388 /****************************************************************************
3389 Utility function to count the number of entries in a POSIX acl.
3390 ****************************************************************************/
3392 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3394 unsigned int ace_count = 0;
3395 int entry_id = SMB_ACL_FIRST_ENTRY;
3396 SMB_ACL_ENTRY_T entry;
3398 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3399 /* get_next... */
3400 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3401 entry_id = SMB_ACL_NEXT_ENTRY;
3403 ace_count++;
3405 return ace_count;
3408 /****************************************************************************
3409 Utility function to marshall a POSIX acl into wire format.
3410 ****************************************************************************/
3412 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3414 int entry_id = SMB_ACL_FIRST_ENTRY;
3415 SMB_ACL_ENTRY_T entry;
3417 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3418 SMB_ACL_TAG_T tagtype;
3419 SMB_ACL_PERMSET_T permset;
3420 unsigned char perms = 0;
3421 unsigned int own_grp;
3423 /* get_next... */
3424 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3425 entry_id = SMB_ACL_NEXT_ENTRY;
3428 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3429 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3430 return False;
3433 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3435 return False;
3438 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3439 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3440 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3442 SCVAL(pdata,1,perms);
3444 switch (tagtype) {
3445 case SMB_ACL_USER_OBJ:
3446 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3447 own_grp = (unsigned int)pst->st_uid;
3448 SIVAL(pdata,2,own_grp);
3449 SIVAL(pdata,6,0);
3450 break;
3451 case SMB_ACL_USER:
3453 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3454 if (!puid) {
3455 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3456 return False;
3458 own_grp = (unsigned int)*puid;
3459 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3460 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3461 SIVAL(pdata,2,own_grp);
3462 SIVAL(pdata,6,0);
3463 break;
3465 case SMB_ACL_GROUP_OBJ:
3466 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3467 own_grp = (unsigned int)pst->st_gid;
3468 SIVAL(pdata,2,own_grp);
3469 SIVAL(pdata,6,0);
3470 break;
3471 case SMB_ACL_GROUP:
3473 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3474 if (!pgid) {
3475 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3476 return False;
3478 own_grp = (unsigned int)*pgid;
3479 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3480 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3481 SIVAL(pdata,2,own_grp);
3482 SIVAL(pdata,6,0);
3483 break;
3485 case SMB_ACL_MASK:
3486 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3487 SIVAL(pdata,2,0xFFFFFFFF);
3488 SIVAL(pdata,6,0xFFFFFFFF);
3489 break;
3490 case SMB_ACL_OTHER:
3491 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3492 SIVAL(pdata,2,0xFFFFFFFF);
3493 SIVAL(pdata,6,0xFFFFFFFF);
3494 break;
3495 default:
3496 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3497 return False;
3499 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3502 return True;
3504 #endif
3506 /****************************************************************************
3507 Store the FILE_UNIX_BASIC info.
3508 ****************************************************************************/
3510 static char *store_file_unix_basic(connection_struct *conn,
3511 char *pdata,
3512 files_struct *fsp,
3513 const SMB_STRUCT_STAT *psbuf)
3515 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3516 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3518 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3519 pdata += 8;
3521 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3522 pdata += 8;
3524 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3525 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3526 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3527 pdata += 24;
3529 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3530 SIVAL(pdata,4,0);
3531 pdata += 8;
3533 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3534 SIVAL(pdata,4,0);
3535 pdata += 8;
3537 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3538 pdata += 4;
3540 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3541 SIVAL(pdata,4,0);
3542 pdata += 8;
3544 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3545 SIVAL(pdata,4,0);
3546 pdata += 8;
3548 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3549 pdata += 8;
3551 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3552 SIVAL(pdata,4,0);
3553 pdata += 8;
3555 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3556 SIVAL(pdata,4,0);
3557 pdata += 8;
3559 return pdata;
3562 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3563 * the chflags(2) (or equivalent) flags.
3565 * XXX: this really should be behind the VFS interface. To do this, we would
3566 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3567 * Each VFS module could then implement its own mapping as appropriate for the
3568 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3570 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3571 info2_flags_map[] =
3573 #ifdef UF_NODUMP
3574 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3575 #endif
3577 #ifdef UF_IMMUTABLE
3578 { UF_IMMUTABLE, EXT_IMMUTABLE },
3579 #endif
3581 #ifdef UF_APPEND
3582 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3583 #endif
3585 #ifdef UF_HIDDEN
3586 { UF_HIDDEN, EXT_HIDDEN },
3587 #endif
3589 /* Do not remove. We need to guarantee that this array has at least one
3590 * entry to build on HP-UX.
3592 { 0, 0 }
3596 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3597 uint32 *smb_fflags, uint32 *smb_fmask)
3599 #ifdef HAVE_STAT_ST_FLAGS
3600 int i;
3602 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3603 *smb_fmask |= info2_flags_map[i].smb_fflag;
3604 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3605 *smb_fflags |= info2_flags_map[i].smb_fflag;
3608 #endif /* HAVE_STAT_ST_FLAGS */
3611 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3612 const uint32 smb_fflags,
3613 const uint32 smb_fmask,
3614 int *stat_fflags)
3616 #ifdef HAVE_STAT_ST_FLAGS
3617 uint32 max_fmask = 0;
3618 int i;
3620 *stat_fflags = psbuf->st_flags;
3622 /* For each flags requested in smb_fmask, check the state of the
3623 * corresponding flag in smb_fflags and set or clear the matching
3624 * stat flag.
3627 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3628 max_fmask |= info2_flags_map[i].smb_fflag;
3629 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3630 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3631 *stat_fflags |= info2_flags_map[i].stat_fflag;
3632 } else {
3633 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3638 /* If smb_fmask is asking to set any bits that are not supported by
3639 * our flag mappings, we should fail.
3641 if ((smb_fmask & max_fmask) != smb_fmask) {
3642 return False;
3645 return True;
3646 #else
3647 return False;
3648 #endif /* HAVE_STAT_ST_FLAGS */
3652 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3653 * of file flags and birth (create) time.
3655 static char *store_file_unix_basic_info2(connection_struct *conn,
3656 char *pdata,
3657 files_struct *fsp,
3658 const SMB_STRUCT_STAT *psbuf)
3660 uint32 file_flags = 0;
3661 uint32 flags_mask = 0;
3663 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3665 /* Create (birth) time 64 bit */
3666 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3667 pdata += 8;
3669 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3670 SIVAL(pdata, 0, file_flags); /* flags */
3671 SIVAL(pdata, 4, flags_mask); /* mask */
3672 pdata += 8;
3674 return pdata;
3677 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3678 const struct stream_struct *streams,
3679 char *data,
3680 unsigned int max_data_bytes,
3681 unsigned int *data_size)
3683 unsigned int i;
3684 unsigned int ofs = 0;
3686 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3687 unsigned int next_offset;
3688 size_t namelen;
3689 smb_ucs2_t *namebuf;
3691 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3692 streams[i].name, &namelen) ||
3693 namelen <= 2)
3695 return NT_STATUS_INVALID_PARAMETER;
3699 * name_buf is now null-terminated, we need to marshall as not
3700 * terminated
3703 namelen -= 2;
3705 SIVAL(data, ofs+4, namelen);
3706 SOFF_T(data, ofs+8, streams[i].size);
3707 SOFF_T(data, ofs+16, streams[i].alloc_size);
3708 memcpy(data+ofs+24, namebuf, namelen);
3709 TALLOC_FREE(namebuf);
3711 next_offset = ofs + 24 + namelen;
3713 if (i == num_streams-1) {
3714 SIVAL(data, ofs, 0);
3716 else {
3717 unsigned int align = ndr_align_size(next_offset, 8);
3719 memset(data+next_offset, 0, align);
3720 next_offset += align;
3722 SIVAL(data, ofs, next_offset - ofs);
3723 ofs = next_offset;
3726 ofs = next_offset;
3729 *data_size = ofs;
3731 return NT_STATUS_OK;
3734 /****************************************************************************
3735 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3736 ****************************************************************************/
3738 static void call_trans2qpipeinfo(connection_struct *conn,
3739 struct smb_request *req,
3740 unsigned int tran_call,
3741 char **pparams, int total_params,
3742 char **ppdata, int total_data,
3743 unsigned int max_data_bytes)
3745 char *params = *pparams;
3746 char *pdata = *ppdata;
3747 unsigned int data_size = 0;
3748 unsigned int param_size = 2;
3749 uint16 info_level;
3750 smb_np_struct *p_pipe = NULL;
3752 if (!params) {
3753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3754 return;
3757 if (total_params < 4) {
3758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3759 return;
3762 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3763 if (p_pipe == NULL) {
3764 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3765 return;
3768 info_level = SVAL(params,2);
3770 *pparams = (char *)SMB_REALLOC(*pparams,2);
3771 if (*pparams == NULL) {
3772 reply_nterror(req, NT_STATUS_NO_MEMORY);
3773 return;
3775 params = *pparams;
3776 SSVAL(params,0,0);
3777 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3778 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3779 if (*ppdata == NULL ) {
3780 reply_nterror(req, NT_STATUS_NO_MEMORY);
3781 return;
3783 pdata = *ppdata;
3785 switch (info_level) {
3786 case SMB_FILE_STANDARD_INFORMATION:
3787 memset(pdata,0,24);
3788 SOFF_T(pdata,0,4096LL);
3789 SIVAL(pdata,16,1);
3790 SIVAL(pdata,20,1);
3791 data_size = 24;
3792 break;
3794 default:
3795 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3796 return;
3799 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3800 max_data_bytes);
3802 return;
3805 /****************************************************************************
3806 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3807 file name or file id).
3808 ****************************************************************************/
3810 static void call_trans2qfilepathinfo(connection_struct *conn,
3811 struct smb_request *req,
3812 unsigned int tran_call,
3813 char **pparams, int total_params,
3814 char **ppdata, int total_data,
3815 unsigned int max_data_bytes)
3817 char *params = *pparams;
3818 char *pdata = *ppdata;
3819 char *dstart, *dend;
3820 uint16 info_level;
3821 int mode=0;
3822 int nlink;
3823 SMB_OFF_T file_size=0;
3824 SMB_BIG_UINT allocation_size=0;
3825 unsigned int data_size = 0;
3826 unsigned int param_size = 2;
3827 SMB_STRUCT_STAT sbuf;
3828 char *dos_fname = NULL;
3829 char *fname = NULL;
3830 char *fullpathname;
3831 char *base_name;
3832 char *p;
3833 SMB_OFF_T pos = 0;
3834 bool delete_pending = False;
3835 int len;
3836 time_t create_time, mtime, atime;
3837 struct timespec create_time_ts, mtime_ts, atime_ts;
3838 struct timespec write_time_ts;
3839 files_struct *fsp = NULL;
3840 struct file_id fileid;
3841 struct ea_list *ea_list = NULL;
3842 char *lock_data = NULL;
3843 bool ms_dfs_link = false;
3844 TALLOC_CTX *ctx = talloc_tos();
3846 if (!params) {
3847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3848 return;
3851 ZERO_STRUCT(sbuf);
3852 ZERO_STRUCT(write_time_ts);
3854 if (tran_call == TRANSACT2_QFILEINFO) {
3855 if (total_params < 4) {
3856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3857 return;
3860 if (IS_IPC(conn)) {
3861 call_trans2qpipeinfo(conn, req, tran_call,
3862 pparams, total_params,
3863 ppdata, total_data,
3864 max_data_bytes);
3865 return;
3868 fsp = file_fsp(SVAL(params,0));
3869 info_level = SVAL(params,2);
3871 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3873 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3874 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3875 return;
3878 /* Initial check for valid fsp ptr. */
3879 if (!check_fsp_open(conn, req, fsp)) {
3880 return;
3883 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3884 if (!fname) {
3885 reply_nterror(req, NT_STATUS_NO_MEMORY);
3886 return;
3889 if(fsp->fake_file_handle) {
3891 * This is actually for the QUOTA_FAKE_FILE --metze
3894 /* We know this name is ok, it's already passed the checks. */
3896 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3898 * This is actually a QFILEINFO on a directory
3899 * handle (returned from an NT SMB). NT5.0 seems
3900 * to do this call. JRA.
3903 if (INFO_LEVEL_IS_UNIX(info_level)) {
3904 /* Always do lstat for UNIX calls. */
3905 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3906 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3907 reply_unixerror(req,ERRDOS,ERRbadpath);
3908 return;
3910 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3911 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3912 reply_unixerror(req, ERRDOS, ERRbadpath);
3913 return;
3916 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3917 get_file_infos(fileid, &delete_pending, &write_time_ts);
3918 } else {
3920 * Original code - this is an open file.
3922 if (!check_fsp(conn, req, fsp)) {
3923 return;
3926 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3927 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3928 reply_unixerror(req, ERRDOS, ERRbadfid);
3929 return;
3931 pos = fsp->fh->position_information;
3932 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3933 get_file_infos(fileid, &delete_pending, &write_time_ts);
3936 } else {
3937 NTSTATUS status = NT_STATUS_OK;
3939 /* qpathinfo */
3940 if (total_params < 7) {
3941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3942 return;
3945 info_level = SVAL(params,0);
3947 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3949 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3951 return;
3954 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3955 total_params - 6,
3956 STR_TERMINATE, &status);
3957 if (!NT_STATUS_IS_OK(status)) {
3958 reply_nterror(req, status);
3959 return;
3962 status = resolve_dfspath(ctx,
3963 conn,
3964 req->flags2 & FLAGS2_DFS_PATHNAMES,
3965 fname,
3966 &fname);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3969 reply_botherror(req,
3970 NT_STATUS_PATH_NOT_COVERED,
3971 ERRSRV, ERRbadpath);
3973 reply_nterror(req, status);
3974 return;
3977 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3978 if (!NT_STATUS_IS_OK(status)) {
3979 reply_nterror(req, status);
3980 return;
3982 status = check_name(conn, fname);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3985 reply_nterror(req, status);
3986 return;
3989 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3990 && is_ntfs_stream_name(fname)) {
3991 char *base;
3992 SMB_STRUCT_STAT bsbuf;
3994 status = split_ntfs_stream_name(talloc_tos(), fname,
3995 &base, NULL);
3996 if (!NT_STATUS_IS_OK(status)) {
3997 DEBUG(10, ("create_file_unixpath: "
3998 "split_ntfs_stream_name failed: %s\n",
3999 nt_errstr(status)));
4000 reply_nterror(req, status);
4001 return;
4004 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4006 if (INFO_LEVEL_IS_UNIX(info_level)) {
4007 /* Always do lstat for UNIX calls. */
4008 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4009 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4010 reply_unixerror(req,ERRDOS,ERRbadpath);
4011 return;
4013 } else {
4014 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4015 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4016 reply_unixerror(req,ERRDOS,ERRbadpath);
4017 return;
4021 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4022 get_file_infos(fileid, &delete_pending, NULL);
4023 if (delete_pending) {
4024 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4025 return;
4029 if (INFO_LEVEL_IS_UNIX(info_level)) {
4030 /* Always do lstat for UNIX calls. */
4031 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4032 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4033 reply_unixerror(req, ERRDOS, ERRbadpath);
4034 return;
4037 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4038 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4040 if (!ms_dfs_link) {
4041 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4042 reply_unixerror(req, ERRDOS, ERRbadpath);
4043 return;
4047 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4048 get_file_infos(fileid, &delete_pending, &write_time_ts);
4049 if (delete_pending) {
4050 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4051 return;
4055 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4056 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4057 return;
4060 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4061 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4063 p = strrchr_m(fname,'/');
4064 if (!p)
4065 base_name = fname;
4066 else
4067 base_name = p+1;
4069 if (ms_dfs_link) {
4070 mode = dos_mode_msdfs(conn,fname,&sbuf);
4071 } else {
4072 mode = dos_mode(conn,fname,&sbuf);
4074 if (!mode)
4075 mode = FILE_ATTRIBUTE_NORMAL;
4077 nlink = sbuf.st_nlink;
4079 if (nlink && (mode&aDIR)) {
4080 nlink = 1;
4083 if ((nlink > 0) && delete_pending) {
4084 nlink -= 1;
4087 fullpathname = fname;
4088 if (!(mode & aDIR))
4089 file_size = get_file_size(sbuf);
4091 /* Pull out any data sent here before we realloc. */
4092 switch (info_level) {
4093 case SMB_INFO_QUERY_EAS_FROM_LIST:
4095 /* Pull any EA list from the data portion. */
4096 uint32 ea_size;
4098 if (total_data < 4) {
4099 reply_nterror(
4100 req, NT_STATUS_INVALID_PARAMETER);
4101 return;
4103 ea_size = IVAL(pdata,0);
4105 if (total_data > 0 && ea_size != total_data) {
4106 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4107 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4108 reply_nterror(
4109 req, NT_STATUS_INVALID_PARAMETER);
4110 return;
4113 if (!lp_ea_support(SNUM(conn))) {
4114 reply_doserror(req, ERRDOS,
4115 ERReasnotsupported);
4116 return;
4119 /* Pull out the list of names. */
4120 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4121 if (!ea_list) {
4122 reply_nterror(
4123 req, NT_STATUS_INVALID_PARAMETER);
4124 return;
4126 break;
4129 case SMB_QUERY_POSIX_LOCK:
4131 if (fsp == NULL || fsp->fh->fd == -1) {
4132 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4133 return;
4136 if (total_data != POSIX_LOCK_DATA_SIZE) {
4137 reply_nterror(
4138 req, NT_STATUS_INVALID_PARAMETER);
4139 return;
4142 /* Copy the lock range data. */
4143 lock_data = (char *)TALLOC_MEMDUP(
4144 ctx, pdata, total_data);
4145 if (!lock_data) {
4146 reply_nterror(req, NT_STATUS_NO_MEMORY);
4147 return;
4150 default:
4151 break;
4154 *pparams = (char *)SMB_REALLOC(*pparams,2);
4155 if (*pparams == NULL) {
4156 reply_nterror(req, NT_STATUS_NO_MEMORY);
4157 return;
4159 params = *pparams;
4160 SSVAL(params,0,0);
4161 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4162 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4163 if (*ppdata == NULL ) {
4164 reply_nterror(req, NT_STATUS_NO_MEMORY);
4165 return;
4167 pdata = *ppdata;
4168 dstart = pdata;
4169 dend = dstart + data_size - 1;
4171 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4172 mtime_ts = get_mtimespec(&sbuf);
4173 atime_ts = get_atimespec(&sbuf);
4175 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4177 if (!fsp) {
4178 /* Do we have this path open ? */
4179 files_struct *fsp1;
4180 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4181 fsp1 = file_find_di_first(fileid);
4182 if (fsp1 && fsp1->initial_allocation_size) {
4183 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4187 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4188 mtime_ts = write_time_ts;
4191 if (lp_dos_filetime_resolution(SNUM(conn))) {
4192 dos_filetime_timespec(&create_time_ts);
4193 dos_filetime_timespec(&mtime_ts);
4194 dos_filetime_timespec(&atime_ts);
4197 create_time = convert_timespec_to_time_t(create_time_ts);
4198 mtime = convert_timespec_to_time_t(mtime_ts);
4199 atime = convert_timespec_to_time_t(atime_ts);
4201 /* NT expects the name to be in an exact form of the *full*
4202 filename. See the trans2 torture test */
4203 if (ISDOT(base_name)) {
4204 dos_fname = talloc_strdup(ctx, "\\");
4205 if (!dos_fname) {
4206 reply_nterror(req, NT_STATUS_NO_MEMORY);
4207 return;
4209 } else {
4210 dos_fname = talloc_asprintf(ctx,
4211 "\\%s",
4212 fname);
4213 if (!dos_fname) {
4214 reply_nterror(req, NT_STATUS_NO_MEMORY);
4215 return;
4217 string_replace(dos_fname, '/', '\\');
4220 switch (info_level) {
4221 case SMB_INFO_STANDARD:
4222 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4223 data_size = 22;
4224 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4225 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4226 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4227 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4228 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4229 SSVAL(pdata,l1_attrFile,mode);
4230 break;
4232 case SMB_INFO_QUERY_EA_SIZE:
4234 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4235 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4236 data_size = 26;
4237 srv_put_dos_date2(pdata,0,create_time);
4238 srv_put_dos_date2(pdata,4,atime);
4239 srv_put_dos_date2(pdata,8,mtime); /* write time */
4240 SIVAL(pdata,12,(uint32)file_size);
4241 SIVAL(pdata,16,(uint32)allocation_size);
4242 SSVAL(pdata,20,mode);
4243 SIVAL(pdata,22,ea_size);
4244 break;
4247 case SMB_INFO_IS_NAME_VALID:
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4249 if (tran_call == TRANSACT2_QFILEINFO) {
4250 /* os/2 needs this ? really ?*/
4251 reply_doserror(req, ERRDOS, ERRbadfunc);
4252 return;
4254 data_size = 0;
4255 param_size = 0;
4256 break;
4258 case SMB_INFO_QUERY_EAS_FROM_LIST:
4260 size_t total_ea_len = 0;
4261 struct ea_list *ea_file_list = NULL;
4263 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4265 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4266 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4268 if (!ea_list || (total_ea_len > data_size)) {
4269 data_size = 4;
4270 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4271 break;
4274 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4275 break;
4278 case SMB_INFO_QUERY_ALL_EAS:
4280 /* We have data_size bytes to put EA's into. */
4281 size_t total_ea_len = 0;
4283 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4285 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4286 if (!ea_list || (total_ea_len > data_size)) {
4287 data_size = 4;
4288 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4289 break;
4292 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4293 break;
4296 case SMB_FILE_BASIC_INFORMATION:
4297 case SMB_QUERY_FILE_BASIC_INFO:
4299 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4300 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4301 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4302 } else {
4303 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4304 data_size = 40;
4305 SIVAL(pdata,36,0);
4307 put_long_date_timespec(pdata,create_time_ts);
4308 put_long_date_timespec(pdata+8,atime_ts);
4309 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4310 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4311 SIVAL(pdata,32,mode);
4313 DEBUG(5,("SMB_QFBI - "));
4314 DEBUG(5,("create: %s ", ctime(&create_time)));
4315 DEBUG(5,("access: %s ", ctime(&atime)));
4316 DEBUG(5,("write: %s ", ctime(&mtime)));
4317 DEBUG(5,("change: %s ", ctime(&mtime)));
4318 DEBUG(5,("mode: %x\n", mode));
4319 break;
4321 case SMB_FILE_STANDARD_INFORMATION:
4322 case SMB_QUERY_FILE_STANDARD_INFO:
4324 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4325 data_size = 24;
4326 SOFF_T(pdata,0,allocation_size);
4327 SOFF_T(pdata,8,file_size);
4328 SIVAL(pdata,16,nlink);
4329 SCVAL(pdata,20,delete_pending?1:0);
4330 SCVAL(pdata,21,(mode&aDIR)?1:0);
4331 SSVAL(pdata,22,0); /* Padding. */
4332 break;
4334 case SMB_FILE_EA_INFORMATION:
4335 case SMB_QUERY_FILE_EA_INFO:
4337 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4339 data_size = 4;
4340 SIVAL(pdata,0,ea_size);
4341 break;
4344 /* Get the 8.3 name - used if NT SMB was negotiated. */
4345 case SMB_QUERY_FILE_ALT_NAME_INFO:
4346 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4348 char mangled_name[13];
4349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4350 if (!name_to_8_3(base_name,mangled_name,
4351 True,conn->params)) {
4352 reply_nterror(
4353 req,
4354 NT_STATUS_NO_MEMORY);
4356 len = srvstr_push(dstart, req->flags2,
4357 pdata+4, mangled_name,
4358 PTR_DIFF(dend, pdata+4),
4359 STR_UNICODE);
4360 data_size = 4 + len;
4361 SIVAL(pdata,0,len);
4362 break;
4365 case SMB_QUERY_FILE_NAME_INFO:
4367 this must be *exactly* right for ACLs on mapped drives to work
4369 len = srvstr_push(dstart, req->flags2,
4370 pdata+4, dos_fname,
4371 PTR_DIFF(dend, pdata+4),
4372 STR_UNICODE);
4373 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4374 data_size = 4 + len;
4375 SIVAL(pdata,0,len);
4376 break;
4378 case SMB_FILE_ALLOCATION_INFORMATION:
4379 case SMB_QUERY_FILE_ALLOCATION_INFO:
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4381 data_size = 8;
4382 SOFF_T(pdata,0,allocation_size);
4383 break;
4385 case SMB_FILE_END_OF_FILE_INFORMATION:
4386 case SMB_QUERY_FILE_END_OF_FILEINFO:
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4388 data_size = 8;
4389 SOFF_T(pdata,0,file_size);
4390 break;
4392 case SMB_QUERY_FILE_ALL_INFO:
4393 case SMB_FILE_ALL_INFORMATION:
4395 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4396 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4397 put_long_date_timespec(pdata,create_time_ts);
4398 put_long_date_timespec(pdata+8,atime_ts);
4399 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4400 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4401 SIVAL(pdata,32,mode);
4402 SIVAL(pdata,36,0); /* padding. */
4403 pdata += 40;
4404 SOFF_T(pdata,0,allocation_size);
4405 SOFF_T(pdata,8,file_size);
4406 SIVAL(pdata,16,nlink);
4407 SCVAL(pdata,20,delete_pending);
4408 SCVAL(pdata,21,(mode&aDIR)?1:0);
4409 SSVAL(pdata,22,0);
4410 pdata += 24;
4411 SIVAL(pdata,0,ea_size);
4412 pdata += 4; /* EA info */
4413 len = srvstr_push(dstart, req->flags2,
4414 pdata+4, dos_fname,
4415 PTR_DIFF(dend, pdata+4),
4416 STR_UNICODE);
4417 SIVAL(pdata,0,len);
4418 pdata += 4 + len;
4419 data_size = PTR_DIFF(pdata,(*ppdata));
4420 break;
4422 case SMB_FILE_INTERNAL_INFORMATION:
4423 /* This should be an index number - looks like
4424 dev/ino to me :-)
4426 I think this causes us to fail the IFSKIT
4427 BasicFileInformationTest. -tpot */
4429 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4430 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4431 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4432 data_size = 8;
4433 break;
4435 case SMB_FILE_ACCESS_INFORMATION:
4436 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4437 if (fsp) {
4438 SIVAL(pdata,0,fsp->access_mask);
4439 } else {
4440 /* GENERIC_EXECUTE mapping from Windows */
4441 SIVAL(pdata,0,0x12019F);
4443 data_size = 4;
4444 break;
4446 case SMB_FILE_NAME_INFORMATION:
4447 /* Pathname with leading '\'. */
4449 size_t byte_len;
4450 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4452 SIVAL(pdata,0,byte_len);
4453 data_size = 4 + byte_len;
4454 break;
4457 case SMB_FILE_DISPOSITION_INFORMATION:
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4459 data_size = 1;
4460 SCVAL(pdata,0,delete_pending);
4461 break;
4463 case SMB_FILE_POSITION_INFORMATION:
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4465 data_size = 8;
4466 SOFF_T(pdata,0,pos);
4467 break;
4469 case SMB_FILE_MODE_INFORMATION:
4470 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4471 SIVAL(pdata,0,mode);
4472 data_size = 4;
4473 break;
4475 case SMB_FILE_ALIGNMENT_INFORMATION:
4476 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4477 SIVAL(pdata,0,0); /* No alignment needed. */
4478 data_size = 4;
4479 break;
4482 * NT4 server just returns "invalid query" to this - if we try
4483 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4484 * want this. JRA.
4486 /* The first statement above is false - verified using Thursby
4487 * client against NT4 -- gcolley.
4489 case SMB_QUERY_FILE_STREAM_INFO:
4490 case SMB_FILE_STREAM_INFORMATION: {
4491 unsigned int num_streams;
4492 struct stream_struct *streams;
4493 NTSTATUS status;
4495 DEBUG(10,("call_trans2qfilepathinfo: "
4496 "SMB_FILE_STREAM_INFORMATION\n"));
4498 status = SMB_VFS_STREAMINFO(
4499 conn, fsp, fname, talloc_tos(),
4500 &num_streams, &streams);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 DEBUG(10, ("could not get stream info: %s\n",
4504 nt_errstr(status)));
4505 reply_nterror(req, status);
4506 return;
4509 status = marshall_stream_info(num_streams, streams,
4510 pdata, max_data_bytes,
4511 &data_size);
4513 if (!NT_STATUS_IS_OK(status)) {
4514 DEBUG(10, ("marshall_stream_info failed: %s\n",
4515 nt_errstr(status)));
4516 reply_nterror(req, status);
4517 return;
4520 TALLOC_FREE(streams);
4522 break;
4524 case SMB_QUERY_COMPRESSION_INFO:
4525 case SMB_FILE_COMPRESSION_INFORMATION:
4526 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4527 SOFF_T(pdata,0,file_size);
4528 SIVAL(pdata,8,0); /* ??? */
4529 SIVAL(pdata,12,0); /* ??? */
4530 data_size = 16;
4531 break;
4533 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4534 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4535 put_long_date_timespec(pdata,create_time_ts);
4536 put_long_date_timespec(pdata+8,atime_ts);
4537 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4538 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4539 SOFF_T(pdata,32,allocation_size);
4540 SOFF_T(pdata,40,file_size);
4541 SIVAL(pdata,48,mode);
4542 SIVAL(pdata,52,0); /* ??? */
4543 data_size = 56;
4544 break;
4546 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4547 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4548 SIVAL(pdata,0,mode);
4549 SIVAL(pdata,4,0);
4550 data_size = 8;
4551 break;
4554 * CIFS UNIX Extensions.
4557 case SMB_QUERY_FILE_UNIX_BASIC:
4559 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4560 data_size = PTR_DIFF(pdata,(*ppdata));
4563 int i;
4564 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4566 for (i=0; i<100; i++)
4567 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4568 DEBUG(4,("\n"));
4571 break;
4573 case SMB_QUERY_FILE_UNIX_INFO2:
4575 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4576 data_size = PTR_DIFF(pdata,(*ppdata));
4579 int i;
4580 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4582 for (i=0; i<100; i++)
4583 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4584 DEBUG(4,("\n"));
4587 break;
4589 case SMB_QUERY_FILE_UNIX_LINK:
4591 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4593 if (!buffer) {
4594 reply_nterror(req, NT_STATUS_NO_MEMORY);
4595 return;
4598 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4599 #ifdef S_ISLNK
4600 if(!S_ISLNK(sbuf.st_mode)) {
4601 reply_unixerror(req, ERRSRV,
4602 ERRbadlink);
4603 return;
4605 #else
4606 reply_unixerror(req, ERRDOS, ERRbadlink);
4607 return;
4608 #endif
4609 len = SMB_VFS_READLINK(conn,fullpathname,
4610 buffer, PATH_MAX);
4611 if (len == -1) {
4612 reply_unixerror(req, ERRDOS,
4613 ERRnoaccess);
4614 return;
4616 buffer[len] = 0;
4617 len = srvstr_push(dstart, req->flags2,
4618 pdata, buffer,
4619 PTR_DIFF(dend, pdata),
4620 STR_TERMINATE);
4621 pdata += len;
4622 data_size = PTR_DIFF(pdata,(*ppdata));
4624 break;
4627 #if defined(HAVE_POSIX_ACLS)
4628 case SMB_QUERY_POSIX_ACL:
4630 SMB_ACL_T file_acl = NULL;
4631 SMB_ACL_T def_acl = NULL;
4632 uint16 num_file_acls = 0;
4633 uint16 num_def_acls = 0;
4635 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4636 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4637 } else {
4638 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4641 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4642 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4643 fname ));
4644 reply_nterror(
4645 req,
4646 NT_STATUS_NOT_IMPLEMENTED);
4647 return;
4650 if (S_ISDIR(sbuf.st_mode)) {
4651 if (fsp && fsp->is_directory) {
4652 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4653 } else {
4654 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4656 def_acl = free_empty_sys_acl(conn, def_acl);
4659 num_file_acls = count_acl_entries(conn, file_acl);
4660 num_def_acls = count_acl_entries(conn, def_acl);
4662 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4663 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4664 data_size,
4665 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4666 SMB_POSIX_ACL_HEADER_SIZE) ));
4667 if (file_acl) {
4668 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4670 if (def_acl) {
4671 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4673 reply_nterror(
4674 req,
4675 NT_STATUS_BUFFER_TOO_SMALL);
4676 return;
4679 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4680 SSVAL(pdata,2,num_file_acls);
4681 SSVAL(pdata,4,num_def_acls);
4682 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4683 if (file_acl) {
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4686 if (def_acl) {
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4689 reply_nterror(
4690 req, NT_STATUS_INTERNAL_ERROR);
4691 return;
4693 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4694 if (file_acl) {
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4697 if (def_acl) {
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4700 reply_nterror(
4701 req,
4702 NT_STATUS_INTERNAL_ERROR);
4703 return;
4706 if (file_acl) {
4707 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4709 if (def_acl) {
4710 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4712 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4713 break;
4715 #endif
4718 case SMB_QUERY_POSIX_LOCK:
4720 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4721 SMB_BIG_UINT count;
4722 SMB_BIG_UINT offset;
4723 uint32 lock_pid;
4724 enum brl_type lock_type;
4726 if (total_data != POSIX_LOCK_DATA_SIZE) {
4727 reply_nterror(
4728 req, NT_STATUS_INVALID_PARAMETER);
4729 return;
4732 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4733 case POSIX_LOCK_TYPE_READ:
4734 lock_type = READ_LOCK;
4735 break;
4736 case POSIX_LOCK_TYPE_WRITE:
4737 lock_type = WRITE_LOCK;
4738 break;
4739 case POSIX_LOCK_TYPE_UNLOCK:
4740 default:
4741 /* There's no point in asking for an unlock... */
4742 reply_nterror(
4743 req,
4744 NT_STATUS_INVALID_PARAMETER);
4745 return;
4748 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4749 #if defined(HAVE_LONGLONG)
4750 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4751 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4752 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4753 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4754 #else /* HAVE_LONGLONG */
4755 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4756 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4757 #endif /* HAVE_LONGLONG */
4759 status = query_lock(fsp,
4760 &lock_pid,
4761 &count,
4762 &offset,
4763 &lock_type,
4764 POSIX_LOCK);
4766 if (ERROR_WAS_LOCK_DENIED(status)) {
4767 /* Here we need to report who has it locked... */
4768 data_size = POSIX_LOCK_DATA_SIZE;
4770 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4771 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4772 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4773 #if defined(HAVE_LONGLONG)
4774 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4775 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4776 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4777 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4778 #else /* HAVE_LONGLONG */
4779 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4780 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4781 #endif /* HAVE_LONGLONG */
4783 } else if (NT_STATUS_IS_OK(status)) {
4784 /* For success we just return a copy of what we sent
4785 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4786 data_size = POSIX_LOCK_DATA_SIZE;
4787 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4788 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4789 } else {
4790 reply_nterror(req, status);
4791 return;
4793 break;
4796 default:
4797 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4798 return;
4801 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4802 max_data_bytes);
4804 return;
4807 /****************************************************************************
4808 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4809 code.
4810 ****************************************************************************/
4812 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4813 connection_struct *conn,
4814 const char *oldname_in,
4815 const char *newname_in)
4817 SMB_STRUCT_STAT sbuf1, sbuf2;
4818 char *last_component_oldname = NULL;
4819 char *last_component_newname = NULL;
4820 char *oldname = NULL;
4821 char *newname = NULL;
4822 NTSTATUS status = NT_STATUS_OK;
4824 ZERO_STRUCT(sbuf1);
4825 ZERO_STRUCT(sbuf2);
4827 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4828 &last_component_oldname, &sbuf1);
4829 if (!NT_STATUS_IS_OK(status)) {
4830 return status;
4833 status = check_name(conn, oldname);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 return status;
4838 /* source must already exist. */
4839 if (!VALID_STAT(sbuf1)) {
4840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4843 status = unix_convert(ctx, conn, newname_in, False, &newname,
4844 &last_component_newname, &sbuf2);
4845 if (!NT_STATUS_IS_OK(status)) {
4846 return status;
4849 status = check_name(conn, newname);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 return status;
4854 /* Disallow if newname already exists. */
4855 if (VALID_STAT(sbuf2)) {
4856 return NT_STATUS_OBJECT_NAME_COLLISION;
4859 /* No links from a directory. */
4860 if (S_ISDIR(sbuf1.st_mode)) {
4861 return NT_STATUS_FILE_IS_A_DIRECTORY;
4864 /* Ensure this is within the share. */
4865 status = check_reduced_name(conn, oldname);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 return status;
4870 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4872 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4873 status = map_nt_error_from_unix(errno);
4874 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4875 nt_errstr(status), newname, oldname));
4878 return status;
4881 /****************************************************************************
4882 Deal with setting the time from any of the setfilepathinfo functions.
4883 ****************************************************************************/
4885 NTSTATUS smb_set_file_time(connection_struct *conn,
4886 files_struct *fsp,
4887 const char *fname,
4888 const SMB_STRUCT_STAT *psbuf,
4889 struct timespec ts[2],
4890 bool setting_write_time)
4892 uint32 action =
4893 FILE_NOTIFY_CHANGE_LAST_ACCESS
4894 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4896 if (!VALID_STAT(*psbuf)) {
4897 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4900 /* get some defaults (no modifications) if any info is zero or -1. */
4901 if (null_timespec(ts[0])) {
4902 ts[0] = get_atimespec(psbuf);
4903 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4906 if (null_timespec(ts[1])) {
4907 ts[1] = get_mtimespec(psbuf);
4908 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4911 if (!setting_write_time) {
4912 /* ts[1] comes from change time, not write time. */
4913 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4916 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4917 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4920 * Try and set the times of this file if
4921 * they are different from the current values.
4925 struct timespec mts = get_mtimespec(psbuf);
4926 struct timespec ats = get_atimespec(psbuf);
4927 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4928 return NT_STATUS_OK;
4932 if (setting_write_time) {
4934 * This was a Windows setfileinfo on an open file.
4935 * NT does this a lot. We also need to
4936 * set the time here, as it can be read by
4937 * FindFirst/FindNext and with the patch for bug #2045
4938 * in smbd/fileio.c it ensures that this timestamp is
4939 * kept sticky even after a write. We save the request
4940 * away and will set it on file close and after a write. JRA.
4943 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4944 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4946 if (fsp != NULL) {
4947 if (fsp->base_fsp) {
4948 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4949 } else {
4950 set_sticky_write_time_fsp(fsp, ts[1]);
4952 } else {
4953 set_sticky_write_time_path(conn, fname,
4954 vfs_file_id_from_sbuf(conn, psbuf),
4955 ts[1]);
4959 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4961 if (fsp && fsp->base_fsp) {
4962 fname = fsp->base_fsp->fsp_name;
4965 if(file_ntimes(conn, fname, ts)!=0) {
4966 return map_nt_error_from_unix(errno);
4968 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4970 return NT_STATUS_OK;
4973 /****************************************************************************
4974 Deal with setting the dosmode from any of the setfilepathinfo functions.
4975 ****************************************************************************/
4977 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4978 files_struct *fsp,
4979 const char *fname,
4980 SMB_STRUCT_STAT *psbuf,
4981 uint32 dosmode)
4983 if (!VALID_STAT(*psbuf)) {
4984 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4987 if (fsp) {
4988 if (fsp->base_fsp) {
4989 fname = fsp->base_fsp->fsp_name;
4990 } else {
4991 fname = fsp->fsp_name;
4995 if (dosmode) {
4996 if (S_ISDIR(psbuf->st_mode)) {
4997 dosmode |= aDIR;
4998 } else {
4999 dosmode &= ~aDIR;
5003 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5005 /* check the mode isn't different, before changing it */
5006 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5008 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5009 fname, (unsigned int)dosmode ));
5011 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5012 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5013 fname, strerror(errno)));
5014 return map_nt_error_from_unix(errno);
5017 return NT_STATUS_OK;
5020 /****************************************************************************
5021 Deal with setting the size from any of the setfilepathinfo functions.
5022 ****************************************************************************/
5024 static NTSTATUS smb_set_file_size(connection_struct *conn,
5025 struct smb_request *req,
5026 files_struct *fsp,
5027 const char *fname,
5028 SMB_STRUCT_STAT *psbuf,
5029 SMB_OFF_T size)
5031 NTSTATUS status = NT_STATUS_OK;
5032 files_struct *new_fsp = NULL;
5034 if (!VALID_STAT(*psbuf)) {
5035 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5038 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5040 if (size == get_file_size(*psbuf)) {
5041 return NT_STATUS_OK;
5044 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5045 fname, (double)size ));
5047 if (fsp && fsp->fh->fd != -1) {
5048 /* Handle based call. */
5049 if (vfs_set_filelen(fsp, size) == -1) {
5050 return map_nt_error_from_unix(errno);
5052 trigger_write_time_update_immediate(fsp);
5053 return NT_STATUS_OK;
5056 status = open_file_ntcreate(conn, req, fname, psbuf,
5057 FILE_WRITE_ATTRIBUTES,
5058 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5059 FILE_OPEN,
5061 FILE_ATTRIBUTE_NORMAL,
5062 FORCE_OPLOCK_BREAK_TO_NONE,
5063 NULL, &new_fsp);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 /* NB. We check for open_was_deferred in the caller. */
5067 return status;
5070 if (vfs_set_filelen(new_fsp, size) == -1) {
5071 status = map_nt_error_from_unix(errno);
5072 close_file(new_fsp,NORMAL_CLOSE);
5073 return status;
5076 trigger_write_time_update_immediate(new_fsp);
5077 close_file(new_fsp,NORMAL_CLOSE);
5078 return NT_STATUS_OK;
5081 /****************************************************************************
5082 Deal with SMB_INFO_SET_EA.
5083 ****************************************************************************/
5085 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5086 const char *pdata,
5087 int total_data,
5088 files_struct *fsp,
5089 const char *fname)
5091 struct ea_list *ea_list = NULL;
5092 TALLOC_CTX *ctx = NULL;
5093 NTSTATUS status = NT_STATUS_OK;
5095 if (total_data < 10) {
5097 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5098 length. They seem to have no effect. Bug #3212. JRA */
5100 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5101 /* We're done. We only get EA info in this call. */
5102 return NT_STATUS_OK;
5105 return NT_STATUS_INVALID_PARAMETER;
5108 if (IVAL(pdata,0) > total_data) {
5109 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5110 IVAL(pdata,0), (unsigned int)total_data));
5111 return NT_STATUS_INVALID_PARAMETER;
5114 ctx = talloc_tos();
5115 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5116 if (!ea_list) {
5117 return NT_STATUS_INVALID_PARAMETER;
5119 status = set_ea(conn, fsp, fname, ea_list);
5121 return status;
5124 /****************************************************************************
5125 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5126 ****************************************************************************/
5128 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5129 const char *pdata,
5130 int total_data,
5131 files_struct *fsp,
5132 const char *fname,
5133 SMB_STRUCT_STAT *psbuf)
5135 NTSTATUS status = NT_STATUS_OK;
5136 bool delete_on_close;
5137 uint32 dosmode = 0;
5139 if (total_data < 1) {
5140 return NT_STATUS_INVALID_PARAMETER;
5143 if (fsp == NULL) {
5144 return NT_STATUS_INVALID_HANDLE;
5147 delete_on_close = (CVAL(pdata,0) ? True : False);
5148 dosmode = dos_mode(conn, fname, psbuf);
5150 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5151 "delete_on_close = %u\n",
5152 fsp->fsp_name,
5153 (unsigned int)dosmode,
5154 (unsigned int)delete_on_close ));
5156 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5158 if (!NT_STATUS_IS_OK(status)) {
5159 return status;
5162 /* The set is across all open files on this dev/inode pair. */
5163 if (!set_delete_on_close(fsp, delete_on_close,
5164 &conn->server_info->utok)) {
5165 return NT_STATUS_ACCESS_DENIED;
5167 return NT_STATUS_OK;
5170 /****************************************************************************
5171 Deal with SMB_FILE_POSITION_INFORMATION.
5172 ****************************************************************************/
5174 static NTSTATUS smb_file_position_information(connection_struct *conn,
5175 const char *pdata,
5176 int total_data,
5177 files_struct *fsp)
5179 SMB_BIG_UINT position_information;
5181 if (total_data < 8) {
5182 return NT_STATUS_INVALID_PARAMETER;
5185 if (fsp == NULL) {
5186 /* Ignore on pathname based set. */
5187 return NT_STATUS_OK;
5190 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5191 #ifdef LARGE_SMB_OFF_T
5192 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5193 #else /* LARGE_SMB_OFF_T */
5194 if (IVAL(pdata,4) != 0) {
5195 /* more than 32 bits? */
5196 return NT_STATUS_INVALID_PARAMETER;
5198 #endif /* LARGE_SMB_OFF_T */
5200 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5201 fsp->fsp_name, (double)position_information ));
5202 fsp->fh->position_information = position_information;
5203 return NT_STATUS_OK;
5206 /****************************************************************************
5207 Deal with SMB_FILE_MODE_INFORMATION.
5208 ****************************************************************************/
5210 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5211 const char *pdata,
5212 int total_data)
5214 uint32 mode;
5216 if (total_data < 4) {
5217 return NT_STATUS_INVALID_PARAMETER;
5219 mode = IVAL(pdata,0);
5220 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5221 return NT_STATUS_INVALID_PARAMETER;
5223 return NT_STATUS_OK;
5226 /****************************************************************************
5227 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5228 ****************************************************************************/
5230 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5231 struct smb_request *req,
5232 const char *pdata,
5233 int total_data,
5234 const char *fname)
5236 char *link_target = NULL;
5237 const char *newname = fname;
5238 NTSTATUS status = NT_STATUS_OK;
5239 TALLOC_CTX *ctx = talloc_tos();
5241 /* Set a symbolic link. */
5242 /* Don't allow this if follow links is false. */
5244 if (total_data == 0) {
5245 return NT_STATUS_INVALID_PARAMETER;
5248 if (!lp_symlinks(SNUM(conn))) {
5249 return NT_STATUS_ACCESS_DENIED;
5252 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5253 total_data, STR_TERMINATE);
5255 if (!link_target) {
5256 return NT_STATUS_INVALID_PARAMETER;
5259 /* !widelinks forces the target path to be within the share. */
5260 /* This means we can interpret the target as a pathname. */
5261 if (!lp_widelinks(SNUM(conn))) {
5262 char *rel_name = NULL;
5263 char *last_dirp = NULL;
5265 if (*link_target == '/') {
5266 /* No absolute paths allowed. */
5267 return NT_STATUS_ACCESS_DENIED;
5269 rel_name = talloc_strdup(ctx,newname);
5270 if (!rel_name) {
5271 return NT_STATUS_NO_MEMORY;
5273 last_dirp = strrchr_m(rel_name, '/');
5274 if (last_dirp) {
5275 last_dirp[1] = '\0';
5276 } else {
5277 rel_name = talloc_strdup(ctx,"./");
5278 if (!rel_name) {
5279 return NT_STATUS_NO_MEMORY;
5282 rel_name = talloc_asprintf_append(rel_name,
5283 "%s",
5284 link_target);
5285 if (!rel_name) {
5286 return NT_STATUS_NO_MEMORY;
5289 status = check_name(conn, rel_name);
5290 if (!NT_STATUS_IS_OK(status)) {
5291 return status;
5295 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5296 newname, link_target ));
5298 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5299 return map_nt_error_from_unix(errno);
5302 return NT_STATUS_OK;
5305 /****************************************************************************
5306 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5307 ****************************************************************************/
5309 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5310 struct smb_request *req,
5311 const char *pdata, int total_data,
5312 const char *fname)
5314 char *oldname = NULL;
5315 TALLOC_CTX *ctx = talloc_tos();
5316 NTSTATUS status = NT_STATUS_OK;
5318 /* Set a hard link. */
5319 if (total_data == 0) {
5320 return NT_STATUS_INVALID_PARAMETER;
5323 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5324 total_data, STR_TERMINATE, &status);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 return status;
5329 status = resolve_dfspath(ctx, conn,
5330 req->flags2 & FLAGS2_DFS_PATHNAMES,
5331 oldname,
5332 &oldname);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 return status;
5337 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5338 fname, oldname));
5340 return hardlink_internals(ctx, conn, oldname, fname);
5343 /****************************************************************************
5344 Deal with SMB_FILE_RENAME_INFORMATION.
5345 ****************************************************************************/
5347 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5348 struct smb_request *req,
5349 const char *pdata,
5350 int total_data,
5351 files_struct *fsp,
5352 const char *fname)
5354 bool overwrite;
5355 uint32 root_fid;
5356 uint32 len;
5357 char *newname = NULL;
5358 char *base_name = NULL;
5359 bool dest_has_wcard = False;
5360 SMB_STRUCT_STAT sbuf;
5361 char *newname_last_component = NULL;
5362 NTSTATUS status = NT_STATUS_OK;
5363 char *p;
5364 TALLOC_CTX *ctx = talloc_tos();
5366 if (total_data < 13) {
5367 return NT_STATUS_INVALID_PARAMETER;
5370 ZERO_STRUCT(sbuf);
5372 overwrite = (CVAL(pdata,0) ? True : False);
5373 root_fid = IVAL(pdata,4);
5374 len = IVAL(pdata,8);
5376 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5377 return NT_STATUS_INVALID_PARAMETER;
5380 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5381 len, 0, &status,
5382 &dest_has_wcard);
5383 if (!NT_STATUS_IS_OK(status)) {
5384 return status;
5387 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5388 newname));
5390 status = resolve_dfspath_wcard(ctx, conn,
5391 req->flags2 & FLAGS2_DFS_PATHNAMES,
5392 newname,
5393 &newname,
5394 &dest_has_wcard);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 return status;
5399 /* Check the new name has no '/' characters. */
5400 if (strchr_m(newname, '/')) {
5401 return NT_STATUS_NOT_SUPPORTED;
5404 if (fsp && fsp->base_fsp) {
5405 /* newname must be a stream name. */
5406 if (newname[0] != ':') {
5407 return NT_STATUS_NOT_SUPPORTED;
5409 base_name = talloc_asprintf(ctx, "%s%s",
5410 fsp->base_fsp->fsp_name,
5411 newname);
5412 if (!base_name) {
5413 return NT_STATUS_NO_MEMORY;
5415 } else {
5416 /* newname must *not* be a stream name. */
5417 if (is_ntfs_stream_name(newname)) {
5418 return NT_STATUS_NOT_SUPPORTED;
5421 /* Create the base directory. */
5422 base_name = talloc_strdup(ctx, fname);
5423 if (!base_name) {
5424 return NT_STATUS_NO_MEMORY;
5426 p = strrchr_m(base_name, '/');
5427 if (p) {
5428 p[1] = '\0';
5429 } else {
5430 base_name = talloc_strdup(ctx, "./");
5431 if (!base_name) {
5432 return NT_STATUS_NO_MEMORY;
5435 /* Append the new name. */
5436 base_name = talloc_asprintf_append(base_name,
5437 "%s",
5438 newname);
5439 if (!base_name) {
5440 return NT_STATUS_NO_MEMORY;
5443 status = unix_convert(ctx, conn, newname, False,
5444 &newname,
5445 &newname_last_component,
5446 &sbuf);
5448 /* If an error we expect this to be
5449 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5451 if (!NT_STATUS_IS_OK(status)
5452 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5453 status)) {
5454 return status;
5458 if (fsp) {
5459 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5460 fsp->fnum, fsp->fsp_name, base_name ));
5461 status = rename_internals_fsp(conn, fsp, base_name,
5462 newname_last_component, 0,
5463 overwrite);
5464 } else {
5465 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5466 fname, base_name ));
5467 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5468 overwrite, False, dest_has_wcard,
5469 FILE_WRITE_ATTRIBUTES);
5472 return status;
5475 /****************************************************************************
5476 Deal with SMB_SET_POSIX_ACL.
5477 ****************************************************************************/
5479 #if defined(HAVE_POSIX_ACLS)
5480 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5481 const char *pdata,
5482 int total_data,
5483 files_struct *fsp,
5484 const char *fname,
5485 SMB_STRUCT_STAT *psbuf)
5487 uint16 posix_acl_version;
5488 uint16 num_file_acls;
5489 uint16 num_def_acls;
5490 bool valid_file_acls = True;
5491 bool valid_def_acls = True;
5493 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5494 return NT_STATUS_INVALID_PARAMETER;
5496 posix_acl_version = SVAL(pdata,0);
5497 num_file_acls = SVAL(pdata,2);
5498 num_def_acls = SVAL(pdata,4);
5500 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5501 valid_file_acls = False;
5502 num_file_acls = 0;
5505 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5506 valid_def_acls = False;
5507 num_def_acls = 0;
5510 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5511 return NT_STATUS_INVALID_PARAMETER;
5514 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5515 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5516 return NT_STATUS_INVALID_PARAMETER;
5519 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5520 fname ? fname : fsp->fsp_name,
5521 (unsigned int)num_file_acls,
5522 (unsigned int)num_def_acls));
5524 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5525 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5526 return map_nt_error_from_unix(errno);
5529 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5530 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5531 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5532 return map_nt_error_from_unix(errno);
5534 return NT_STATUS_OK;
5536 #endif
5538 /****************************************************************************
5539 Deal with SMB_SET_POSIX_LOCK.
5540 ****************************************************************************/
5542 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5543 const struct smb_request *req,
5544 const char *pdata,
5545 int total_data,
5546 files_struct *fsp)
5548 SMB_BIG_UINT count;
5549 SMB_BIG_UINT offset;
5550 uint32 lock_pid;
5551 bool blocking_lock = False;
5552 enum brl_type lock_type;
5554 NTSTATUS status = NT_STATUS_OK;
5556 if (fsp == NULL || fsp->fh->fd == -1) {
5557 return NT_STATUS_INVALID_HANDLE;
5560 if (total_data != POSIX_LOCK_DATA_SIZE) {
5561 return NT_STATUS_INVALID_PARAMETER;
5564 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5565 case POSIX_LOCK_TYPE_READ:
5566 lock_type = READ_LOCK;
5567 break;
5568 case POSIX_LOCK_TYPE_WRITE:
5569 /* Return the right POSIX-mappable error code for files opened read-only. */
5570 if (!fsp->can_write) {
5571 return NT_STATUS_INVALID_HANDLE;
5573 lock_type = WRITE_LOCK;
5574 break;
5575 case POSIX_LOCK_TYPE_UNLOCK:
5576 lock_type = UNLOCK_LOCK;
5577 break;
5578 default:
5579 return NT_STATUS_INVALID_PARAMETER;
5582 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5583 blocking_lock = False;
5584 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5585 blocking_lock = True;
5586 } else {
5587 return NT_STATUS_INVALID_PARAMETER;
5590 if (!lp_blocking_locks(SNUM(conn))) {
5591 blocking_lock = False;
5594 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5595 #if defined(HAVE_LONGLONG)
5596 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5597 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5598 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5599 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5600 #else /* HAVE_LONGLONG */
5601 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5602 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5603 #endif /* HAVE_LONGLONG */
5605 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5606 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5607 fsp->fsp_name,
5608 (unsigned int)lock_type,
5609 (unsigned int)lock_pid,
5610 (double)count,
5611 (double)offset ));
5613 if (lock_type == UNLOCK_LOCK) {
5614 status = do_unlock(smbd_messaging_context(),
5615 fsp,
5616 lock_pid,
5617 count,
5618 offset,
5619 POSIX_LOCK);
5620 } else {
5621 uint32 block_smbpid;
5623 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5624 fsp,
5625 lock_pid,
5626 count,
5627 offset,
5628 lock_type,
5629 POSIX_LOCK,
5630 blocking_lock,
5631 &status,
5632 &block_smbpid);
5634 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5636 * A blocking lock was requested. Package up
5637 * this smb into a queued request and push it
5638 * onto the blocking lock queue.
5640 if(push_blocking_lock_request(br_lck,
5641 req,
5642 fsp,
5643 -1, /* infinite timeout. */
5645 lock_pid,
5646 lock_type,
5647 POSIX_LOCK,
5648 offset,
5649 count,
5650 block_smbpid)) {
5651 TALLOC_FREE(br_lck);
5652 return status;
5655 TALLOC_FREE(br_lck);
5658 return status;
5661 /****************************************************************************
5662 Deal with SMB_INFO_STANDARD.
5663 ****************************************************************************/
5665 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5666 const char *pdata,
5667 int total_data,
5668 files_struct *fsp,
5669 const char *fname,
5670 const SMB_STRUCT_STAT *psbuf)
5672 struct timespec ts[2];
5674 if (total_data < 12) {
5675 return NT_STATUS_INVALID_PARAMETER;
5678 /* access time */
5679 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5680 /* write time */
5681 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5683 DEBUG(10,("smb_set_info_standard: file %s\n",
5684 fname ? fname : fsp->fsp_name ));
5686 return smb_set_file_time(conn,
5687 fsp,
5688 fname,
5689 psbuf,
5691 true);
5694 /****************************************************************************
5695 Deal with SMB_SET_FILE_BASIC_INFO.
5696 ****************************************************************************/
5698 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5699 const char *pdata,
5700 int total_data,
5701 files_struct *fsp,
5702 const char *fname,
5703 SMB_STRUCT_STAT *psbuf)
5705 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5706 struct timespec write_time;
5707 struct timespec changed_time;
5708 uint32 dosmode = 0;
5709 struct timespec ts[2];
5710 NTSTATUS status = NT_STATUS_OK;
5711 bool setting_write_time = true;
5713 if (total_data < 36) {
5714 return NT_STATUS_INVALID_PARAMETER;
5717 /* Set the attributes */
5718 dosmode = IVAL(pdata,32);
5719 status = smb_set_file_dosmode(conn,
5720 fsp,
5721 fname,
5722 psbuf,
5723 dosmode);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 return status;
5729 /* Ignore create time at offset pdata. */
5731 /* access time */
5732 ts[0] = interpret_long_date(pdata+8);
5734 write_time = interpret_long_date(pdata+16);
5735 changed_time = interpret_long_date(pdata+24);
5737 /* mtime */
5738 ts[1] = timespec_min(&write_time, &changed_time);
5740 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5741 ts[1] = write_time;
5744 /* Prefer a defined time to an undefined one. */
5745 if (null_timespec(ts[1])) {
5746 if (null_timespec(write_time)) {
5747 ts[1] = changed_time;
5748 setting_write_time = false;
5749 } else {
5750 ts[1] = write_time;
5754 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5755 fname ? fname : fsp->fsp_name ));
5757 return smb_set_file_time(conn,
5758 fsp,
5759 fname,
5760 psbuf,
5762 setting_write_time);
5765 /****************************************************************************
5766 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5767 ****************************************************************************/
5769 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5770 struct smb_request *req,
5771 const char *pdata,
5772 int total_data,
5773 files_struct *fsp,
5774 const char *fname,
5775 SMB_STRUCT_STAT *psbuf)
5777 SMB_BIG_UINT allocation_size = 0;
5778 NTSTATUS status = NT_STATUS_OK;
5779 files_struct *new_fsp = NULL;
5781 if (!VALID_STAT(*psbuf)) {
5782 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5785 if (total_data < 8) {
5786 return NT_STATUS_INVALID_PARAMETER;
5789 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5790 #ifdef LARGE_SMB_OFF_T
5791 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5792 #else /* LARGE_SMB_OFF_T */
5793 if (IVAL(pdata,4) != 0) {
5794 /* more than 32 bits? */
5795 return NT_STATUS_INVALID_PARAMETER;
5797 #endif /* LARGE_SMB_OFF_T */
5799 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5800 fname, (double)allocation_size ));
5802 if (allocation_size) {
5803 allocation_size = smb_roundup(conn, allocation_size);
5806 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5807 fname, (double)allocation_size ));
5809 if (fsp && fsp->fh->fd != -1) {
5810 /* Open file handle. */
5811 /* Only change if needed. */
5812 if (allocation_size != get_file_size(*psbuf)) {
5813 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5814 return map_nt_error_from_unix(errno);
5817 /* But always update the time. */
5819 * This is equivalent to a write. Ensure it's seen immediately
5820 * if there are no pending writes.
5822 trigger_write_time_update_immediate(fsp);
5823 return NT_STATUS_OK;
5826 /* Pathname or stat or directory file. */
5828 status = open_file_ntcreate(conn, req, fname, psbuf,
5829 FILE_WRITE_DATA,
5830 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5831 FILE_OPEN,
5833 FILE_ATTRIBUTE_NORMAL,
5834 FORCE_OPLOCK_BREAK_TO_NONE,
5835 NULL, &new_fsp);
5837 if (!NT_STATUS_IS_OK(status)) {
5838 /* NB. We check for open_was_deferred in the caller. */
5839 return status;
5842 /* Only change if needed. */
5843 if (allocation_size != get_file_size(*psbuf)) {
5844 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5845 status = map_nt_error_from_unix(errno);
5846 close_file(new_fsp,NORMAL_CLOSE);
5847 return status;
5851 /* Changing the allocation size should set the last mod time. */
5853 * This is equivalent to a write. Ensure it's seen immediately
5854 * if there are no pending writes.
5856 trigger_write_time_update_immediate(new_fsp);
5858 close_file(new_fsp,NORMAL_CLOSE);
5859 return NT_STATUS_OK;
5862 /****************************************************************************
5863 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5864 ****************************************************************************/
5866 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5867 struct smb_request *req,
5868 const char *pdata,
5869 int total_data,
5870 files_struct *fsp,
5871 const char *fname,
5872 SMB_STRUCT_STAT *psbuf)
5874 SMB_OFF_T size;
5876 if (total_data < 8) {
5877 return NT_STATUS_INVALID_PARAMETER;
5880 size = IVAL(pdata,0);
5881 #ifdef LARGE_SMB_OFF_T
5882 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5883 #else /* LARGE_SMB_OFF_T */
5884 if (IVAL(pdata,4) != 0) {
5885 /* more than 32 bits? */
5886 return NT_STATUS_INVALID_PARAMETER;
5888 #endif /* LARGE_SMB_OFF_T */
5889 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5890 "file %s to %.0f\n", fname, (double)size ));
5892 return smb_set_file_size(conn, req,
5893 fsp,
5894 fname,
5895 psbuf,
5896 size);
5899 /****************************************************************************
5900 Allow a UNIX info mknod.
5901 ****************************************************************************/
5903 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5904 const char *pdata,
5905 int total_data,
5906 const char *fname,
5907 SMB_STRUCT_STAT *psbuf)
5909 uint32 file_type = IVAL(pdata,56);
5910 #if defined(HAVE_MAKEDEV)
5911 uint32 dev_major = IVAL(pdata,60);
5912 uint32 dev_minor = IVAL(pdata,68);
5913 #endif
5914 SMB_DEV_T dev = (SMB_DEV_T)0;
5915 uint32 raw_unixmode = IVAL(pdata,84);
5916 NTSTATUS status;
5917 mode_t unixmode;
5919 if (total_data < 100) {
5920 return NT_STATUS_INVALID_PARAMETER;
5923 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5924 if (!NT_STATUS_IS_OK(status)) {
5925 return status;
5928 #if defined(HAVE_MAKEDEV)
5929 dev = makedev(dev_major, dev_minor);
5930 #endif
5932 switch (file_type) {
5933 #if defined(S_IFIFO)
5934 case UNIX_TYPE_FIFO:
5935 unixmode |= S_IFIFO;
5936 break;
5937 #endif
5938 #if defined(S_IFSOCK)
5939 case UNIX_TYPE_SOCKET:
5940 unixmode |= S_IFSOCK;
5941 break;
5942 #endif
5943 #if defined(S_IFCHR)
5944 case UNIX_TYPE_CHARDEV:
5945 unixmode |= S_IFCHR;
5946 break;
5947 #endif
5948 #if defined(S_IFBLK)
5949 case UNIX_TYPE_BLKDEV:
5950 unixmode |= S_IFBLK;
5951 break;
5952 #endif
5953 default:
5954 return NT_STATUS_INVALID_PARAMETER;
5957 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5958 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5960 /* Ok - do the mknod. */
5961 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5962 return map_nt_error_from_unix(errno);
5965 /* If any of the other "set" calls fail we
5966 * don't want to end up with a half-constructed mknod.
5969 if (lp_inherit_perms(SNUM(conn))) {
5970 inherit_access_posix_acl(
5971 conn, parent_dirname(fname),
5972 fname, unixmode);
5975 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5976 status = map_nt_error_from_unix(errno);
5977 SMB_VFS_UNLINK(conn,fname);
5978 return status;
5980 return NT_STATUS_OK;
5983 /****************************************************************************
5984 Deal with SMB_SET_FILE_UNIX_BASIC.
5985 ****************************************************************************/
5987 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5988 struct smb_request *req,
5989 const char *pdata,
5990 int total_data,
5991 files_struct *fsp,
5992 const char *fname,
5993 SMB_STRUCT_STAT *psbuf)
5995 struct timespec ts[2];
5996 uint32 raw_unixmode;
5997 mode_t unixmode;
5998 SMB_OFF_T size = 0;
5999 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6000 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6001 NTSTATUS status = NT_STATUS_OK;
6002 bool delete_on_fail = False;
6003 enum perm_type ptype;
6004 files_struct *all_fsps = NULL;
6005 bool modify_mtime = true;
6006 struct file_id id;
6008 if (total_data < 100) {
6009 return NT_STATUS_INVALID_PARAMETER;
6012 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6013 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6014 size=IVAL(pdata,0); /* first 8 Bytes are size */
6015 #ifdef LARGE_SMB_OFF_T
6016 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6017 #else /* LARGE_SMB_OFF_T */
6018 if (IVAL(pdata,4) != 0) {
6019 /* more than 32 bits? */
6020 return NT_STATUS_INVALID_PARAMETER;
6022 #endif /* LARGE_SMB_OFF_T */
6025 ts[0] = interpret_long_date(pdata+24); /* access_time */
6026 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6027 set_owner = (uid_t)IVAL(pdata,40);
6028 set_grp = (gid_t)IVAL(pdata,48);
6029 raw_unixmode = IVAL(pdata,84);
6031 if (VALID_STAT(*psbuf)) {
6032 if (S_ISDIR(psbuf->st_mode)) {
6033 ptype = PERM_EXISTING_DIR;
6034 } else {
6035 ptype = PERM_EXISTING_FILE;
6037 } else {
6038 ptype = PERM_NEW_FILE;
6041 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6042 if (!NT_STATUS_IS_OK(status)) {
6043 return status;
6046 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6047 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6048 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6050 if (!VALID_STAT(*psbuf)) {
6052 * The only valid use of this is to create character and block
6053 * devices, and named pipes. This is deprecated (IMHO) and
6054 * a new info level should be used for mknod. JRA.
6057 status = smb_unix_mknod(conn,
6058 pdata,
6059 total_data,
6060 fname,
6061 psbuf);
6062 if (!NT_STATUS_IS_OK(status)) {
6063 return status;
6066 /* Ensure we don't try and change anything else. */
6067 raw_unixmode = SMB_MODE_NO_CHANGE;
6068 size = get_file_size(*psbuf);
6069 ts[0] = get_atimespec(psbuf);
6070 ts[1] = get_mtimespec(psbuf);
6072 * We continue here as we might want to change the
6073 * owner uid/gid.
6075 delete_on_fail = True;
6078 #if 1
6079 /* Horrible backwards compatibility hack as an old server bug
6080 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6081 * */
6083 if (!size) {
6084 size = get_file_size(*psbuf);
6086 #endif
6089 * Deal with the UNIX specific mode set.
6092 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6093 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6094 (unsigned int)unixmode, fname ));
6095 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6096 return map_nt_error_from_unix(errno);
6101 * Deal with the UNIX specific uid set.
6104 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6105 int ret;
6107 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6108 (unsigned int)set_owner, fname ));
6110 if (S_ISLNK(psbuf->st_mode)) {
6111 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6112 } else {
6113 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6116 if (ret != 0) {
6117 status = map_nt_error_from_unix(errno);
6118 if (delete_on_fail) {
6119 SMB_VFS_UNLINK(conn,fname);
6121 return status;
6126 * Deal with the UNIX specific gid set.
6129 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6130 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6131 (unsigned int)set_owner, fname ));
6132 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6133 status = map_nt_error_from_unix(errno);
6134 if (delete_on_fail) {
6135 SMB_VFS_UNLINK(conn,fname);
6137 return status;
6141 /* Deal with any size changes. */
6143 status = smb_set_file_size(conn, req,
6144 fsp,
6145 fname,
6146 psbuf,
6147 size);
6148 if (!NT_STATUS_IS_OK(status)) {
6149 return status;
6152 /* Deal with any time changes. */
6153 id = vfs_file_id_from_sbuf(conn, psbuf);
6154 for(all_fsps = file_find_di_first(id); all_fsps;
6155 all_fsps = file_find_di_next(all_fsps)) {
6157 * We're setting the time explicitly for UNIX.
6158 * Cancel any pending changes over all handles.
6160 all_fsps->update_write_time_on_close = false;
6161 TALLOC_FREE(all_fsps->update_write_time_event);
6165 * Override the "setting_write_time"
6166 * parameter here as it almost does what
6167 * we need. Just remember if we modified
6168 * mtime and send the notify ourselves.
6170 if (null_timespec(ts[1])) {
6171 modify_mtime = false;
6174 status = smb_set_file_time(conn,
6175 fsp,
6176 fname,
6177 psbuf,
6179 false);
6181 if (modify_mtime) {
6182 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6183 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6185 return status;
6188 /****************************************************************************
6189 Deal with SMB_SET_FILE_UNIX_INFO2.
6190 ****************************************************************************/
6192 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6193 struct smb_request *req,
6194 const char *pdata,
6195 int total_data,
6196 files_struct *fsp,
6197 const char *fname,
6198 SMB_STRUCT_STAT *psbuf)
6200 NTSTATUS status;
6201 uint32 smb_fflags;
6202 uint32 smb_fmask;
6204 if (total_data < 116) {
6205 return NT_STATUS_INVALID_PARAMETER;
6208 /* Start by setting all the fields that are common between UNIX_BASIC
6209 * and UNIX_INFO2.
6211 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6212 fsp, fname, psbuf);
6213 if (!NT_STATUS_IS_OK(status)) {
6214 return status;
6217 smb_fflags = IVAL(pdata, 108);
6218 smb_fmask = IVAL(pdata, 112);
6220 /* NB: We should only attempt to alter the file flags if the client
6221 * sends a non-zero mask.
6223 if (smb_fmask != 0) {
6224 int stat_fflags = 0;
6226 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6227 &stat_fflags)) {
6228 /* Client asked to alter a flag we don't understand. */
6229 return NT_STATUS_INVALID_PARAMETER;
6232 if (fsp && fsp->fh->fd != -1) {
6233 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6234 return NT_STATUS_NOT_SUPPORTED;
6235 } else {
6236 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6237 return map_nt_error_from_unix(errno);
6242 /* XXX: need to add support for changing the create_time here. You
6243 * can do this for paths on Darwin with setattrlist(2). The right way
6244 * to hook this up is probably by extending the VFS utimes interface.
6247 return NT_STATUS_OK;
6250 /****************************************************************************
6251 Create a directory with POSIX semantics.
6252 ****************************************************************************/
6254 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6255 struct smb_request *req,
6256 char **ppdata,
6257 int total_data,
6258 const char *fname,
6259 SMB_STRUCT_STAT *psbuf,
6260 int *pdata_return_size)
6262 NTSTATUS status = NT_STATUS_OK;
6263 uint32 raw_unixmode = 0;
6264 uint32 mod_unixmode = 0;
6265 mode_t unixmode = (mode_t)0;
6266 files_struct *fsp = NULL;
6267 uint16 info_level_return = 0;
6268 int info;
6269 char *pdata = *ppdata;
6271 if (total_data < 18) {
6272 return NT_STATUS_INVALID_PARAMETER;
6275 raw_unixmode = IVAL(pdata,8);
6276 /* Next 4 bytes are not yet defined. */
6278 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 return status;
6283 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6285 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6286 fname, (unsigned int)unixmode ));
6288 status = open_directory(conn, req,
6289 fname,
6290 psbuf,
6291 FILE_READ_ATTRIBUTES, /* Just a stat open */
6292 FILE_SHARE_NONE, /* Ignored for stat opens */
6293 FILE_CREATE,
6295 mod_unixmode,
6296 &info,
6297 &fsp);
6299 if (NT_STATUS_IS_OK(status)) {
6300 close_file(fsp, NORMAL_CLOSE);
6303 info_level_return = SVAL(pdata,16);
6305 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6306 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6307 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6308 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6309 } else {
6310 *pdata_return_size = 12;
6313 /* Realloc the data size */
6314 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6315 if (*ppdata == NULL) {
6316 *pdata_return_size = 0;
6317 return NT_STATUS_NO_MEMORY;
6319 pdata = *ppdata;
6321 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6322 SSVAL(pdata,2,0); /* No fnum. */
6323 SIVAL(pdata,4,info); /* Was directory created. */
6325 switch (info_level_return) {
6326 case SMB_QUERY_FILE_UNIX_BASIC:
6327 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6328 SSVAL(pdata,10,0); /* Padding. */
6329 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6330 break;
6331 case SMB_QUERY_FILE_UNIX_INFO2:
6332 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6333 SSVAL(pdata,10,0); /* Padding. */
6334 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6335 break;
6336 default:
6337 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6338 SSVAL(pdata,10,0); /* Padding. */
6339 break;
6342 return status;
6345 /****************************************************************************
6346 Open/Create a file with POSIX semantics.
6347 ****************************************************************************/
6349 static NTSTATUS smb_posix_open(connection_struct *conn,
6350 struct smb_request *req,
6351 char **ppdata,
6352 int total_data,
6353 const char *fname,
6354 SMB_STRUCT_STAT *psbuf,
6355 int *pdata_return_size)
6357 bool extended_oplock_granted = False;
6358 char *pdata = *ppdata;
6359 uint32 flags = 0;
6360 uint32 wire_open_mode = 0;
6361 uint32 raw_unixmode = 0;
6362 uint32 mod_unixmode = 0;
6363 uint32 create_disp = 0;
6364 uint32 access_mask = 0;
6365 uint32 create_options = 0;
6366 NTSTATUS status = NT_STATUS_OK;
6367 mode_t unixmode = (mode_t)0;
6368 files_struct *fsp = NULL;
6369 int oplock_request = 0;
6370 int info = 0;
6371 uint16 info_level_return = 0;
6373 if (total_data < 18) {
6374 return NT_STATUS_INVALID_PARAMETER;
6377 flags = IVAL(pdata,0);
6378 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6379 if (oplock_request) {
6380 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6383 wire_open_mode = IVAL(pdata,4);
6385 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6386 return smb_posix_mkdir(conn, req,
6387 ppdata,
6388 total_data,
6389 fname,
6390 psbuf,
6391 pdata_return_size);
6394 switch (wire_open_mode & SMB_ACCMODE) {
6395 case SMB_O_RDONLY:
6396 access_mask = FILE_READ_DATA;
6397 break;
6398 case SMB_O_WRONLY:
6399 access_mask = FILE_WRITE_DATA;
6400 break;
6401 case SMB_O_RDWR:
6402 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6403 break;
6404 default:
6405 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6406 (unsigned int)wire_open_mode ));
6407 return NT_STATUS_INVALID_PARAMETER;
6410 wire_open_mode &= ~SMB_ACCMODE;
6412 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6413 create_disp = FILE_CREATE;
6414 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6415 create_disp = FILE_OVERWRITE_IF;
6416 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6417 create_disp = FILE_OPEN_IF;
6418 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6419 create_disp = FILE_OPEN;
6420 } else {
6421 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6422 (unsigned int)wire_open_mode ));
6423 return NT_STATUS_INVALID_PARAMETER;
6426 raw_unixmode = IVAL(pdata,8);
6427 /* Next 4 bytes are not yet defined. */
6429 status = unix_perms_from_wire(conn,
6430 psbuf,
6431 raw_unixmode,
6432 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6433 &unixmode);
6435 if (!NT_STATUS_IS_OK(status)) {
6436 return status;
6439 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6441 if (wire_open_mode & SMB_O_SYNC) {
6442 create_options |= FILE_WRITE_THROUGH;
6444 if (wire_open_mode & SMB_O_APPEND) {
6445 access_mask |= FILE_APPEND_DATA;
6447 if (wire_open_mode & SMB_O_DIRECT) {
6448 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6451 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6452 fname,
6453 (unsigned int)wire_open_mode,
6454 (unsigned int)unixmode ));
6456 status = open_file_ntcreate(conn, req,
6457 fname,
6458 psbuf,
6459 access_mask,
6460 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6461 create_disp,
6462 0, /* no create options yet. */
6463 mod_unixmode,
6464 oplock_request,
6465 &info,
6466 &fsp);
6468 if (!NT_STATUS_IS_OK(status)) {
6469 return status;
6472 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6473 extended_oplock_granted = True;
6476 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6477 extended_oplock_granted = True;
6480 info_level_return = SVAL(pdata,16);
6482 /* Allocate the correct return size. */
6484 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6485 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6486 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6487 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6488 } else {
6489 *pdata_return_size = 12;
6492 /* Realloc the data size */
6493 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6494 if (*ppdata == NULL) {
6495 close_file(fsp,ERROR_CLOSE);
6496 *pdata_return_size = 0;
6497 return NT_STATUS_NO_MEMORY;
6499 pdata = *ppdata;
6501 if (extended_oplock_granted) {
6502 if (flags & REQUEST_BATCH_OPLOCK) {
6503 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6504 } else {
6505 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6507 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6508 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6509 } else {
6510 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6513 SSVAL(pdata,2,fsp->fnum);
6514 SIVAL(pdata,4,info); /* Was file created etc. */
6516 switch (info_level_return) {
6517 case SMB_QUERY_FILE_UNIX_BASIC:
6518 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6519 SSVAL(pdata,10,0); /* padding. */
6520 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6521 break;
6522 case SMB_QUERY_FILE_UNIX_INFO2:
6523 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6524 SSVAL(pdata,10,0); /* padding. */
6525 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6526 break;
6527 default:
6528 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6529 SSVAL(pdata,10,0); /* padding. */
6530 break;
6532 return NT_STATUS_OK;
6535 /****************************************************************************
6536 Delete a file with POSIX semantics.
6537 ****************************************************************************/
6539 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6540 struct smb_request *req,
6541 const char *pdata,
6542 int total_data,
6543 const char *fname,
6544 SMB_STRUCT_STAT *psbuf)
6546 NTSTATUS status = NT_STATUS_OK;
6547 files_struct *fsp = NULL;
6548 uint16 flags = 0;
6549 char del = 1;
6550 int info = 0;
6551 int i;
6552 struct share_mode_lock *lck = NULL;
6554 if (total_data < 2) {
6555 return NT_STATUS_INVALID_PARAMETER;
6558 flags = SVAL(pdata,0);
6560 if (!VALID_STAT(*psbuf)) {
6561 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6564 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6565 !VALID_STAT_OF_DIR(*psbuf)) {
6566 return NT_STATUS_NOT_A_DIRECTORY;
6569 DEBUG(10,("smb_posix_unlink: %s %s\n",
6570 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6571 fname));
6573 if (VALID_STAT_OF_DIR(*psbuf)) {
6574 status = open_directory(conn, req,
6575 fname,
6576 psbuf,
6577 DELETE_ACCESS,
6578 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6579 FILE_OPEN,
6581 FILE_FLAG_POSIX_SEMANTICS|0777,
6582 &info,
6583 &fsp);
6584 } else {
6586 status = open_file_ntcreate(conn, req,
6587 fname,
6588 psbuf,
6589 DELETE_ACCESS,
6590 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6591 FILE_OPEN,
6593 FILE_FLAG_POSIX_SEMANTICS|0777,
6594 0, /* No oplock, but break existing ones. */
6595 &info,
6596 &fsp);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 return status;
6604 * Don't lie to client. If we can't really delete due to
6605 * non-POSIX opens return SHARING_VIOLATION.
6608 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6609 NULL);
6610 if (lck == NULL) {
6611 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6612 "lock for file %s\n", fsp->fsp_name));
6613 close_file(fsp, NORMAL_CLOSE);
6614 return NT_STATUS_INVALID_PARAMETER;
6618 * See if others still have the file open. If this is the case, then
6619 * don't delete. If all opens are POSIX delete we can set the delete
6620 * on close disposition.
6622 for (i=0; i<lck->num_share_modes; i++) {
6623 struct share_mode_entry *e = &lck->share_modes[i];
6624 if (is_valid_share_mode_entry(e)) {
6625 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6626 continue;
6628 /* Fail with sharing violation. */
6629 close_file(fsp, NORMAL_CLOSE);
6630 TALLOC_FREE(lck);
6631 return NT_STATUS_SHARING_VIOLATION;
6636 * Set the delete on close.
6638 status = smb_set_file_disposition_info(conn,
6639 &del,
6641 fsp,
6642 fname,
6643 psbuf);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 close_file(fsp, NORMAL_CLOSE);
6647 TALLOC_FREE(lck);
6648 return status;
6650 TALLOC_FREE(lck);
6651 return close_file(fsp, NORMAL_CLOSE);
6654 /****************************************************************************
6655 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6656 ****************************************************************************/
6658 static void call_trans2setfilepathinfo(connection_struct *conn,
6659 struct smb_request *req,
6660 unsigned int tran_call,
6661 char **pparams, int total_params,
6662 char **ppdata, int total_data,
6663 unsigned int max_data_bytes)
6665 char *params = *pparams;
6666 char *pdata = *ppdata;
6667 uint16 info_level;
6668 SMB_STRUCT_STAT sbuf;
6669 char *fname = NULL;
6670 files_struct *fsp = NULL;
6671 NTSTATUS status = NT_STATUS_OK;
6672 int data_return_size = 0;
6673 TALLOC_CTX *ctx = talloc_tos();
6675 if (!params) {
6676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6677 return;
6680 ZERO_STRUCT(sbuf);
6682 if (tran_call == TRANSACT2_SETFILEINFO) {
6683 if (total_params < 4) {
6684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6685 return;
6688 fsp = file_fsp(SVAL(params,0));
6689 /* Basic check for non-null fsp. */
6690 if (!check_fsp_open(conn, req, fsp)) {
6691 return;
6693 info_level = SVAL(params,2);
6695 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6696 if (!fname) {
6697 reply_nterror(req, NT_STATUS_NO_MEMORY);
6698 return;
6701 if(fsp->is_directory || fsp->fh->fd == -1) {
6703 * This is actually a SETFILEINFO on a directory
6704 * handle (returned from an NT SMB). NT5.0 seems
6705 * to do this call. JRA.
6707 if (INFO_LEVEL_IS_UNIX(info_level)) {
6708 /* Always do lstat for UNIX calls. */
6709 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6710 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6711 reply_unixerror(req,ERRDOS,ERRbadpath);
6712 return;
6714 } else {
6715 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6716 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6717 reply_unixerror(req,ERRDOS,ERRbadpath);
6718 return;
6721 } else if (fsp->print_file) {
6723 * Doing a DELETE_ON_CLOSE should cancel a print job.
6725 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6726 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6728 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6730 SSVAL(params,0,0);
6731 send_trans2_replies(conn, req, params, 2,
6732 *ppdata, 0,
6733 max_data_bytes);
6734 return;
6735 } else {
6736 reply_unixerror(req, ERRDOS, ERRbadpath);
6737 return;
6739 } else {
6741 * Original code - this is an open file.
6743 if (!check_fsp(conn, req, fsp)) {
6744 return;
6747 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6748 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6749 reply_unixerror(req, ERRDOS, ERRbadfid);
6750 return;
6753 } else {
6754 /* set path info */
6755 if (total_params < 7) {
6756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6757 return;
6760 info_level = SVAL(params,0);
6761 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6762 total_params - 6, STR_TERMINATE,
6763 &status);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, status);
6766 return;
6769 status = resolve_dfspath(ctx, conn,
6770 req->flags2 & FLAGS2_DFS_PATHNAMES,
6771 fname,
6772 &fname);
6773 if (!NT_STATUS_IS_OK(status)) {
6774 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6775 reply_botherror(req,
6776 NT_STATUS_PATH_NOT_COVERED,
6777 ERRSRV, ERRbadpath);
6778 return;
6780 reply_nterror(req, status);
6781 return;
6784 status = unix_convert(ctx, conn, fname, False,
6785 &fname, NULL, &sbuf);
6786 if (!NT_STATUS_IS_OK(status)) {
6787 reply_nterror(req, status);
6788 return;
6791 status = check_name(conn, fname);
6792 if (!NT_STATUS_IS_OK(status)) {
6793 reply_nterror(req, status);
6794 return;
6797 if (INFO_LEVEL_IS_UNIX(info_level)) {
6799 * For CIFS UNIX extensions the target name may not exist.
6802 /* Always do lstat for UNIX calls. */
6803 SMB_VFS_LSTAT(conn,fname,&sbuf);
6805 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6806 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6807 reply_unixerror(req, ERRDOS, ERRbadpath);
6808 return;
6812 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6813 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6814 return;
6817 if (!CAN_WRITE(conn)) {
6818 /* Allow POSIX opens. The open path will deny
6819 * any non-readonly opens. */
6820 if (info_level != SMB_POSIX_PATH_OPEN) {
6821 reply_doserror(req, ERRSRV, ERRaccess);
6822 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 = resolve_dfspath(ctx,
7132 conn,
7133 req->flags2 & FLAGS2_DFS_PATHNAMES,
7134 directory,
7135 &directory);
7136 if (!NT_STATUS_IS_OK(status)) {
7137 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7138 reply_botherror(req,
7139 NT_STATUS_PATH_NOT_COVERED,
7140 ERRSRV, ERRbadpath);
7142 reply_nterror(req, status);
7143 return;
7146 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7147 if (!NT_STATUS_IS_OK(status)) {
7148 reply_nterror(req, status);
7149 return;
7152 status = check_name(conn, directory);
7153 if (!NT_STATUS_IS_OK(status)) {
7154 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7155 reply_nterror(req, status);
7156 return;
7159 /* Any data in this call is an EA list. */
7160 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7161 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7162 return;
7166 * OS/2 workplace shell seems to send SET_EA requests of "null"
7167 * length (4 bytes containing IVAL 4).
7168 * They seem to have no effect. Bug #3212. JRA.
7171 if (total_data != 4) {
7172 if (total_data < 10) {
7173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7174 return;
7177 if (IVAL(pdata,0) > total_data) {
7178 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7179 IVAL(pdata,0), (unsigned int)total_data));
7180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7181 return;
7184 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7185 total_data - 4);
7186 if (!ea_list) {
7187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7188 return;
7191 /* If total_data == 4 Windows doesn't care what values
7192 * are placed in that field, it just ignores them.
7193 * The System i QNTC IBM SMB client puts bad values here,
7194 * so ignore them. */
7196 status = create_directory(conn, req, directory);
7198 if (!NT_STATUS_IS_OK(status)) {
7199 reply_nterror(req, status);
7200 return;
7203 /* Try and set any given EA. */
7204 if (ea_list) {
7205 status = set_ea(conn, NULL, directory, ea_list);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 reply_nterror(req, status);
7208 return;
7212 /* Realloc the parameter and data sizes */
7213 *pparams = (char *)SMB_REALLOC(*pparams,2);
7214 if(*pparams == NULL) {
7215 reply_nterror(req, NT_STATUS_NO_MEMORY);
7216 return;
7218 params = *pparams;
7220 SSVAL(params,0,0);
7222 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7224 return;
7227 /****************************************************************************
7228 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7229 We don't actually do this - we just send a null response.
7230 ****************************************************************************/
7232 static void call_trans2findnotifyfirst(connection_struct *conn,
7233 struct smb_request *req,
7234 char **pparams, int total_params,
7235 char **ppdata, int total_data,
7236 unsigned int max_data_bytes)
7238 static uint16 fnf_handle = 257;
7239 char *params = *pparams;
7240 uint16 info_level;
7242 if (total_params < 6) {
7243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7244 return;
7247 info_level = SVAL(params,4);
7248 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7250 switch (info_level) {
7251 case 1:
7252 case 2:
7253 break;
7254 default:
7255 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7256 return;
7259 /* Realloc the parameter and data sizes */
7260 *pparams = (char *)SMB_REALLOC(*pparams,6);
7261 if (*pparams == NULL) {
7262 reply_nterror(req, NT_STATUS_NO_MEMORY);
7263 return;
7265 params = *pparams;
7267 SSVAL(params,0,fnf_handle);
7268 SSVAL(params,2,0); /* No changes */
7269 SSVAL(params,4,0); /* No EA errors */
7271 fnf_handle++;
7273 if(fnf_handle == 0)
7274 fnf_handle = 257;
7276 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7278 return;
7281 /****************************************************************************
7282 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7283 changes). Currently this does nothing.
7284 ****************************************************************************/
7286 static void call_trans2findnotifynext(connection_struct *conn,
7287 struct smb_request *req,
7288 char **pparams, int total_params,
7289 char **ppdata, int total_data,
7290 unsigned int max_data_bytes)
7292 char *params = *pparams;
7294 DEBUG(3,("call_trans2findnotifynext\n"));
7296 /* Realloc the parameter and data sizes */
7297 *pparams = (char *)SMB_REALLOC(*pparams,4);
7298 if (*pparams == NULL) {
7299 reply_nterror(req, NT_STATUS_NO_MEMORY);
7300 return;
7302 params = *pparams;
7304 SSVAL(params,0,0); /* No changes */
7305 SSVAL(params,2,0); /* No EA errors */
7307 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7309 return;
7312 /****************************************************************************
7313 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7314 ****************************************************************************/
7316 static void call_trans2getdfsreferral(connection_struct *conn,
7317 struct smb_request *req,
7318 char **pparams, int total_params,
7319 char **ppdata, int total_data,
7320 unsigned int max_data_bytes)
7322 char *params = *pparams;
7323 char *pathname = NULL;
7324 int reply_size = 0;
7325 int max_referral_level;
7326 NTSTATUS status = NT_STATUS_OK;
7327 TALLOC_CTX *ctx = talloc_tos();
7329 DEBUG(10,("call_trans2getdfsreferral\n"));
7331 if (total_params < 3) {
7332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7333 return;
7336 max_referral_level = SVAL(params,0);
7338 if(!lp_host_msdfs()) {
7339 reply_doserror(req, ERRDOS, ERRbadfunc);
7340 return;
7343 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7344 total_params - 2, STR_TERMINATE);
7345 if (!pathname) {
7346 reply_nterror(req, NT_STATUS_NOT_FOUND);
7347 return;
7349 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7350 ppdata,&status)) < 0) {
7351 reply_nterror(req, status);
7352 return;
7355 SSVAL(req->inbuf, smb_flg2,
7356 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7357 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7359 return;
7362 #define LMCAT_SPL 0x53
7363 #define LMFUNC_GETJOBID 0x60
7365 /****************************************************************************
7366 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7367 ****************************************************************************/
7369 static void call_trans2ioctl(connection_struct *conn,
7370 struct smb_request *req,
7371 char **pparams, int total_params,
7372 char **ppdata, int total_data,
7373 unsigned int max_data_bytes)
7375 char *pdata = *ppdata;
7376 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7378 /* check for an invalid fid before proceeding */
7380 if (!fsp) {
7381 reply_doserror(req, ERRDOS, ERRbadfid);
7382 return;
7385 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7386 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7387 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7388 if (*ppdata == NULL) {
7389 reply_nterror(req, NT_STATUS_NO_MEMORY);
7390 return;
7392 pdata = *ppdata;
7394 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7395 CAN ACCEPT THIS IN UNICODE. JRA. */
7397 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7398 srvstr_push(pdata, req->flags2, pdata + 2,
7399 global_myname(), 15,
7400 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7401 srvstr_push(pdata, req->flags2, pdata+18,
7402 lp_servicename(SNUM(conn)), 13,
7403 STR_ASCII|STR_TERMINATE); /* Service name */
7404 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7405 max_data_bytes);
7406 return;
7409 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7410 reply_doserror(req, ERRSRV, ERRerror);
7413 /****************************************************************************
7414 Reply to a SMBfindclose (stop trans2 directory search).
7415 ****************************************************************************/
7417 void reply_findclose(struct smb_request *req)
7419 int dptr_num;
7421 START_PROFILE(SMBfindclose);
7423 if (req->wct < 1) {
7424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7425 END_PROFILE(SMBfindclose);
7426 return;
7429 dptr_num = SVALS(req->inbuf,smb_vwv0);
7431 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7433 dptr_close(&dptr_num);
7435 reply_outbuf(req, 0, 0);
7437 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7439 END_PROFILE(SMBfindclose);
7440 return;
7443 /****************************************************************************
7444 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7445 ****************************************************************************/
7447 void reply_findnclose(struct smb_request *req)
7449 int dptr_num;
7451 START_PROFILE(SMBfindnclose);
7453 if (req->wct < 1) {
7454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7455 END_PROFILE(SMBfindnclose);
7456 return;
7459 dptr_num = SVAL(req->inbuf,smb_vwv0);
7461 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7463 /* We never give out valid handles for a
7464 findnotifyfirst - so any dptr_num is ok here.
7465 Just ignore it. */
7467 reply_outbuf(req, 0, 0);
7469 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7471 END_PROFILE(SMBfindnclose);
7472 return;
7475 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7476 struct trans_state *state)
7478 if (Protocol >= PROTOCOL_NT1) {
7479 req->flags2 |= 0x40; /* IS_LONG_NAME */
7480 SSVAL(req->inbuf,smb_flg2,req->flags2);
7483 if (conn->encrypt_level == Required && !req->encrypted) {
7484 if (state->call != TRANSACT2_QFSINFO &&
7485 state->call != TRANSACT2_SETFSINFO) {
7486 DEBUG(0,("handle_trans2: encryption required "
7487 "with call 0x%x\n",
7488 (unsigned int)state->call));
7489 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7490 return;
7494 /* Now we must call the relevant TRANS2 function */
7495 switch(state->call) {
7496 case TRANSACT2_OPEN:
7498 START_PROFILE(Trans2_open);
7499 call_trans2open(conn, req,
7500 &state->param, state->total_param,
7501 &state->data, state->total_data,
7502 state->max_data_return);
7503 END_PROFILE(Trans2_open);
7504 break;
7507 case TRANSACT2_FINDFIRST:
7509 START_PROFILE(Trans2_findfirst);
7510 call_trans2findfirst(conn, req,
7511 &state->param, state->total_param,
7512 &state->data, state->total_data,
7513 state->max_data_return);
7514 END_PROFILE(Trans2_findfirst);
7515 break;
7518 case TRANSACT2_FINDNEXT:
7520 START_PROFILE(Trans2_findnext);
7521 call_trans2findnext(conn, req,
7522 &state->param, state->total_param,
7523 &state->data, state->total_data,
7524 state->max_data_return);
7525 END_PROFILE(Trans2_findnext);
7526 break;
7529 case TRANSACT2_QFSINFO:
7531 START_PROFILE(Trans2_qfsinfo);
7532 call_trans2qfsinfo(conn, req,
7533 &state->param, state->total_param,
7534 &state->data, state->total_data,
7535 state->max_data_return);
7536 END_PROFILE(Trans2_qfsinfo);
7537 break;
7540 case TRANSACT2_SETFSINFO:
7542 START_PROFILE(Trans2_setfsinfo);
7543 call_trans2setfsinfo(conn, req,
7544 &state->param, state->total_param,
7545 &state->data, state->total_data,
7546 state->max_data_return);
7547 END_PROFILE(Trans2_setfsinfo);
7548 break;
7551 case TRANSACT2_QPATHINFO:
7552 case TRANSACT2_QFILEINFO:
7554 START_PROFILE(Trans2_qpathinfo);
7555 call_trans2qfilepathinfo(conn, req, state->call,
7556 &state->param, state->total_param,
7557 &state->data, state->total_data,
7558 state->max_data_return);
7559 END_PROFILE(Trans2_qpathinfo);
7560 break;
7563 case TRANSACT2_SETPATHINFO:
7564 case TRANSACT2_SETFILEINFO:
7566 START_PROFILE(Trans2_setpathinfo);
7567 call_trans2setfilepathinfo(conn, req, state->call,
7568 &state->param, state->total_param,
7569 &state->data, state->total_data,
7570 state->max_data_return);
7571 END_PROFILE(Trans2_setpathinfo);
7572 break;
7575 case TRANSACT2_FINDNOTIFYFIRST:
7577 START_PROFILE(Trans2_findnotifyfirst);
7578 call_trans2findnotifyfirst(conn, req,
7579 &state->param, state->total_param,
7580 &state->data, state->total_data,
7581 state->max_data_return);
7582 END_PROFILE(Trans2_findnotifyfirst);
7583 break;
7586 case TRANSACT2_FINDNOTIFYNEXT:
7588 START_PROFILE(Trans2_findnotifynext);
7589 call_trans2findnotifynext(conn, req,
7590 &state->param, state->total_param,
7591 &state->data, state->total_data,
7592 state->max_data_return);
7593 END_PROFILE(Trans2_findnotifynext);
7594 break;
7597 case TRANSACT2_MKDIR:
7599 START_PROFILE(Trans2_mkdir);
7600 call_trans2mkdir(conn, req,
7601 &state->param, state->total_param,
7602 &state->data, state->total_data,
7603 state->max_data_return);
7604 END_PROFILE(Trans2_mkdir);
7605 break;
7608 case TRANSACT2_GET_DFS_REFERRAL:
7610 START_PROFILE(Trans2_get_dfs_referral);
7611 call_trans2getdfsreferral(conn, req,
7612 &state->param, state->total_param,
7613 &state->data, state->total_data,
7614 state->max_data_return);
7615 END_PROFILE(Trans2_get_dfs_referral);
7616 break;
7619 case TRANSACT2_IOCTL:
7621 START_PROFILE(Trans2_ioctl);
7622 call_trans2ioctl(conn, req,
7623 &state->param, state->total_param,
7624 &state->data, state->total_data,
7625 state->max_data_return);
7626 END_PROFILE(Trans2_ioctl);
7627 break;
7630 default:
7631 /* Error in request */
7632 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7633 reply_doserror(req, ERRSRV,ERRerror);
7637 /****************************************************************************
7638 Reply to a SMBtrans2.
7639 ****************************************************************************/
7641 void reply_trans2(struct smb_request *req)
7643 connection_struct *conn = req->conn;
7644 unsigned int dsoff;
7645 unsigned int dscnt;
7646 unsigned int psoff;
7647 unsigned int pscnt;
7648 unsigned int tran_call;
7649 unsigned int size;
7650 unsigned int av_size;
7651 struct trans_state *state;
7652 NTSTATUS result;
7654 START_PROFILE(SMBtrans2);
7656 if (req->wct < 14) {
7657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7658 END_PROFILE(SMBtrans2);
7659 return;
7662 dsoff = SVAL(req->inbuf, smb_dsoff);
7663 dscnt = SVAL(req->inbuf, smb_dscnt);
7664 psoff = SVAL(req->inbuf, smb_psoff);
7665 pscnt = SVAL(req->inbuf, smb_pscnt);
7666 tran_call = SVAL(req->inbuf, smb_setup0);
7667 size = smb_len(req->inbuf) + 4;
7668 av_size = smb_len(req->inbuf);
7670 result = allow_new_trans(conn->pending_trans, req->mid);
7671 if (!NT_STATUS_IS_OK(result)) {
7672 DEBUG(2, ("Got invalid trans2 request: %s\n",
7673 nt_errstr(result)));
7674 reply_nterror(req, result);
7675 END_PROFILE(SMBtrans2);
7676 return;
7679 if (IS_IPC(conn)) {
7680 switch (tran_call) {
7681 /* List the allowed trans2 calls on IPC$ */
7682 case TRANSACT2_OPEN:
7683 case TRANSACT2_GET_DFS_REFERRAL:
7684 case TRANSACT2_QFILEINFO:
7685 case TRANSACT2_QFSINFO:
7686 case TRANSACT2_SETFSINFO:
7687 break;
7688 default:
7689 reply_doserror(req, ERRSRV, ERRaccess);
7690 END_PROFILE(SMBtrans2);
7691 return;
7695 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7696 DEBUG(0, ("talloc failed\n"));
7697 reply_nterror(req, NT_STATUS_NO_MEMORY);
7698 END_PROFILE(SMBtrans2);
7699 return;
7702 state->cmd = SMBtrans2;
7704 state->mid = req->mid;
7705 state->vuid = req->vuid;
7706 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7707 state->setup = NULL;
7708 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7709 state->param = NULL;
7710 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7711 state->data = NULL;
7712 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7713 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7714 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7715 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7716 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7718 state->call = tran_call;
7720 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7721 is so as a sanity check */
7722 if (state->setup_count != 1) {
7724 * Need to have rc=0 for ioctl to get job id for OS/2.
7725 * Network printing will fail if function is not successful.
7726 * Similar function in reply.c will be used if protocol
7727 * is LANMAN1.0 instead of LM1.2X002.
7728 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7729 * outbuf doesn't have to be set(only job id is used).
7731 if ( (state->setup_count == 4)
7732 && (tran_call == TRANSACT2_IOCTL)
7733 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7734 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7735 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7736 } else {
7737 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7738 DEBUG(2,("Transaction is %d\n",tran_call));
7739 TALLOC_FREE(state);
7740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7741 END_PROFILE(SMBtrans2);
7742 return;
7746 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7747 goto bad_param;
7749 if (state->total_data) {
7750 /* Can't use talloc here, the core routines do realloc on the
7751 * params and data. */
7752 state->data = (char *)SMB_MALLOC(state->total_data);
7753 if (state->data == NULL) {
7754 DEBUG(0,("reply_trans2: data malloc fail for %u "
7755 "bytes !\n", (unsigned int)state->total_data));
7756 TALLOC_FREE(state);
7757 reply_nterror(req, NT_STATUS_NO_MEMORY);
7758 END_PROFILE(SMBtrans2);
7759 return;
7762 if (dscnt > state->total_data ||
7763 dsoff+dscnt < dsoff) {
7764 goto bad_param;
7767 if (dsoff > av_size ||
7768 dscnt > av_size ||
7769 dsoff+dscnt > av_size) {
7770 goto bad_param;
7773 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7776 if (state->total_param) {
7777 /* Can't use talloc here, the core routines do realloc on the
7778 * params and data. */
7779 state->param = (char *)SMB_MALLOC(state->total_param);
7780 if (state->param == NULL) {
7781 DEBUG(0,("reply_trans: param malloc fail for %u "
7782 "bytes !\n", (unsigned int)state->total_param));
7783 SAFE_FREE(state->data);
7784 TALLOC_FREE(state);
7785 reply_nterror(req, NT_STATUS_NO_MEMORY);
7786 END_PROFILE(SMBtrans2);
7787 return;
7790 if (pscnt > state->total_param ||
7791 psoff+pscnt < psoff) {
7792 goto bad_param;
7795 if (psoff > av_size ||
7796 pscnt > av_size ||
7797 psoff+pscnt > av_size) {
7798 goto bad_param;
7801 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7804 state->received_data = dscnt;
7805 state->received_param = pscnt;
7807 if ((state->received_param == state->total_param) &&
7808 (state->received_data == state->total_data)) {
7810 handle_trans2(conn, req, state);
7812 SAFE_FREE(state->data);
7813 SAFE_FREE(state->param);
7814 TALLOC_FREE(state);
7815 END_PROFILE(SMBtrans2);
7816 return;
7819 DLIST_ADD(conn->pending_trans, state);
7821 /* We need to send an interim response then receive the rest
7822 of the parameter/data bytes */
7823 reply_outbuf(req, 0, 0);
7824 show_msg((char *)req->outbuf);
7825 END_PROFILE(SMBtrans2);
7826 return;
7828 bad_param:
7830 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7831 SAFE_FREE(state->data);
7832 SAFE_FREE(state->param);
7833 TALLOC_FREE(state);
7834 END_PROFILE(SMBtrans2);
7835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7839 /****************************************************************************
7840 Reply to a SMBtranss2
7841 ****************************************************************************/
7843 void reply_transs2(struct smb_request *req)
7845 connection_struct *conn = req->conn;
7846 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7847 struct trans_state *state;
7848 unsigned int size;
7849 unsigned int av_size;
7851 START_PROFILE(SMBtranss2);
7853 show_msg((char *)req->inbuf);
7855 if (req->wct < 8) {
7856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7857 END_PROFILE(SMBtranss2);
7858 return;
7861 size = smb_len(req->inbuf)+4;
7862 av_size = smb_len(req->inbuf);
7864 for (state = conn->pending_trans; state != NULL;
7865 state = state->next) {
7866 if (state->mid == req->mid) {
7867 break;
7871 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7873 END_PROFILE(SMBtranss2);
7874 return;
7877 /* Revise state->total_param and state->total_data in case they have
7878 changed downwards */
7880 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7881 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7882 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7883 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7885 pcnt = SVAL(req->inbuf, smb_spscnt);
7886 poff = SVAL(req->inbuf, smb_spsoff);
7887 pdisp = SVAL(req->inbuf, smb_spsdisp);
7889 dcnt = SVAL(req->inbuf, smb_sdscnt);
7890 doff = SVAL(req->inbuf, smb_sdsoff);
7891 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7893 state->received_param += pcnt;
7894 state->received_data += dcnt;
7896 if ((state->received_data > state->total_data) ||
7897 (state->received_param > state->total_param))
7898 goto bad_param;
7900 if (pcnt) {
7901 if (pdisp > state->total_param ||
7902 pcnt > state->total_param ||
7903 pdisp+pcnt > state->total_param ||
7904 pdisp+pcnt < pdisp) {
7905 goto bad_param;
7908 if (poff > av_size ||
7909 pcnt > av_size ||
7910 poff+pcnt > av_size ||
7911 poff+pcnt < poff) {
7912 goto bad_param;
7915 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7916 pcnt);
7919 if (dcnt) {
7920 if (ddisp > state->total_data ||
7921 dcnt > state->total_data ||
7922 ddisp+dcnt > state->total_data ||
7923 ddisp+dcnt < ddisp) {
7924 goto bad_param;
7927 if (doff > av_size ||
7928 dcnt > av_size ||
7929 doff+dcnt > av_size ||
7930 doff+dcnt < doff) {
7931 goto bad_param;
7934 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7935 dcnt);
7938 if ((state->received_param < state->total_param) ||
7939 (state->received_data < state->total_data)) {
7940 END_PROFILE(SMBtranss2);
7941 return;
7945 * construct_reply_common will copy smb_com from inbuf to
7946 * outbuf. SMBtranss2 is wrong here.
7948 SCVAL(req->inbuf,smb_com,SMBtrans2);
7950 handle_trans2(conn, req, state);
7952 DLIST_REMOVE(conn->pending_trans, state);
7953 SAFE_FREE(state->data);
7954 SAFE_FREE(state->param);
7955 TALLOC_FREE(state);
7957 END_PROFILE(SMBtranss2);
7958 return;
7960 bad_param:
7962 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7963 DLIST_REMOVE(conn->pending_trans, state);
7964 SAFE_FREE(state->data);
7965 SAFE_FREE(state->param);
7966 TALLOC_FREE(state);
7967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7968 END_PROFILE(SMBtranss2);
7969 return;