The compatibility function also should have a const buffer pointer
[Samba/gbeck.git] / source3 / smbd / trans2.c
blob881b29c6f0ac76265344124282187ef0b88c342b
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 /* useable_space can never be more than max_send minus the alignment offset. */
749 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
751 while (params_to_send || data_to_send) {
752 /* Calculate whether we will totally or partially fill this packet */
754 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
756 /* We can never send more than useable_space */
758 * Note that 'useable_space' does not include the alignment offsets,
759 * but we must include the alignment offsets in the calculation of
760 * the length of the data we send over the wire, as the alignment offsets
761 * are sent here. Fix from Marc_Jacobsen@hp.com.
764 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
766 reply_outbuf(req, 10, total_sent_thistime);
768 /* Set total params and data to be sent */
769 SSVAL(req->outbuf,smb_tprcnt,paramsize);
770 SSVAL(req->outbuf,smb_tdrcnt,datasize);
772 /* Calculate how many parameters and data we can fit into
773 * this packet. Parameters get precedence
776 params_sent_thistime = MIN(params_to_send,useable_space);
777 data_sent_thistime = useable_space - params_sent_thistime;
778 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
780 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
782 /* smb_proff is the offset from the start of the SMB header to the
783 parameter bytes, however the first 4 bytes of outbuf are
784 the Netbios over TCP header. Thus use smb_base() to subtract
785 them from the calculation */
787 SSVAL(req->outbuf,smb_proff,
788 ((smb_buf(req->outbuf)+alignment_offset)
789 - smb_base(req->outbuf)));
791 if(params_sent_thistime == 0)
792 SSVAL(req->outbuf,smb_prdisp,0);
793 else
794 /* Absolute displacement of param bytes sent in this packet */
795 SSVAL(req->outbuf,smb_prdisp,pp - params);
797 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
798 if(data_sent_thistime == 0) {
799 SSVAL(req->outbuf,smb_droff,0);
800 SSVAL(req->outbuf,smb_drdisp, 0);
801 } else {
802 /* The offset of the data bytes is the offset of the
803 parameter bytes plus the number of parameters being sent this time */
804 SSVAL(req->outbuf, smb_droff,
805 ((smb_buf(req->outbuf)+alignment_offset)
806 - smb_base(req->outbuf))
807 + params_sent_thistime + data_alignment_offset);
808 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
811 /* Initialize the padding for alignment */
813 if (alignment_offset != 0) {
814 memset(smb_buf(req->outbuf), 0, alignment_offset);
817 /* Copy the param bytes into the packet */
819 if(params_sent_thistime) {
820 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
821 params_sent_thistime);
824 /* Copy in the data bytes */
825 if(data_sent_thistime) {
826 if (data_alignment_offset != 0) {
827 memset((smb_buf(req->outbuf)+alignment_offset+
828 params_sent_thistime), 0,
829 data_alignment_offset);
831 memcpy(smb_buf(req->outbuf)+alignment_offset
832 +params_sent_thistime+data_alignment_offset,
833 pd,data_sent_thistime);
836 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
837 params_sent_thistime, data_sent_thistime, useable_space));
838 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
839 params_to_send, data_to_send, paramsize, datasize));
841 if (overflow) {
842 error_packet_set((char *)req->outbuf,
843 ERRDOS,ERRbufferoverflow,
844 STATUS_BUFFER_OVERFLOW,
845 __LINE__,__FILE__);
848 /* Send the packet */
849 show_msg((char *)req->outbuf);
850 if (!srv_send_smb(smbd_server_fd(),
851 (char *)req->outbuf,
852 IS_CONN_ENCRYPTED(conn)))
853 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
855 TALLOC_FREE(req->outbuf);
857 pp += params_sent_thistime;
858 pd += data_sent_thistime;
860 params_to_send -= params_sent_thistime;
861 data_to_send -= data_sent_thistime;
863 /* Sanity check */
864 if(params_to_send < 0 || data_to_send < 0) {
865 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
866 params_to_send, data_to_send));
867 return;
871 return;
874 /****************************************************************************
875 Reply to a TRANSACT2_OPEN.
876 ****************************************************************************/
878 static void call_trans2open(connection_struct *conn,
879 struct smb_request *req,
880 char **pparams, int total_params,
881 char **ppdata, int total_data,
882 unsigned int max_data_bytes)
884 char *params = *pparams;
885 char *pdata = *ppdata;
886 int deny_mode;
887 int32 open_attr;
888 bool oplock_request;
889 #if 0
890 bool return_additional_info;
891 int16 open_sattr;
892 time_t open_time;
893 #endif
894 int open_ofun;
895 uint32 open_size;
896 char *pname;
897 char *fname = NULL;
898 SMB_OFF_T size=0;
899 int fattr=0,mtime=0;
900 SMB_INO_T inode = 0;
901 SMB_STRUCT_STAT sbuf;
902 int smb_action = 0;
903 files_struct *fsp;
904 struct ea_list *ea_list = NULL;
905 uint16 flags = 0;
906 NTSTATUS status;
907 uint32 access_mask;
908 uint32 share_mode;
909 uint32 create_disposition;
910 uint32 create_options = 0;
911 TALLOC_CTX *ctx = talloc_tos();
914 * Ensure we have enough parameters to perform the operation.
917 if (total_params < 29) {
918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
919 return;
922 flags = SVAL(params, 0);
923 deny_mode = SVAL(params, 2);
924 open_attr = SVAL(params,6);
925 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
926 if (oplock_request) {
927 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
930 #if 0
931 return_additional_info = BITSETW(params,0);
932 open_sattr = SVAL(params, 4);
933 open_time = make_unix_date3(params+8);
934 #endif
935 open_ofun = SVAL(params,12);
936 open_size = IVAL(params,14);
937 pname = &params[28];
939 if (IS_IPC(conn)) {
940 reply_doserror(req, ERRSRV, ERRaccess);
941 return;
944 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
945 total_params - 28, STR_TERMINATE,
946 &status);
947 if (!NT_STATUS_IS_OK(status)) {
948 reply_nterror(req, status);
949 return;
952 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
953 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
954 (unsigned int)open_ofun, open_size));
956 if (open_ofun == 0) {
957 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
958 return;
961 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
962 &access_mask,
963 &share_mode,
964 &create_disposition,
965 &create_options)) {
966 reply_doserror(req, ERRDOS, ERRbadaccess);
967 return;
970 /* Any data in this call is an EA list. */
971 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
972 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
973 return;
976 if (total_data != 4) {
977 if (total_data < 10) {
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 return;
982 if (IVAL(pdata,0) > total_data) {
983 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
984 IVAL(pdata,0), (unsigned int)total_data));
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
986 return;
989 ea_list = read_ea_list(talloc_tos(), pdata + 4,
990 total_data - 4);
991 if (!ea_list) {
992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 return;
995 } else if (IVAL(pdata,0) != 4) {
996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
997 return;
1000 status = create_file(conn, /* conn */
1001 req, /* req */
1002 0, /* root_dir_fid */
1003 fname, /* fname */
1004 access_mask, /* access_mask */
1005 share_mode, /* share_access */
1006 create_disposition, /* create_disposition*/
1007 create_options, /* create_options */
1008 open_attr, /* file_attributes */
1009 oplock_request, /* oplock_request */
1010 open_size, /* allocation_size */
1011 NULL, /* sd */
1012 ea_list, /* ea_list */
1013 &fsp, /* result */
1014 &smb_action, /* pinfo */
1015 &sbuf); /* psbuf */
1017 if (!NT_STATUS_IS_OK(status)) {
1018 if (open_was_deferred(req->mid)) {
1019 /* We have re-scheduled this call. */
1020 return;
1022 reply_openerror(req, status);
1023 return;
1026 size = get_file_size(sbuf);
1027 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1028 mtime = sbuf.st_mtime;
1029 inode = sbuf.st_ino;
1030 if (fattr & aDIR) {
1031 close_file(fsp,ERROR_CLOSE);
1032 reply_doserror(req, ERRDOS,ERRnoaccess);
1033 return;
1036 /* Realloc the size of parameters and data we will return */
1037 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1038 if(*pparams == NULL ) {
1039 reply_nterror(req, NT_STATUS_NO_MEMORY);
1040 return;
1042 params = *pparams;
1044 SSVAL(params,0,fsp->fnum);
1045 SSVAL(params,2,fattr);
1046 srv_put_dos_date2(params,4, mtime);
1047 SIVAL(params,8, (uint32)size);
1048 SSVAL(params,12,deny_mode);
1049 SSVAL(params,14,0); /* open_type - file or directory. */
1050 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1052 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1053 smb_action |= EXTENDED_OPLOCK_GRANTED;
1056 SSVAL(params,18,smb_action);
1059 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1061 SIVAL(params,20,inode);
1062 SSVAL(params,24,0); /* Padding. */
1063 if (flags & 8) {
1064 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1065 SIVAL(params, 26, ea_size);
1066 } else {
1067 SIVAL(params, 26, 0);
1070 /* Send the required number of replies */
1071 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1074 /*********************************************************
1075 Routine to check if a given string matches exactly.
1076 as a special case a mask of "." does NOT match. That
1077 is required for correct wildcard semantics
1078 Case can be significant or not.
1079 **********************************************************/
1081 static bool exact_match(connection_struct *conn,
1082 const char *str,
1083 const char *mask)
1085 if (mask[0] == '.' && mask[1] == 0)
1086 return False;
1087 if (conn->case_sensitive)
1088 return strcmp(str,mask)==0;
1089 if (StrCaseCmp(str,mask) != 0) {
1090 return False;
1092 if (dptr_has_wild(conn->dirptr)) {
1093 return False;
1095 return True;
1098 /****************************************************************************
1099 Return the filetype for UNIX extensions.
1100 ****************************************************************************/
1102 static uint32 unix_filetype(mode_t mode)
1104 if(S_ISREG(mode))
1105 return UNIX_TYPE_FILE;
1106 else if(S_ISDIR(mode))
1107 return UNIX_TYPE_DIR;
1108 #ifdef S_ISLNK
1109 else if(S_ISLNK(mode))
1110 return UNIX_TYPE_SYMLINK;
1111 #endif
1112 #ifdef S_ISCHR
1113 else if(S_ISCHR(mode))
1114 return UNIX_TYPE_CHARDEV;
1115 #endif
1116 #ifdef S_ISBLK
1117 else if(S_ISBLK(mode))
1118 return UNIX_TYPE_BLKDEV;
1119 #endif
1120 #ifdef S_ISFIFO
1121 else if(S_ISFIFO(mode))
1122 return UNIX_TYPE_FIFO;
1123 #endif
1124 #ifdef S_ISSOCK
1125 else if(S_ISSOCK(mode))
1126 return UNIX_TYPE_SOCKET;
1127 #endif
1129 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1130 return UNIX_TYPE_UNKNOWN;
1133 /****************************************************************************
1134 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1135 ****************************************************************************/
1137 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1139 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1140 SMB_STRUCT_STAT *psbuf,
1141 uint32 perms,
1142 enum perm_type ptype,
1143 mode_t *ret_perms)
1145 mode_t ret = 0;
1147 if (perms == SMB_MODE_NO_CHANGE) {
1148 if (!VALID_STAT(*psbuf)) {
1149 return NT_STATUS_INVALID_PARAMETER;
1150 } else {
1151 *ret_perms = psbuf->st_mode;
1152 return NT_STATUS_OK;
1156 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1157 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1158 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1159 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1160 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1161 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1162 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1163 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1164 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1165 #ifdef S_ISVTX
1166 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1167 #endif
1168 #ifdef S_ISGID
1169 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1170 #endif
1171 #ifdef S_ISUID
1172 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1173 #endif
1175 switch (ptype) {
1176 case PERM_NEW_FILE:
1177 /* Apply mode mask */
1178 ret &= lp_create_mask(SNUM(conn));
1179 /* Add in force bits */
1180 ret |= lp_force_create_mode(SNUM(conn));
1181 break;
1182 case PERM_NEW_DIR:
1183 ret &= lp_dir_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_dir_mode(SNUM(conn));
1186 break;
1187 case PERM_EXISTING_FILE:
1188 /* Apply mode mask */
1189 ret &= lp_security_mask(SNUM(conn));
1190 /* Add in force bits */
1191 ret |= lp_force_security_mode(SNUM(conn));
1192 break;
1193 case PERM_EXISTING_DIR:
1194 /* Apply mode mask */
1195 ret &= lp_dir_security_mask(SNUM(conn));
1196 /* Add in force bits */
1197 ret |= lp_force_dir_security_mode(SNUM(conn));
1198 break;
1201 *ret_perms = ret;
1202 return NT_STATUS_OK;
1205 /****************************************************************************
1206 Needed to show the msdfs symlinks as directories. Modifies psbuf
1207 to be a directory if it's a msdfs link.
1208 ****************************************************************************/
1210 static bool check_msdfs_link(connection_struct *conn,
1211 const char *pathname,
1212 SMB_STRUCT_STAT *psbuf)
1214 int saved_errno = errno;
1215 if(lp_host_msdfs() &&
1216 lp_msdfs_root(SNUM(conn)) &&
1217 is_msdfs_link(conn, pathname, psbuf)) {
1219 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1220 "as a directory\n",
1221 pathname));
1222 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1223 errno = saved_errno;
1224 return true;
1226 errno = saved_errno;
1227 return false;
1231 /****************************************************************************
1232 Get a level dependent lanman2 dir entry.
1233 ****************************************************************************/
1235 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1236 connection_struct *conn,
1237 uint16 flags2,
1238 const char *path_mask,
1239 uint32 dirtype,
1240 int info_level,
1241 int requires_resume_key,
1242 bool dont_descend,
1243 bool ask_sharemode,
1244 char **ppdata,
1245 char *base_data,
1246 char *end_data,
1247 int space_remaining,
1248 bool *out_of_space,
1249 bool *got_exact_match,
1250 int *last_entry_off,
1251 struct ea_list *name_list)
1253 const char *dname;
1254 bool found = False;
1255 SMB_STRUCT_STAT sbuf;
1256 const char *mask = NULL;
1257 char *pathreal = NULL;
1258 const char *fname = NULL;
1259 char *p, *q, *pdata = *ppdata;
1260 uint32 reskey=0;
1261 long prev_dirpos=0;
1262 uint32 mode=0;
1263 SMB_OFF_T file_size = 0;
1264 SMB_BIG_UINT allocation_size = 0;
1265 uint32 len;
1266 struct timespec mdate_ts, adate_ts, create_date_ts;
1267 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1268 char *nameptr;
1269 char *last_entry_ptr;
1270 bool was_8_3;
1271 uint32 nt_extmode; /* Used for NT connections instead of mode */
1272 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1273 bool check_mangled_names = lp_manglednames(conn->params);
1274 char mangled_name[13]; /* mangled 8.3 name. */
1276 *out_of_space = False;
1277 *got_exact_match = False;
1279 ZERO_STRUCT(mdate_ts);
1280 ZERO_STRUCT(adate_ts);
1281 ZERO_STRUCT(create_date_ts);
1283 if (!conn->dirptr) {
1284 return(False);
1287 p = strrchr_m(path_mask,'/');
1288 if(p != NULL) {
1289 if(p[1] == '\0') {
1290 mask = talloc_strdup(ctx,"*.*");
1291 } else {
1292 mask = p+1;
1294 } else {
1295 mask = path_mask;
1298 while (!found) {
1299 bool got_match;
1300 bool ms_dfs_link = False;
1302 /* Needed if we run out of space */
1303 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1304 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1307 * Due to bugs in NT client redirectors we are not using
1308 * resume keys any more - set them to zero.
1309 * Check out the related comments in findfirst/findnext.
1310 * JRA.
1313 reskey = 0;
1315 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1316 (long)conn->dirptr,curr_dirpos));
1318 if (!dname) {
1319 return(False);
1323 * fname may get mangled, dname is never mangled.
1324 * Whenever we're accessing the filesystem we use
1325 * pathreal which is composed from dname.
1328 pathreal = NULL;
1329 fname = dname;
1331 /* Mangle fname if it's an illegal name. */
1332 if (mangle_must_mangle(dname,conn->params)) {
1333 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1334 continue; /* Error - couldn't mangle. */
1336 fname = mangled_name;
1339 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1340 got_match = mask_match(fname, mask, conn->case_sensitive);
1343 if(!got_match && check_mangled_names &&
1344 !mangle_is_8_3(fname, False, conn->params)) {
1346 * It turns out that NT matches wildcards against
1347 * both long *and* short names. This may explain some
1348 * of the wildcard wierdness from old DOS clients
1349 * that some people have been seeing.... JRA.
1351 /* Force the mangling into 8.3. */
1352 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1353 continue; /* Error - couldn't mangle. */
1356 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1357 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1361 if (got_match) {
1362 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1364 if (dont_descend && !isdots) {
1365 continue;
1368 if (needslash) {
1369 pathreal = NULL;
1370 pathreal = talloc_asprintf(ctx,
1371 "%s/%s",
1372 conn->dirpath,
1373 dname);
1374 } else {
1375 pathreal = talloc_asprintf(ctx,
1376 "%s%s",
1377 conn->dirpath,
1378 dname);
1381 if (!pathreal) {
1382 return False;
1385 if (INFO_LEVEL_IS_UNIX(info_level)) {
1386 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1387 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1388 pathreal,strerror(errno)));
1389 TALLOC_FREE(pathreal);
1390 continue;
1392 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1393 /* Needed to show the msdfs symlinks as
1394 * directories */
1396 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1397 if (!ms_dfs_link) {
1398 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1399 pathreal,strerror(errno)));
1400 TALLOC_FREE(pathreal);
1401 continue;
1405 if (ms_dfs_link) {
1406 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1407 } else {
1408 mode = dos_mode(conn,pathreal,&sbuf);
1411 if (!dir_check_ftype(conn,mode,dirtype)) {
1412 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1413 TALLOC_FREE(pathreal);
1414 continue;
1417 if (!(mode & aDIR)) {
1418 file_size = get_file_size(sbuf);
1420 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1422 mdate_ts = get_mtimespec(&sbuf);
1423 adate_ts = get_atimespec(&sbuf);
1424 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1426 if (ask_sharemode) {
1427 struct timespec write_time_ts;
1428 struct file_id fileid;
1430 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1431 get_file_infos(fileid, NULL, &write_time_ts);
1432 if (!null_timespec(write_time_ts)) {
1433 mdate_ts = write_time_ts;
1437 if (lp_dos_filetime_resolution(SNUM(conn))) {
1438 dos_filetime_timespec(&create_date_ts);
1439 dos_filetime_timespec(&mdate_ts);
1440 dos_filetime_timespec(&adate_ts);
1443 create_date = convert_timespec_to_time_t(create_date_ts);
1444 mdate = convert_timespec_to_time_t(mdate_ts);
1445 adate = convert_timespec_to_time_t(adate_ts);
1447 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1449 found = True;
1451 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1455 p = pdata;
1456 last_entry_ptr = p;
1458 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1460 switch (info_level) {
1461 case SMB_FIND_INFO_STANDARD:
1462 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1463 if(requires_resume_key) {
1464 SIVAL(p,0,reskey);
1465 p += 4;
1467 srv_put_dos_date2(p,0,create_date);
1468 srv_put_dos_date2(p,4,adate);
1469 srv_put_dos_date2(p,8,mdate);
1470 SIVAL(p,12,(uint32)file_size);
1471 SIVAL(p,16,(uint32)allocation_size);
1472 SSVAL(p,20,mode);
1473 p += 23;
1474 nameptr = p;
1475 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1476 p += ucs2_align(base_data, p, 0);
1478 len = srvstr_push(base_data, flags2, p,
1479 fname, PTR_DIFF(end_data, p),
1480 STR_TERMINATE);
1481 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1482 if (len > 2) {
1483 SCVAL(nameptr, -1, len - 2);
1484 } else {
1485 SCVAL(nameptr, -1, 0);
1487 } else {
1488 if (len > 1) {
1489 SCVAL(nameptr, -1, len - 1);
1490 } else {
1491 SCVAL(nameptr, -1, 0);
1494 p += len;
1495 break;
1497 case SMB_FIND_EA_SIZE:
1498 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1499 if(requires_resume_key) {
1500 SIVAL(p,0,reskey);
1501 p += 4;
1503 srv_put_dos_date2(p,0,create_date);
1504 srv_put_dos_date2(p,4,adate);
1505 srv_put_dos_date2(p,8,mdate);
1506 SIVAL(p,12,(uint32)file_size);
1507 SIVAL(p,16,(uint32)allocation_size);
1508 SSVAL(p,20,mode);
1510 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1511 SIVAL(p,22,ea_size); /* Extended attributes */
1513 p += 27;
1514 nameptr = p - 1;
1515 len = srvstr_push(base_data, flags2,
1516 p, fname, PTR_DIFF(end_data, p),
1517 STR_TERMINATE | STR_NOALIGN);
1518 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1519 if (len > 2) {
1520 len -= 2;
1521 } else {
1522 len = 0;
1524 } else {
1525 if (len > 1) {
1526 len -= 1;
1527 } else {
1528 len = 0;
1531 SCVAL(nameptr,0,len);
1532 p += len;
1533 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1534 break;
1536 case SMB_FIND_EA_LIST:
1538 struct ea_list *file_list = NULL;
1539 size_t ea_len = 0;
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1542 if (!name_list) {
1543 return False;
1545 if(requires_resume_key) {
1546 SIVAL(p,0,reskey);
1547 p += 4;
1549 srv_put_dos_date2(p,0,create_date);
1550 srv_put_dos_date2(p,4,adate);
1551 srv_put_dos_date2(p,8,mdate);
1552 SIVAL(p,12,(uint32)file_size);
1553 SIVAL(p,16,(uint32)allocation_size);
1554 SSVAL(p,20,mode);
1555 p += 22; /* p now points to the EA area. */
1557 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1558 name_list = ea_list_union(name_list, file_list, &ea_len);
1560 /* We need to determine if this entry will fit in the space available. */
1561 /* Max string size is 255 bytes. */
1562 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1563 /* Move the dirptr back to prev_dirpos */
1564 dptr_SeekDir(conn->dirptr, prev_dirpos);
1565 *out_of_space = True;
1566 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1567 return False; /* Not finished - just out of space */
1570 /* Push the ea_data followed by the name. */
1571 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1572 nameptr = p;
1573 len = srvstr_push(base_data, flags2,
1574 p + 1, fname, PTR_DIFF(end_data, p+1),
1575 STR_TERMINATE | STR_NOALIGN);
1576 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1577 if (len > 2) {
1578 len -= 2;
1579 } else {
1580 len = 0;
1582 } else {
1583 if (len > 1) {
1584 len -= 1;
1585 } else {
1586 len = 0;
1589 SCVAL(nameptr,0,len);
1590 p += len + 1;
1591 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1592 break;
1595 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1596 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1597 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1598 p += 4;
1599 SIVAL(p,0,reskey); p += 4;
1600 put_long_date_timespec(p,create_date_ts); p += 8;
1601 put_long_date_timespec(p,adate_ts); p += 8;
1602 put_long_date_timespec(p,mdate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 SOFF_T(p,0,file_size); p += 8;
1605 SOFF_T(p,0,allocation_size); p += 8;
1606 SIVAL(p,0,nt_extmode); p += 4;
1607 q = p; p += 4; /* q is placeholder for name length. */
1609 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1610 SIVAL(p,0,ea_size); /* Extended attributes */
1611 p += 4;
1613 /* Clear the short name buffer. This is
1614 * IMPORTANT as not doing so will trigger
1615 * a Win2k client bug. JRA.
1617 if (!was_8_3 && check_mangled_names) {
1618 if (!name_to_8_3(fname,mangled_name,True,
1619 conn->params)) {
1620 /* Error - mangle failed ! */
1621 memset(mangled_name,'\0',12);
1623 mangled_name[12] = 0;
1624 len = srvstr_push(base_data, flags2,
1625 p+2, mangled_name, 24,
1626 STR_UPPER|STR_UNICODE);
1627 if (len < 24) {
1628 memset(p + 2 + len,'\0',24 - len);
1630 SSVAL(p, 0, len);
1631 } else {
1632 memset(p,'\0',26);
1634 p += 2 + 24;
1635 len = srvstr_push(base_data, flags2, p,
1636 fname, PTR_DIFF(end_data, p),
1637 STR_TERMINATE_ASCII);
1638 SIVAL(q,0,len);
1639 p += len;
1640 SIVAL(p,0,0); /* Ensure any padding is null. */
1641 len = PTR_DIFF(p, pdata);
1642 len = (len + 3) & ~3;
1643 SIVAL(pdata,0,len);
1644 p = pdata + len;
1645 break;
1647 case SMB_FIND_FILE_DIRECTORY_INFO:
1648 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1649 p += 4;
1650 SIVAL(p,0,reskey); p += 4;
1651 put_long_date_timespec(p,create_date_ts); p += 8;
1652 put_long_date_timespec(p,adate_ts); p += 8;
1653 put_long_date_timespec(p,mdate_ts); p += 8;
1654 put_long_date_timespec(p,mdate_ts); p += 8;
1655 SOFF_T(p,0,file_size); p += 8;
1656 SOFF_T(p,0,allocation_size); p += 8;
1657 SIVAL(p,0,nt_extmode); p += 4;
1658 len = srvstr_push(base_data, flags2,
1659 p + 4, fname, PTR_DIFF(end_data, p+4),
1660 STR_TERMINATE_ASCII);
1661 SIVAL(p,0,len);
1662 p += 4 + len;
1663 SIVAL(p,0,0); /* Ensure any padding is null. */
1664 len = PTR_DIFF(p, pdata);
1665 len = (len + 3) & ~3;
1666 SIVAL(pdata,0,len);
1667 p = pdata + len;
1668 break;
1670 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1671 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1672 p += 4;
1673 SIVAL(p,0,reskey); p += 4;
1674 put_long_date_timespec(p,create_date_ts); p += 8;
1675 put_long_date_timespec(p,adate_ts); p += 8;
1676 put_long_date_timespec(p,mdate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 SOFF_T(p,0,file_size); p += 8;
1679 SOFF_T(p,0,allocation_size); p += 8;
1680 SIVAL(p,0,nt_extmode); p += 4;
1681 q = p; p += 4; /* q is placeholder for name length. */
1683 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1684 SIVAL(p,0,ea_size); /* Extended attributes */
1685 p +=4;
1687 len = srvstr_push(base_data, flags2, p,
1688 fname, PTR_DIFF(end_data, p),
1689 STR_TERMINATE_ASCII);
1690 SIVAL(q, 0, len);
1691 p += len;
1693 SIVAL(p,0,0); /* Ensure any padding is null. */
1694 len = PTR_DIFF(p, pdata);
1695 len = (len + 3) & ~3;
1696 SIVAL(pdata,0,len);
1697 p = pdata + len;
1698 break;
1700 case SMB_FIND_FILE_NAMES_INFO:
1701 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1702 p += 4;
1703 SIVAL(p,0,reskey); p += 4;
1704 p += 4;
1705 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1706 acl on a dir (tridge) */
1707 len = srvstr_push(base_data, flags2, p,
1708 fname, PTR_DIFF(end_data, p),
1709 STR_TERMINATE_ASCII);
1710 SIVAL(p, -4, len);
1711 p += len;
1712 SIVAL(p,0,0); /* Ensure any padding is null. */
1713 len = PTR_DIFF(p, pdata);
1714 len = (len + 3) & ~3;
1715 SIVAL(pdata,0,len);
1716 p = pdata + len;
1717 break;
1719 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1720 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1721 p += 4;
1722 SIVAL(p,0,reskey); p += 4;
1723 put_long_date_timespec(p,create_date_ts); p += 8;
1724 put_long_date_timespec(p,adate_ts); p += 8;
1725 put_long_date_timespec(p,mdate_ts); p += 8;
1726 put_long_date_timespec(p,mdate_ts); p += 8;
1727 SOFF_T(p,0,file_size); p += 8;
1728 SOFF_T(p,0,allocation_size); p += 8;
1729 SIVAL(p,0,nt_extmode); p += 4;
1730 q = p; p += 4; /* q is placeholder for name length. */
1732 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1733 SIVAL(p,0,ea_size); /* Extended attributes */
1734 p +=4;
1736 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1737 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1738 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1739 len = srvstr_push(base_data, flags2, p,
1740 fname, PTR_DIFF(end_data, p),
1741 STR_TERMINATE_ASCII);
1742 SIVAL(q, 0, len);
1743 p += len;
1744 SIVAL(p,0,0); /* Ensure any padding is null. */
1745 len = PTR_DIFF(p, pdata);
1746 len = (len + 3) & ~3;
1747 SIVAL(pdata,0,len);
1748 p = pdata + len;
1749 break;
1751 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1752 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1753 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1754 p += 4;
1755 SIVAL(p,0,reskey); p += 4;
1756 put_long_date_timespec(p,create_date_ts); p += 8;
1757 put_long_date_timespec(p,adate_ts); p += 8;
1758 put_long_date_timespec(p,mdate_ts); p += 8;
1759 put_long_date_timespec(p,mdate_ts); p += 8;
1760 SOFF_T(p,0,file_size); p += 8;
1761 SOFF_T(p,0,allocation_size); p += 8;
1762 SIVAL(p,0,nt_extmode); p += 4;
1763 q = p; p += 4; /* q is placeholder for name length */
1765 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1766 SIVAL(p,0,ea_size); /* Extended attributes */
1767 p +=4;
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3 && check_mangled_names) {
1774 if (!name_to_8_3(fname,mangled_name,True,
1775 conn->params)) {
1776 /* Error - mangle failed ! */
1777 memset(mangled_name,'\0',12);
1779 mangled_name[12] = 0;
1780 len = srvstr_push(base_data, flags2,
1781 p+2, mangled_name, 24,
1782 STR_UPPER|STR_UNICODE);
1783 SSVAL(p, 0, len);
1784 if (len < 24) {
1785 memset(p + 2 + len,'\0',24 - len);
1787 SSVAL(p, 0, len);
1788 } else {
1789 memset(p,'\0',26);
1791 p += 26;
1792 SSVAL(p,0,0); p += 2; /* Reserved ? */
1793 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1794 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1795 len = srvstr_push(base_data, flags2, p,
1796 fname, PTR_DIFF(end_data, p),
1797 STR_TERMINATE_ASCII);
1798 SIVAL(q,0,len);
1799 p += len;
1800 SIVAL(p,0,0); /* Ensure any padding is null. */
1801 len = PTR_DIFF(p, pdata);
1802 len = (len + 3) & ~3;
1803 SIVAL(pdata,0,len);
1804 p = pdata + len;
1805 break;
1807 /* CIFS UNIX Extension. */
1809 case SMB_FIND_FILE_UNIX:
1810 case SMB_FIND_FILE_UNIX_INFO2:
1811 p+= 4;
1812 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1814 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1816 if (info_level == SMB_FIND_FILE_UNIX) {
1817 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1818 p = store_file_unix_basic(conn, p,
1819 NULL, &sbuf);
1820 len = srvstr_push(base_data, flags2, p,
1821 fname, PTR_DIFF(end_data, p),
1822 STR_TERMINATE);
1823 } else {
1824 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1825 p = store_file_unix_basic_info2(conn, p,
1826 NULL, &sbuf);
1827 nameptr = p;
1828 p += 4;
1829 len = srvstr_push(base_data, flags2, p, fname,
1830 PTR_DIFF(end_data, p), 0);
1831 SIVAL(nameptr, 0, len);
1834 p += len;
1835 SIVAL(p,0,0); /* Ensure any padding is null. */
1837 len = PTR_DIFF(p, pdata);
1838 len = (len + 3) & ~3;
1839 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1840 p = pdata + len;
1841 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1843 break;
1845 default:
1846 return(False);
1850 if (PTR_DIFF(p,pdata) > space_remaining) {
1851 /* Move the dirptr back to prev_dirpos */
1852 dptr_SeekDir(conn->dirptr, prev_dirpos);
1853 *out_of_space = True;
1854 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1855 return False; /* Not finished - just out of space */
1858 /* Setup the last entry pointer, as an offset from base_data */
1859 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1860 /* Advance the data pointer to the next slot */
1861 *ppdata = p;
1863 return(found);
1866 /****************************************************************************
1867 Reply to a TRANS2_FINDFIRST.
1868 ****************************************************************************/
1870 static void call_trans2findfirst(connection_struct *conn,
1871 struct smb_request *req,
1872 char **pparams, int total_params,
1873 char **ppdata, int total_data,
1874 unsigned int max_data_bytes)
1876 /* We must be careful here that we don't return more than the
1877 allowed number of data bytes. If this means returning fewer than
1878 maxentries then so be it. We assume that the redirector has
1879 enough room for the fixed number of parameter bytes it has
1880 requested. */
1881 char *params = *pparams;
1882 char *pdata = *ppdata;
1883 char *data_end;
1884 uint32 dirtype;
1885 int maxentries;
1886 uint16 findfirst_flags;
1887 bool close_after_first;
1888 bool close_if_end;
1889 bool requires_resume_key;
1890 int info_level;
1891 char *directory = NULL;
1892 const char *mask = NULL;
1893 char *p;
1894 int last_entry_off=0;
1895 int dptr_num = -1;
1896 int numentries = 0;
1897 int i;
1898 bool finished = False;
1899 bool dont_descend = False;
1900 bool out_of_space = False;
1901 int space_remaining;
1902 bool mask_contains_wcard = False;
1903 SMB_STRUCT_STAT sbuf;
1904 struct ea_list *ea_list = NULL;
1905 NTSTATUS ntstatus = NT_STATUS_OK;
1906 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1907 TALLOC_CTX *ctx = talloc_tos();
1909 if (total_params < 13) {
1910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1911 return;
1914 dirtype = SVAL(params,0);
1915 maxentries = SVAL(params,2);
1916 findfirst_flags = SVAL(params,4);
1917 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1918 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1919 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1920 info_level = SVAL(params,6);
1922 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1923 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1924 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1925 info_level, max_data_bytes));
1927 if (!maxentries) {
1928 /* W2K3 seems to treat zero as 1. */
1929 maxentries = 1;
1932 switch (info_level) {
1933 case SMB_FIND_INFO_STANDARD:
1934 case SMB_FIND_EA_SIZE:
1935 case SMB_FIND_EA_LIST:
1936 case SMB_FIND_FILE_DIRECTORY_INFO:
1937 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1938 case SMB_FIND_FILE_NAMES_INFO:
1939 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1940 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1941 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1942 break;
1943 case SMB_FIND_FILE_UNIX:
1944 case SMB_FIND_FILE_UNIX_INFO2:
1945 if (!lp_unix_extensions()) {
1946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1947 return;
1949 break;
1950 default:
1951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1952 return;
1955 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1956 params+12, total_params - 12,
1957 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1958 if (!NT_STATUS_IS_OK(ntstatus)) {
1959 reply_nterror(req, ntstatus);
1960 return;
1963 ntstatus = resolve_dfspath_wcard(ctx, conn,
1964 req->flags2 & FLAGS2_DFS_PATHNAMES,
1965 directory,
1966 &directory,
1967 &mask_contains_wcard);
1968 if (!NT_STATUS_IS_OK(ntstatus)) {
1969 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1970 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1971 ERRSRV, ERRbadpath);
1972 return;
1974 reply_nterror(req, ntstatus);
1975 return;
1978 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1979 if (!NT_STATUS_IS_OK(ntstatus)) {
1980 reply_nterror(req, ntstatus);
1981 return;
1984 ntstatus = check_name(conn, directory);
1985 if (!NT_STATUS_IS_OK(ntstatus)) {
1986 reply_nterror(req, ntstatus);
1987 return;
1990 p = strrchr_m(directory,'/');
1991 if(p == NULL) {
1992 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1993 if((directory[0] == '.') && (directory[1] == '\0')) {
1994 mask = "*";
1995 mask_contains_wcard = True;
1996 } else {
1997 mask = directory;
1999 directory = talloc_strdup(talloc_tos(), "./");
2000 if (!directory) {
2001 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 return;
2004 } else {
2005 mask = p+1;
2006 *p = 0;
2009 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2011 if (info_level == SMB_FIND_EA_LIST) {
2012 uint32 ea_size;
2014 if (total_data < 4) {
2015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2016 return;
2019 ea_size = IVAL(pdata,0);
2020 if (ea_size != total_data) {
2021 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2022 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2024 return;
2027 if (!lp_ea_support(SNUM(conn))) {
2028 reply_doserror(req, ERRDOS, ERReasnotsupported);
2029 return;
2032 /* Pull out the list of names. */
2033 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2034 if (!ea_list) {
2035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2036 return;
2040 *ppdata = (char *)SMB_REALLOC(
2041 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2042 if(*ppdata == NULL ) {
2043 reply_nterror(req, NT_STATUS_NO_MEMORY);
2044 return;
2046 pdata = *ppdata;
2047 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2049 /* Realloc the params space */
2050 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2051 if (*pparams == NULL) {
2052 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053 return;
2055 params = *pparams;
2057 /* Save the wildcard match and attribs we are using on this directory -
2058 needed as lanman2 assumes these are being saved between calls */
2060 ntstatus = dptr_create(conn,
2061 directory,
2062 False,
2063 True,
2064 req->smbpid,
2065 mask,
2066 mask_contains_wcard,
2067 dirtype,
2068 &conn->dirptr);
2070 if (!NT_STATUS_IS_OK(ntstatus)) {
2071 reply_nterror(req, ntstatus);
2072 return;
2075 dptr_num = dptr_dnum(conn->dirptr);
2076 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2078 /* We don't need to check for VOL here as this is returned by
2079 a different TRANS2 call. */
2081 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2082 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2083 dont_descend = True;
2085 p = pdata;
2086 space_remaining = max_data_bytes;
2087 out_of_space = False;
2089 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2090 bool got_exact_match = False;
2092 /* this is a heuristic to avoid seeking the dirptr except when
2093 absolutely necessary. It allows for a filename of about 40 chars */
2094 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2095 out_of_space = True;
2096 finished = False;
2097 } else {
2098 finished = !get_lanman2_dir_entry(ctx,
2099 conn,
2100 req->flags2,
2101 mask,dirtype,info_level,
2102 requires_resume_key,dont_descend,
2103 ask_sharemode,
2104 &p,pdata,data_end,
2105 space_remaining, &out_of_space,
2106 &got_exact_match,
2107 &last_entry_off, ea_list);
2110 if (finished && out_of_space)
2111 finished = False;
2113 if (!finished && !out_of_space)
2114 numentries++;
2117 * As an optimisation if we know we aren't looking
2118 * for a wildcard name (ie. the name matches the wildcard exactly)
2119 * then we can finish on any (first) match.
2120 * This speeds up large directory searches. JRA.
2123 if(got_exact_match)
2124 finished = True;
2126 /* Ensure space_remaining never goes -ve. */
2127 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2128 space_remaining = 0;
2129 out_of_space = true;
2130 } else {
2131 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2135 /* Check if we can close the dirptr */
2136 if(close_after_first || (finished && close_if_end)) {
2137 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2138 dptr_close(&dptr_num);
2142 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2143 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2144 * the protocol level is less than NT1. Tested with smbclient. JRA.
2145 * This should fix the OS/2 client bug #2335.
2148 if(numentries == 0) {
2149 dptr_close(&dptr_num);
2150 if (Protocol < PROTOCOL_NT1) {
2151 reply_doserror(req, ERRDOS, ERRnofiles);
2152 return;
2153 } else {
2154 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2155 ERRDOS, ERRbadfile);
2156 return;
2160 /* At this point pdata points to numentries directory entries. */
2162 /* Set up the return parameter block */
2163 SSVAL(params,0,dptr_num);
2164 SSVAL(params,2,numentries);
2165 SSVAL(params,4,finished);
2166 SSVAL(params,6,0); /* Never an EA error */
2167 SSVAL(params,8,last_entry_off);
2169 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2170 max_data_bytes);
2172 if ((! *directory) && dptr_path(dptr_num)) {
2173 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2174 if (!directory) {
2175 reply_nterror(req, NT_STATUS_NO_MEMORY);
2179 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2180 smb_fn_name(CVAL(req->inbuf,smb_com)),
2181 mask, directory, dirtype, numentries ) );
2184 * Force a name mangle here to ensure that the
2185 * mask as an 8.3 name is top of the mangled cache.
2186 * The reasons for this are subtle. Don't remove
2187 * this code unless you know what you are doing
2188 * (see PR#13758). JRA.
2191 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2192 char mangled_name[13];
2193 name_to_8_3(mask, mangled_name, True, conn->params);
2196 return;
2199 /****************************************************************************
2200 Reply to a TRANS2_FINDNEXT.
2201 ****************************************************************************/
2203 static void call_trans2findnext(connection_struct *conn,
2204 struct smb_request *req,
2205 char **pparams, int total_params,
2206 char **ppdata, int total_data,
2207 unsigned int max_data_bytes)
2209 /* We must be careful here that we don't return more than the
2210 allowed number of data bytes. If this means returning fewer than
2211 maxentries then so be it. We assume that the redirector has
2212 enough room for the fixed number of parameter bytes it has
2213 requested. */
2214 char *params = *pparams;
2215 char *pdata = *ppdata;
2216 char *data_end;
2217 int dptr_num;
2218 int maxentries;
2219 uint16 info_level;
2220 uint32 resume_key;
2221 uint16 findnext_flags;
2222 bool close_after_request;
2223 bool close_if_end;
2224 bool requires_resume_key;
2225 bool continue_bit;
2226 bool mask_contains_wcard = False;
2227 char *resume_name = NULL;
2228 const char *mask = NULL;
2229 const char *directory = NULL;
2230 char *p = NULL;
2231 uint16 dirtype;
2232 int numentries = 0;
2233 int i, last_entry_off=0;
2234 bool finished = False;
2235 bool dont_descend = False;
2236 bool out_of_space = False;
2237 int space_remaining;
2238 struct ea_list *ea_list = NULL;
2239 NTSTATUS ntstatus = NT_STATUS_OK;
2240 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2241 TALLOC_CTX *ctx = talloc_tos();
2243 if (total_params < 13) {
2244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2245 return;
2248 dptr_num = SVAL(params,0);
2249 maxentries = SVAL(params,2);
2250 info_level = SVAL(params,4);
2251 resume_key = IVAL(params,6);
2252 findnext_flags = SVAL(params,10);
2253 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2254 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2255 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2256 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2258 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2259 params+12,
2260 total_params - 12, STR_TERMINATE, &ntstatus,
2261 &mask_contains_wcard);
2262 if (!NT_STATUS_IS_OK(ntstatus)) {
2263 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2264 complain (it thinks we're asking for the directory above the shared
2265 path or an invalid name). Catch this as the resume name is only compared, never used in
2266 a file access. JRA. */
2267 srvstr_pull_talloc(ctx, params, req->flags2,
2268 &resume_name, params+12,
2269 total_params - 12,
2270 STR_TERMINATE);
2272 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2273 reply_nterror(req, ntstatus);
2274 return;
2278 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2279 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2280 resume_key = %d resume name = %s continue=%d level = %d\n",
2281 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2282 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2284 if (!maxentries) {
2285 /* W2K3 seems to treat zero as 1. */
2286 maxentries = 1;
2289 switch (info_level) {
2290 case SMB_FIND_INFO_STANDARD:
2291 case SMB_FIND_EA_SIZE:
2292 case SMB_FIND_EA_LIST:
2293 case SMB_FIND_FILE_DIRECTORY_INFO:
2294 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2295 case SMB_FIND_FILE_NAMES_INFO:
2296 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2297 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2298 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2299 break;
2300 case SMB_FIND_FILE_UNIX:
2301 case SMB_FIND_FILE_UNIX_INFO2:
2302 if (!lp_unix_extensions()) {
2303 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2304 return;
2306 break;
2307 default:
2308 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2309 return;
2312 if (info_level == SMB_FIND_EA_LIST) {
2313 uint32 ea_size;
2315 if (total_data < 4) {
2316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2317 return;
2320 ea_size = IVAL(pdata,0);
2321 if (ea_size != total_data) {
2322 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2323 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 return;
2328 if (!lp_ea_support(SNUM(conn))) {
2329 reply_doserror(req, ERRDOS, ERReasnotsupported);
2330 return;
2333 /* Pull out the list of names. */
2334 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2335 if (!ea_list) {
2336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2337 return;
2341 *ppdata = (char *)SMB_REALLOC(
2342 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2343 if(*ppdata == NULL) {
2344 reply_nterror(req, NT_STATUS_NO_MEMORY);
2345 return;
2348 pdata = *ppdata;
2349 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2351 /* Realloc the params space */
2352 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2353 if(*pparams == NULL ) {
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2355 return;
2358 params = *pparams;
2360 /* Check that the dptr is valid */
2361 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2362 reply_doserror(req, ERRDOS, ERRnofiles);
2363 return;
2366 string_set(&conn->dirpath,dptr_path(dptr_num));
2368 /* Get the wildcard mask from the dptr */
2369 if((p = dptr_wcard(dptr_num))== NULL) {
2370 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2371 reply_doserror(req, ERRDOS, ERRnofiles);
2372 return;
2375 mask = p;
2376 directory = conn->dirpath;
2378 /* Get the attr mask from the dptr */
2379 dirtype = dptr_attr(dptr_num);
2381 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2382 dptr_num, mask, dirtype,
2383 (long)conn->dirptr,
2384 dptr_TellDir(conn->dirptr)));
2386 /* We don't need to check for VOL here as this is returned by
2387 a different TRANS2 call. */
2389 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2390 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2391 dont_descend = True;
2393 p = pdata;
2394 space_remaining = max_data_bytes;
2395 out_of_space = False;
2398 * Seek to the correct position. We no longer use the resume key but
2399 * depend on the last file name instead.
2402 if(*resume_name && !continue_bit) {
2403 SMB_STRUCT_STAT st;
2405 long current_pos = 0;
2407 * Remember, name_to_8_3 is called by
2408 * get_lanman2_dir_entry(), so the resume name
2409 * could be mangled. Ensure we check the unmangled name.
2412 if (mangle_is_mangled(resume_name, conn->params)) {
2413 char *new_resume_name = NULL;
2414 mangle_lookup_name_from_8_3(ctx,
2415 resume_name,
2416 &new_resume_name,
2417 conn->params);
2418 if (new_resume_name) {
2419 resume_name = new_resume_name;
2424 * Fix for NT redirector problem triggered by resume key indexes
2425 * changing between directory scans. We now return a resume key of 0
2426 * and instead look for the filename to continue from (also given
2427 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2428 * findfirst/findnext (as is usual) then the directory pointer
2429 * should already be at the correct place.
2432 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2433 } /* end if resume_name && !continue_bit */
2435 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2436 bool got_exact_match = False;
2438 /* this is a heuristic to avoid seeking the dirptr except when
2439 absolutely necessary. It allows for a filename of about 40 chars */
2440 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2441 out_of_space = True;
2442 finished = False;
2443 } else {
2444 finished = !get_lanman2_dir_entry(ctx,
2445 conn,
2446 req->flags2,
2447 mask,dirtype,info_level,
2448 requires_resume_key,dont_descend,
2449 ask_sharemode,
2450 &p,pdata,data_end,
2451 space_remaining, &out_of_space,
2452 &got_exact_match,
2453 &last_entry_off, ea_list);
2456 if (finished && out_of_space)
2457 finished = False;
2459 if (!finished && !out_of_space)
2460 numentries++;
2463 * As an optimisation if we know we aren't looking
2464 * for a wildcard name (ie. the name matches the wildcard exactly)
2465 * then we can finish on any (first) match.
2466 * This speeds up large directory searches. JRA.
2469 if(got_exact_match)
2470 finished = True;
2472 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2475 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2476 smb_fn_name(CVAL(req->inbuf,smb_com)),
2477 mask, directory, dirtype, numentries ) );
2479 /* Check if we can close the dirptr */
2480 if(close_after_request || (finished && close_if_end)) {
2481 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2482 dptr_close(&dptr_num); /* This frees up the saved mask */
2485 /* Set up the return parameter block */
2486 SSVAL(params,0,numentries);
2487 SSVAL(params,2,finished);
2488 SSVAL(params,4,0); /* Never an EA error */
2489 SSVAL(params,6,last_entry_off);
2491 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2492 max_data_bytes);
2494 return;
2497 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2499 E_md4hash(lp_servicename(SNUM(conn)),objid);
2500 return objid;
2503 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2505 SMB_ASSERT(extended_info != NULL);
2507 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2508 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2509 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2510 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2511 #ifdef SAMBA_VERSION_REVISION
2512 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2513 #endif
2514 extended_info->samba_subversion = 0;
2515 #ifdef SAMBA_VERSION_RC_RELEASE
2516 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2517 #else
2518 #ifdef SAMBA_VERSION_PRE_RELEASE
2519 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2520 #endif
2521 #endif
2522 #ifdef SAMBA_VERSION_VENDOR_PATCH
2523 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2524 #endif
2525 extended_info->samba_gitcommitdate = 0;
2526 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2527 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2528 #endif
2530 memset(extended_info->samba_version_string, 0,
2531 sizeof(extended_info->samba_version_string));
2533 snprintf (extended_info->samba_version_string,
2534 sizeof(extended_info->samba_version_string),
2535 "%s", samba_version_string());
2538 /****************************************************************************
2539 Reply to a TRANS2_QFSINFO (query filesystem info).
2540 ****************************************************************************/
2542 static void call_trans2qfsinfo(connection_struct *conn,
2543 struct smb_request *req,
2544 char **pparams, int total_params,
2545 char **ppdata, int total_data,
2546 unsigned int max_data_bytes)
2548 char *pdata, *end_data;
2549 char *params = *pparams;
2550 uint16 info_level;
2551 int data_len, len;
2552 SMB_STRUCT_STAT st;
2553 const char *vname = volume_label(SNUM(conn));
2554 int snum = SNUM(conn);
2555 char *fstype = lp_fstype(SNUM(conn));
2556 uint32 additional_flags = 0;
2558 if (total_params < 2) {
2559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2560 return;
2563 info_level = SVAL(params,0);
2565 if (IS_IPC(conn)) {
2566 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2567 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2568 "info level (0x%x) on IPC$.\n",
2569 (unsigned int)info_level));
2570 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2571 return;
2575 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2576 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2577 DEBUG(0,("call_trans2qfsinfo: encryption required "
2578 "and info level 0x%x sent.\n",
2579 (unsigned int)info_level));
2580 exit_server_cleanly("encryption required "
2581 "on connection");
2582 return;
2586 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2588 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2589 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2590 reply_doserror(req, ERRSRV, ERRinvdevice);
2591 return;
2594 *ppdata = (char *)SMB_REALLOC(
2595 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2596 if (*ppdata == NULL ) {
2597 reply_nterror(req, NT_STATUS_NO_MEMORY);
2598 return;
2601 pdata = *ppdata;
2602 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2603 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2605 switch (info_level) {
2606 case SMB_INFO_ALLOCATION:
2608 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2609 data_len = 18;
2610 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2611 reply_unixerror(req, ERRHRD, ERRgeneral);
2612 return;
2615 block_size = lp_block_size(snum);
2616 if (bsize < block_size) {
2617 SMB_BIG_UINT factor = block_size/bsize;
2618 bsize = block_size;
2619 dsize /= factor;
2620 dfree /= factor;
2622 if (bsize > block_size) {
2623 SMB_BIG_UINT factor = bsize/block_size;
2624 bsize = block_size;
2625 dsize *= factor;
2626 dfree *= factor;
2628 bytes_per_sector = 512;
2629 sectors_per_unit = bsize/bytes_per_sector;
2631 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2632 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2633 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2635 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2636 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2637 SIVAL(pdata,l1_cUnit,dsize);
2638 SIVAL(pdata,l1_cUnitAvail,dfree);
2639 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2640 break;
2643 case SMB_INFO_VOLUME:
2644 /* Return volume name */
2646 * Add volume serial number - hash of a combination of
2647 * the called hostname and the service name.
2649 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2651 * Win2k3 and previous mess this up by sending a name length
2652 * one byte short. I believe only older clients (OS/2 Win9x) use
2653 * this call so try fixing this by adding a terminating null to
2654 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2656 len = srvstr_push(
2657 pdata, req->flags2,
2658 pdata+l2_vol_szVolLabel, vname,
2659 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2660 STR_NOALIGN|STR_TERMINATE);
2661 SCVAL(pdata,l2_vol_cch,len);
2662 data_len = l2_vol_szVolLabel + len;
2663 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2664 (unsigned)st.st_ctime, len, vname));
2665 break;
2667 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2668 case SMB_FS_ATTRIBUTE_INFORMATION:
2670 additional_flags = 0;
2671 #if defined(HAVE_SYS_QUOTAS)
2672 additional_flags |= FILE_VOLUME_QUOTAS;
2673 #endif
2675 if(lp_nt_acl_support(SNUM(conn))) {
2676 additional_flags |= FILE_PERSISTENT_ACLS;
2679 /* Capabilities are filled in at connection time through STATVFS call */
2680 additional_flags |= conn->fs_capabilities;
2682 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2683 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2684 additional_flags); /* FS ATTRIBUTES */
2686 SIVAL(pdata,4,255); /* Max filename component length */
2687 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2688 and will think we can't do long filenames */
2689 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2690 PTR_DIFF(end_data, pdata+12),
2691 STR_UNICODE);
2692 SIVAL(pdata,8,len);
2693 data_len = 12 + len;
2694 break;
2696 case SMB_QUERY_FS_LABEL_INFO:
2697 case SMB_FS_LABEL_INFORMATION:
2698 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2699 PTR_DIFF(end_data, pdata+4), 0);
2700 data_len = 4 + len;
2701 SIVAL(pdata,0,len);
2702 break;
2704 case SMB_QUERY_FS_VOLUME_INFO:
2705 case SMB_FS_VOLUME_INFORMATION:
2708 * Add volume serial number - hash of a combination of
2709 * the called hostname and the service name.
2711 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2712 (str_checksum(get_local_machine_name())<<16));
2714 /* Max label len is 32 characters. */
2715 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2716 PTR_DIFF(end_data, pdata+18),
2717 STR_UNICODE);
2718 SIVAL(pdata,12,len);
2719 data_len = 18+len;
2721 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2722 (int)strlen(vname),vname, lp_servicename(snum)));
2723 break;
2725 case SMB_QUERY_FS_SIZE_INFO:
2726 case SMB_FS_SIZE_INFORMATION:
2728 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2729 data_len = 24;
2730 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2731 reply_unixerror(req, ERRHRD, ERRgeneral);
2732 return;
2734 block_size = lp_block_size(snum);
2735 if (bsize < block_size) {
2736 SMB_BIG_UINT factor = block_size/bsize;
2737 bsize = block_size;
2738 dsize /= factor;
2739 dfree /= factor;
2741 if (bsize > block_size) {
2742 SMB_BIG_UINT factor = bsize/block_size;
2743 bsize = block_size;
2744 dsize *= factor;
2745 dfree *= factor;
2747 bytes_per_sector = 512;
2748 sectors_per_unit = bsize/bytes_per_sector;
2749 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2750 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2751 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2752 SBIG_UINT(pdata,0,dsize);
2753 SBIG_UINT(pdata,8,dfree);
2754 SIVAL(pdata,16,sectors_per_unit);
2755 SIVAL(pdata,20,bytes_per_sector);
2756 break;
2759 case SMB_FS_FULL_SIZE_INFORMATION:
2761 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2762 data_len = 32;
2763 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2764 reply_unixerror(req, ERRHRD, ERRgeneral);
2765 return;
2767 block_size = lp_block_size(snum);
2768 if (bsize < block_size) {
2769 SMB_BIG_UINT factor = block_size/bsize;
2770 bsize = block_size;
2771 dsize /= factor;
2772 dfree /= factor;
2774 if (bsize > block_size) {
2775 SMB_BIG_UINT factor = bsize/block_size;
2776 bsize = block_size;
2777 dsize *= factor;
2778 dfree *= factor;
2780 bytes_per_sector = 512;
2781 sectors_per_unit = bsize/bytes_per_sector;
2782 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2783 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2784 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2785 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2786 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2787 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2788 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2789 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2790 break;
2793 case SMB_QUERY_FS_DEVICE_INFO:
2794 case SMB_FS_DEVICE_INFORMATION:
2795 data_len = 8;
2796 SIVAL(pdata,0,0); /* dev type */
2797 SIVAL(pdata,4,0); /* characteristics */
2798 break;
2800 #ifdef HAVE_SYS_QUOTAS
2801 case SMB_FS_QUOTA_INFORMATION:
2803 * what we have to send --metze:
2805 * Unknown1: 24 NULL bytes
2806 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2807 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2808 * Quota Flags: 2 byte :
2809 * Unknown3: 6 NULL bytes
2811 * 48 bytes total
2813 * details for Quota Flags:
2815 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2816 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2817 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2818 * 0x0001 Enable Quotas: enable quota for this fs
2822 /* we need to fake up a fsp here,
2823 * because its not send in this call
2825 files_struct fsp;
2826 SMB_NTQUOTA_STRUCT quotas;
2828 ZERO_STRUCT(fsp);
2829 ZERO_STRUCT(quotas);
2831 fsp.conn = conn;
2832 fsp.fnum = -1;
2834 /* access check */
2835 if (conn->server_info->utok.uid != 0) {
2836 DEBUG(0,("set_user_quota: access_denied "
2837 "service [%s] user [%s]\n",
2838 lp_servicename(SNUM(conn)),
2839 conn->server_info->unix_name));
2840 reply_doserror(req, ERRDOS, ERRnoaccess);
2841 return;
2844 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2845 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2846 reply_doserror(req, ERRSRV, ERRerror);
2847 return;
2850 data_len = 48;
2852 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2854 /* Unknown1 24 NULL bytes*/
2855 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2856 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2857 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2859 /* Default Soft Quota 8 bytes */
2860 SBIG_UINT(pdata,24,quotas.softlim);
2862 /* Default Hard Quota 8 bytes */
2863 SBIG_UINT(pdata,32,quotas.hardlim);
2865 /* Quota flag 2 bytes */
2866 SSVAL(pdata,40,quotas.qflags);
2868 /* Unknown3 6 NULL bytes */
2869 SSVAL(pdata,42,0);
2870 SIVAL(pdata,44,0);
2872 break;
2874 #endif /* HAVE_SYS_QUOTAS */
2875 case SMB_FS_OBJECTID_INFORMATION:
2877 unsigned char objid[16];
2878 struct smb_extended_info extended_info;
2879 memcpy(pdata,create_volume_objectid(conn, objid),16);
2880 samba_extended_info_version (&extended_info);
2881 SIVAL(pdata,16,extended_info.samba_magic);
2882 SIVAL(pdata,20,extended_info.samba_version);
2883 SIVAL(pdata,24,extended_info.samba_subversion);
2884 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2885 memcpy(pdata+36,extended_info.samba_version_string,28);
2886 data_len = 64;
2887 break;
2891 * Query the version and capabilities of the CIFS UNIX extensions
2892 * in use.
2895 case SMB_QUERY_CIFS_UNIX_INFO:
2897 bool large_write = lp_min_receive_file_size() &&
2898 !srv_is_signing_active();
2899 bool large_read = !srv_is_signing_active();
2900 int encrypt_caps = 0;
2902 if (!lp_unix_extensions()) {
2903 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2904 return;
2907 switch (conn->encrypt_level) {
2908 case 0:
2909 encrypt_caps = 0;
2910 break;
2911 case 1:
2912 case Auto:
2913 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2914 break;
2915 case Required:
2916 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2917 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2918 large_write = false;
2919 large_read = false;
2920 break;
2923 data_len = 12;
2924 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2925 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2927 /* We have POSIX ACLs, pathname, encryption,
2928 * large read/write, and locking capability. */
2930 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2931 CIFS_UNIX_POSIX_ACLS_CAP|
2932 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2933 CIFS_UNIX_FCNTL_LOCKS_CAP|
2934 CIFS_UNIX_EXTATTR_CAP|
2935 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2936 encrypt_caps|
2937 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2938 (large_write ?
2939 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2940 break;
2943 case SMB_QUERY_POSIX_FS_INFO:
2945 int rc;
2946 vfs_statvfs_struct svfs;
2948 if (!lp_unix_extensions()) {
2949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2950 return;
2953 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2955 if (!rc) {
2956 data_len = 56;
2957 SIVAL(pdata,0,svfs.OptimalTransferSize);
2958 SIVAL(pdata,4,svfs.BlockSize);
2959 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2960 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2961 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2962 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2963 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2964 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2965 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2966 #ifdef EOPNOTSUPP
2967 } else if (rc == EOPNOTSUPP) {
2968 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2969 return;
2970 #endif /* EOPNOTSUPP */
2971 } else {
2972 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2973 reply_doserror(req, ERRSRV, ERRerror);
2974 return;
2976 break;
2979 case SMB_QUERY_POSIX_WHOAMI:
2981 uint32_t flags = 0;
2982 uint32_t sid_bytes;
2983 int i;
2985 if (!lp_unix_extensions()) {
2986 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2987 return;
2990 if (max_data_bytes < 40) {
2991 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2992 return;
2995 /* We ARE guest if global_sid_Builtin_Guests is
2996 * in our list of SIDs.
2998 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2999 conn->server_info->ptok)) {
3000 flags |= SMB_WHOAMI_GUEST;
3003 /* We are NOT guest if global_sid_Authenticated_Users
3004 * is in our list of SIDs.
3006 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3007 conn->server_info->ptok)) {
3008 flags &= ~SMB_WHOAMI_GUEST;
3011 /* NOTE: 8 bytes for UID/GID, irrespective of native
3012 * platform size. This matches
3013 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3015 data_len = 4 /* flags */
3016 + 4 /* flag mask */
3017 + 8 /* uid */
3018 + 8 /* gid */
3019 + 4 /* ngroups */
3020 + 4 /* num_sids */
3021 + 4 /* SID bytes */
3022 + 4 /* pad/reserved */
3023 + (conn->server_info->utok.ngroups * 8)
3024 /* groups list */
3025 + (conn->server_info->ptok->num_sids *
3026 SID_MAX_SIZE)
3027 /* SID list */;
3029 SIVAL(pdata, 0, flags);
3030 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3031 SBIG_UINT(pdata, 8,
3032 (SMB_BIG_UINT)conn->server_info->utok.uid);
3033 SBIG_UINT(pdata, 16,
3034 (SMB_BIG_UINT)conn->server_info->utok.gid);
3037 if (data_len >= max_data_bytes) {
3038 /* Potential overflow, skip the GIDs and SIDs. */
3040 SIVAL(pdata, 24, 0); /* num_groups */
3041 SIVAL(pdata, 28, 0); /* num_sids */
3042 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3043 SIVAL(pdata, 36, 0); /* reserved */
3045 data_len = 40;
3046 break;
3049 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3050 SIVAL(pdata, 28, conn->server_info->num_sids);
3052 /* We walk the SID list twice, but this call is fairly
3053 * infrequent, and I don't expect that it's performance
3054 * sensitive -- jpeach
3056 for (i = 0, sid_bytes = 0;
3057 i < conn->server_info->ptok->num_sids; ++i) {
3058 sid_bytes += ndr_size_dom_sid(
3059 &conn->server_info->ptok->user_sids[i],
3063 /* SID list byte count */
3064 SIVAL(pdata, 32, sid_bytes);
3066 /* 4 bytes pad/reserved - must be zero */
3067 SIVAL(pdata, 36, 0);
3068 data_len = 40;
3070 /* GID list */
3071 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3072 SBIG_UINT(pdata, data_len,
3073 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3074 data_len += 8;
3077 /* SID list */
3078 for (i = 0;
3079 i < conn->server_info->ptok->num_sids; ++i) {
3080 int sid_len = ndr_size_dom_sid(
3081 &conn->server_info->ptok->user_sids[i],
3084 sid_linearize(pdata + data_len, sid_len,
3085 &conn->server_info->ptok->user_sids[i]);
3086 data_len += sid_len;
3089 break;
3092 case SMB_MAC_QUERY_FS_INFO:
3094 * Thursby MAC extension... ONLY on NTFS filesystems
3095 * once we do streams then we don't need this
3097 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3098 data_len = 88;
3099 SIVAL(pdata,84,0x100); /* Don't support mac... */
3100 break;
3102 /* drop through */
3103 default:
3104 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3105 return;
3109 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3110 max_data_bytes);
3112 DEBUG( 4, ( "%s info_level = %d\n",
3113 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3115 return;
3118 /****************************************************************************
3119 Reply to a TRANS2_SETFSINFO (set filesystem info).
3120 ****************************************************************************/
3122 static void call_trans2setfsinfo(connection_struct *conn,
3123 struct smb_request *req,
3124 char **pparams, int total_params,
3125 char **ppdata, int total_data,
3126 unsigned int max_data_bytes)
3128 char *pdata = *ppdata;
3129 char *params = *pparams;
3130 uint16 info_level;
3132 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3134 /* */
3135 if (total_params < 4) {
3136 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3137 total_params));
3138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3139 return;
3142 info_level = SVAL(params,2);
3144 if (IS_IPC(conn)) {
3145 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3146 info_level != SMB_SET_CIFS_UNIX_INFO) {
3147 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3148 "info level (0x%x) on IPC$.\n",
3149 (unsigned int)info_level));
3150 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3151 return;
3155 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3156 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3157 DEBUG(0,("call_trans2setfsinfo: encryption required "
3158 "and info level 0x%x sent.\n",
3159 (unsigned int)info_level));
3160 exit_server_cleanly("encryption required "
3161 "on connection");
3162 return;
3166 switch(info_level) {
3167 case SMB_SET_CIFS_UNIX_INFO:
3169 uint16 client_unix_major;
3170 uint16 client_unix_minor;
3171 uint32 client_unix_cap_low;
3172 uint32 client_unix_cap_high;
3174 if (!lp_unix_extensions()) {
3175 reply_nterror(req,
3176 NT_STATUS_INVALID_LEVEL);
3177 return;
3180 /* There should be 12 bytes of capabilities set. */
3181 if (total_data < 8) {
3182 reply_nterror(
3183 req,
3184 NT_STATUS_INVALID_PARAMETER);
3185 return;
3187 client_unix_major = SVAL(pdata,0);
3188 client_unix_minor = SVAL(pdata,2);
3189 client_unix_cap_low = IVAL(pdata,4);
3190 client_unix_cap_high = IVAL(pdata,8);
3191 /* Just print these values for now. */
3192 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3193 cap_low = 0x%x, cap_high = 0x%x\n",
3194 (unsigned int)client_unix_major,
3195 (unsigned int)client_unix_minor,
3196 (unsigned int)client_unix_cap_low,
3197 (unsigned int)client_unix_cap_high ));
3199 /* Here is where we must switch to posix pathname processing... */
3200 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3201 lp_set_posix_pathnames();
3202 mangle_change_to_posix();
3205 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3206 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3207 /* Client that knows how to do posix locks,
3208 * but not posix open/mkdir operations. Set a
3209 * default type for read/write checks. */
3211 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3214 break;
3217 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3219 NTSTATUS status;
3220 size_t param_len = 0;
3221 size_t data_len = total_data;
3223 if (!lp_unix_extensions()) {
3224 reply_nterror(
3225 req,
3226 NT_STATUS_INVALID_LEVEL);
3227 return;
3230 if (lp_smb_encrypt(SNUM(conn)) == false) {
3231 reply_nterror(
3232 req,
3233 NT_STATUS_NOT_SUPPORTED);
3234 return;
3237 DEBUG( 4,("call_trans2setfsinfo: "
3238 "request transport encryption.\n"));
3240 status = srv_request_encryption_setup(conn,
3241 (unsigned char **)ppdata,
3242 &data_len,
3243 (unsigned char **)pparams,
3244 &param_len);
3246 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3247 !NT_STATUS_IS_OK(status)) {
3248 reply_nterror(req, status);
3249 return;
3252 send_trans2_replies(conn, req,
3253 *pparams,
3254 param_len,
3255 *ppdata,
3256 data_len,
3257 max_data_bytes);
3259 if (NT_STATUS_IS_OK(status)) {
3260 /* Server-side transport
3261 * encryption is now *on*. */
3262 status = srv_encryption_start(conn);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 exit_server_cleanly(
3265 "Failure in setting "
3266 "up encrypted transport");
3269 return;
3272 case SMB_FS_QUOTA_INFORMATION:
3274 files_struct *fsp = NULL;
3275 SMB_NTQUOTA_STRUCT quotas;
3277 ZERO_STRUCT(quotas);
3279 /* access check */
3280 if ((conn->server_info->utok.uid != 0)
3281 ||!CAN_WRITE(conn)) {
3282 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3283 lp_servicename(SNUM(conn)),
3284 conn->server_info->unix_name));
3285 reply_doserror(req, ERRSRV, ERRaccess);
3286 return;
3289 /* note: normaly there're 48 bytes,
3290 * but we didn't use the last 6 bytes for now
3291 * --metze
3293 fsp = file_fsp(SVAL(params,0));
3295 if (!check_fsp_ntquota_handle(conn, req,
3296 fsp)) {
3297 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3298 reply_nterror(
3299 req, NT_STATUS_INVALID_HANDLE);
3300 return;
3303 if (total_data < 42) {
3304 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3305 total_data));
3306 reply_nterror(
3307 req,
3308 NT_STATUS_INVALID_PARAMETER);
3309 return;
3312 /* unknown_1 24 NULL bytes in pdata*/
3314 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3315 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3316 #ifdef LARGE_SMB_OFF_T
3317 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3318 #else /* LARGE_SMB_OFF_T */
3319 if ((IVAL(pdata,28) != 0)&&
3320 ((quotas.softlim != 0xFFFFFFFF)||
3321 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3322 /* more than 32 bits? */
3323 reply_nterror(
3324 req,
3325 NT_STATUS_INVALID_PARAMETER);
3326 return;
3328 #endif /* LARGE_SMB_OFF_T */
3330 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3331 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3332 #ifdef LARGE_SMB_OFF_T
3333 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3334 #else /* LARGE_SMB_OFF_T */
3335 if ((IVAL(pdata,36) != 0)&&
3336 ((quotas.hardlim != 0xFFFFFFFF)||
3337 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3338 /* more than 32 bits? */
3339 reply_nterror(
3340 req,
3341 NT_STATUS_INVALID_PARAMETER);
3342 return;
3344 #endif /* LARGE_SMB_OFF_T */
3346 /* quota_flags 2 bytes **/
3347 quotas.qflags = SVAL(pdata,40);
3349 /* unknown_2 6 NULL bytes follow*/
3351 /* now set the quotas */
3352 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3353 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3354 reply_doserror(req, ERRSRV, ERRerror);
3355 return;
3358 break;
3360 default:
3361 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3362 info_level));
3363 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3364 return;
3365 break;
3369 * sending this reply works fine,
3370 * but I'm not sure it's the same
3371 * like windows do...
3372 * --metze
3374 reply_outbuf(req, 10, 0);
3377 #if defined(HAVE_POSIX_ACLS)
3378 /****************************************************************************
3379 Utility function to count the number of entries in a POSIX acl.
3380 ****************************************************************************/
3382 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3384 unsigned int ace_count = 0;
3385 int entry_id = SMB_ACL_FIRST_ENTRY;
3386 SMB_ACL_ENTRY_T entry;
3388 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3389 /* get_next... */
3390 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3391 entry_id = SMB_ACL_NEXT_ENTRY;
3393 ace_count++;
3395 return ace_count;
3398 /****************************************************************************
3399 Utility function to marshall a POSIX acl into wire format.
3400 ****************************************************************************/
3402 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3404 int entry_id = SMB_ACL_FIRST_ENTRY;
3405 SMB_ACL_ENTRY_T entry;
3407 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3408 SMB_ACL_TAG_T tagtype;
3409 SMB_ACL_PERMSET_T permset;
3410 unsigned char perms = 0;
3411 unsigned int own_grp;
3413 /* get_next... */
3414 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3415 entry_id = SMB_ACL_NEXT_ENTRY;
3418 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3419 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3420 return False;
3423 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3424 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3425 return False;
3428 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3429 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3430 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3432 SCVAL(pdata,1,perms);
3434 switch (tagtype) {
3435 case SMB_ACL_USER_OBJ:
3436 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3437 own_grp = (unsigned int)pst->st_uid;
3438 SIVAL(pdata,2,own_grp);
3439 SIVAL(pdata,6,0);
3440 break;
3441 case SMB_ACL_USER:
3443 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3444 if (!puid) {
3445 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3446 return False;
3448 own_grp = (unsigned int)*puid;
3449 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3450 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3451 SIVAL(pdata,2,own_grp);
3452 SIVAL(pdata,6,0);
3453 break;
3455 case SMB_ACL_GROUP_OBJ:
3456 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3457 own_grp = (unsigned int)pst->st_gid;
3458 SIVAL(pdata,2,own_grp);
3459 SIVAL(pdata,6,0);
3460 break;
3461 case SMB_ACL_GROUP:
3463 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3464 if (!pgid) {
3465 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3466 return False;
3468 own_grp = (unsigned int)*pgid;
3469 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3470 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3471 SIVAL(pdata,2,own_grp);
3472 SIVAL(pdata,6,0);
3473 break;
3475 case SMB_ACL_MASK:
3476 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3477 SIVAL(pdata,2,0xFFFFFFFF);
3478 SIVAL(pdata,6,0xFFFFFFFF);
3479 break;
3480 case SMB_ACL_OTHER:
3481 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3482 SIVAL(pdata,2,0xFFFFFFFF);
3483 SIVAL(pdata,6,0xFFFFFFFF);
3484 break;
3485 default:
3486 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3487 return False;
3489 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3492 return True;
3494 #endif
3496 /****************************************************************************
3497 Store the FILE_UNIX_BASIC info.
3498 ****************************************************************************/
3500 static char *store_file_unix_basic(connection_struct *conn,
3501 char *pdata,
3502 files_struct *fsp,
3503 const SMB_STRUCT_STAT *psbuf)
3505 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3506 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3508 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3509 pdata += 8;
3511 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3512 pdata += 8;
3514 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3515 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3516 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3517 pdata += 24;
3519 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3520 SIVAL(pdata,4,0);
3521 pdata += 8;
3523 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3524 SIVAL(pdata,4,0);
3525 pdata += 8;
3527 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3528 pdata += 4;
3530 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3531 SIVAL(pdata,4,0);
3532 pdata += 8;
3534 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3535 SIVAL(pdata,4,0);
3536 pdata += 8;
3538 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3539 pdata += 8;
3541 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3542 SIVAL(pdata,4,0);
3543 pdata += 8;
3545 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3546 SIVAL(pdata,4,0);
3547 pdata += 8;
3549 return pdata;
3552 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3553 * the chflags(2) (or equivalent) flags.
3555 * XXX: this really should be behind the VFS interface. To do this, we would
3556 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3557 * Each VFS module could then implement its own mapping as appropriate for the
3558 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3560 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3561 info2_flags_map[] =
3563 #ifdef UF_NODUMP
3564 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3565 #endif
3567 #ifdef UF_IMMUTABLE
3568 { UF_IMMUTABLE, EXT_IMMUTABLE },
3569 #endif
3571 #ifdef UF_APPEND
3572 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3573 #endif
3575 #ifdef UF_HIDDEN
3576 { UF_HIDDEN, EXT_HIDDEN },
3577 #endif
3579 /* Do not remove. We need to guarantee that this array has at least one
3580 * entry to build on HP-UX.
3582 { 0, 0 }
3586 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3587 uint32 *smb_fflags, uint32 *smb_fmask)
3589 #ifdef HAVE_STAT_ST_FLAGS
3590 int i;
3592 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3593 *smb_fmask |= info2_flags_map[i].smb_fflag;
3594 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3595 *smb_fflags |= info2_flags_map[i].smb_fflag;
3598 #endif /* HAVE_STAT_ST_FLAGS */
3601 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3602 const uint32 smb_fflags,
3603 const uint32 smb_fmask,
3604 int *stat_fflags)
3606 #ifdef HAVE_STAT_ST_FLAGS
3607 uint32 max_fmask = 0;
3608 int i;
3610 *stat_fflags = psbuf->st_flags;
3612 /* For each flags requested in smb_fmask, check the state of the
3613 * corresponding flag in smb_fflags and set or clear the matching
3614 * stat flag.
3617 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3618 max_fmask |= info2_flags_map[i].smb_fflag;
3619 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3620 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3621 *stat_fflags |= info2_flags_map[i].stat_fflag;
3622 } else {
3623 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3628 /* If smb_fmask is asking to set any bits that are not supported by
3629 * our flag mappings, we should fail.
3631 if ((smb_fmask & max_fmask) != smb_fmask) {
3632 return False;
3635 return True;
3636 #else
3637 return False;
3638 #endif /* HAVE_STAT_ST_FLAGS */
3642 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3643 * of file flags and birth (create) time.
3645 static char *store_file_unix_basic_info2(connection_struct *conn,
3646 char *pdata,
3647 files_struct *fsp,
3648 const SMB_STRUCT_STAT *psbuf)
3650 uint32 file_flags = 0;
3651 uint32 flags_mask = 0;
3653 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3655 /* Create (birth) time 64 bit */
3656 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3657 pdata += 8;
3659 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3660 SIVAL(pdata, 0, file_flags); /* flags */
3661 SIVAL(pdata, 4, flags_mask); /* mask */
3662 pdata += 8;
3664 return pdata;
3667 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3668 const struct stream_struct *streams,
3669 char *data,
3670 unsigned int max_data_bytes,
3671 unsigned int *data_size)
3673 unsigned int i;
3674 unsigned int ofs = 0;
3676 for (i=0; i<num_streams; i++) {
3677 unsigned int next_offset;
3678 size_t namelen;
3679 smb_ucs2_t *namebuf;
3681 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3682 streams[i].name, &namelen) ||
3683 namelen <= 2)
3685 return NT_STATUS_INVALID_PARAMETER;
3689 * name_buf is now null-terminated, we need to marshall as not
3690 * terminated
3693 namelen -= 2;
3695 if (ofs + 24 + namelen > max_data_bytes) {
3696 TALLOC_FREE(namebuf);
3697 return NT_STATUS_BUFFER_TOO_SMALL;
3700 SIVAL(data, ofs+4, namelen);
3701 SOFF_T(data, ofs+8, streams[i].size);
3702 SOFF_T(data, ofs+16, streams[i].alloc_size);
3703 memcpy(data+ofs+24, namebuf, namelen);
3704 TALLOC_FREE(namebuf);
3706 next_offset = ofs + 24 + namelen;
3708 if (i == num_streams-1) {
3709 SIVAL(data, ofs, 0);
3711 else {
3712 unsigned int align = ndr_align_size(next_offset, 8);
3714 if (next_offset + align > max_data_bytes) {
3715 return NT_STATUS_BUFFER_TOO_SMALL;
3718 memset(data+next_offset, 0, align);
3719 next_offset += align;
3721 SIVAL(data, ofs, next_offset - ofs);
3722 ofs = next_offset;
3725 ofs = next_offset;
3728 *data_size = ofs;
3730 return NT_STATUS_OK;
3733 /****************************************************************************
3734 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3735 ****************************************************************************/
3737 static void call_trans2qpipeinfo(connection_struct *conn,
3738 struct smb_request *req,
3739 unsigned int tran_call,
3740 char **pparams, int total_params,
3741 char **ppdata, int total_data,
3742 unsigned int max_data_bytes)
3744 char *params = *pparams;
3745 char *pdata = *ppdata;
3746 unsigned int data_size = 0;
3747 unsigned int param_size = 2;
3748 uint16 info_level;
3749 smb_np_struct *p_pipe = NULL;
3751 if (!params) {
3752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3753 return;
3756 if (total_params < 4) {
3757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3758 return;
3761 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3762 if (p_pipe == NULL) {
3763 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3764 return;
3767 info_level = SVAL(params,2);
3769 *pparams = (char *)SMB_REALLOC(*pparams,2);
3770 if (*pparams == NULL) {
3771 reply_nterror(req, NT_STATUS_NO_MEMORY);
3772 return;
3774 params = *pparams;
3775 SSVAL(params,0,0);
3776 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3777 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3778 if (*ppdata == NULL ) {
3779 reply_nterror(req, NT_STATUS_NO_MEMORY);
3780 return;
3782 pdata = *ppdata;
3784 switch (info_level) {
3785 case SMB_FILE_STANDARD_INFORMATION:
3786 memset(pdata,0,24);
3787 SOFF_T(pdata,0,4096LL);
3788 SIVAL(pdata,16,1);
3789 SIVAL(pdata,20,1);
3790 data_size = 24;
3791 break;
3793 default:
3794 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3795 return;
3798 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3799 max_data_bytes);
3801 return;
3804 /****************************************************************************
3805 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3806 file name or file id).
3807 ****************************************************************************/
3809 static void call_trans2qfilepathinfo(connection_struct *conn,
3810 struct smb_request *req,
3811 unsigned int tran_call,
3812 char **pparams, int total_params,
3813 char **ppdata, int total_data,
3814 unsigned int max_data_bytes)
3816 char *params = *pparams;
3817 char *pdata = *ppdata;
3818 char *dstart, *dend;
3819 uint16 info_level;
3820 int mode=0;
3821 int nlink;
3822 SMB_OFF_T file_size=0;
3823 SMB_BIG_UINT allocation_size=0;
3824 unsigned int data_size = 0;
3825 unsigned int param_size = 2;
3826 SMB_STRUCT_STAT sbuf;
3827 char *dos_fname = NULL;
3828 char *fname = NULL;
3829 char *fullpathname;
3830 char *base_name;
3831 char *p;
3832 SMB_OFF_T pos = 0;
3833 bool delete_pending = False;
3834 int len;
3835 time_t create_time, mtime, atime;
3836 struct timespec create_time_ts, mtime_ts, atime_ts;
3837 struct timespec write_time_ts;
3838 files_struct *fsp = NULL;
3839 struct file_id fileid;
3840 struct ea_list *ea_list = NULL;
3841 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
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);
3934 access_mask = fsp->access_mask;
3937 } else {
3938 NTSTATUS status = NT_STATUS_OK;
3940 /* qpathinfo */
3941 if (total_params < 7) {
3942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3943 return;
3946 info_level = SVAL(params,0);
3948 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3950 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3952 return;
3955 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3956 total_params - 6,
3957 STR_TERMINATE, &status);
3958 if (!NT_STATUS_IS_OK(status)) {
3959 reply_nterror(req, status);
3960 return;
3963 status = resolve_dfspath(ctx,
3964 conn,
3965 req->flags2 & FLAGS2_DFS_PATHNAMES,
3966 fname,
3967 &fname);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3970 reply_botherror(req,
3971 NT_STATUS_PATH_NOT_COVERED,
3972 ERRSRV, ERRbadpath);
3974 reply_nterror(req, status);
3975 return;
3978 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 reply_nterror(req, status);
3981 return;
3983 status = check_name(conn, fname);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3986 reply_nterror(req, status);
3987 return;
3990 if (INFO_LEVEL_IS_UNIX(info_level)) {
3991 /* Always do lstat for UNIX calls. */
3992 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3993 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3994 reply_unixerror(req, ERRDOS, ERRbadpath);
3995 return;
3998 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3999 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4001 if (!ms_dfs_link) {
4002 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4003 reply_unixerror(req, ERRDOS, ERRbadpath);
4004 return;
4008 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4009 get_file_infos(fileid, &delete_pending, &write_time_ts);
4010 if (delete_pending) {
4011 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4012 return;
4016 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4017 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4018 return;
4021 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4022 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4024 p = strrchr_m(fname,'/');
4025 if (!p)
4026 base_name = fname;
4027 else
4028 base_name = p+1;
4030 if (ms_dfs_link) {
4031 mode = dos_mode_msdfs(conn,fname,&sbuf);
4032 } else {
4033 mode = dos_mode(conn,fname,&sbuf);
4035 if (!mode)
4036 mode = FILE_ATTRIBUTE_NORMAL;
4038 nlink = sbuf.st_nlink;
4040 if (nlink && (mode&aDIR)) {
4041 nlink = 1;
4044 if ((nlink > 0) && delete_pending) {
4045 nlink -= 1;
4048 fullpathname = fname;
4049 if (!(mode & aDIR))
4050 file_size = get_file_size(sbuf);
4052 /* Pull out any data sent here before we realloc. */
4053 switch (info_level) {
4054 case SMB_INFO_QUERY_EAS_FROM_LIST:
4056 /* Pull any EA list from the data portion. */
4057 uint32 ea_size;
4059 if (total_data < 4) {
4060 reply_nterror(
4061 req, NT_STATUS_INVALID_PARAMETER);
4062 return;
4064 ea_size = IVAL(pdata,0);
4066 if (total_data > 0 && ea_size != total_data) {
4067 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4068 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4069 reply_nterror(
4070 req, NT_STATUS_INVALID_PARAMETER);
4071 return;
4074 if (!lp_ea_support(SNUM(conn))) {
4075 reply_doserror(req, ERRDOS,
4076 ERReasnotsupported);
4077 return;
4080 /* Pull out the list of names. */
4081 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4082 if (!ea_list) {
4083 reply_nterror(
4084 req, NT_STATUS_INVALID_PARAMETER);
4085 return;
4087 break;
4090 case SMB_QUERY_POSIX_LOCK:
4092 if (fsp == NULL || fsp->fh->fd == -1) {
4093 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4094 return;
4097 if (total_data != POSIX_LOCK_DATA_SIZE) {
4098 reply_nterror(
4099 req, NT_STATUS_INVALID_PARAMETER);
4100 return;
4103 /* Copy the lock range data. */
4104 lock_data = (char *)TALLOC_MEMDUP(
4105 ctx, pdata, total_data);
4106 if (!lock_data) {
4107 reply_nterror(req, NT_STATUS_NO_MEMORY);
4108 return;
4111 default:
4112 break;
4115 *pparams = (char *)SMB_REALLOC(*pparams,2);
4116 if (*pparams == NULL) {
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 return;
4120 params = *pparams;
4121 SSVAL(params,0,0);
4122 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4123 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4124 if (*ppdata == NULL ) {
4125 reply_nterror(req, NT_STATUS_NO_MEMORY);
4126 return;
4128 pdata = *ppdata;
4129 dstart = pdata;
4130 dend = dstart + data_size - 1;
4132 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4133 mtime_ts = get_mtimespec(&sbuf);
4134 atime_ts = get_atimespec(&sbuf);
4136 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4138 if (!fsp) {
4139 /* Do we have this path open ? */
4140 files_struct *fsp1;
4141 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4142 fsp1 = file_find_di_first(fileid);
4143 if (fsp1 && fsp1->initial_allocation_size) {
4144 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4148 if (!null_timespec(write_time_ts)) {
4149 mtime_ts = write_time_ts;
4152 if (lp_dos_filetime_resolution(SNUM(conn))) {
4153 dos_filetime_timespec(&create_time_ts);
4154 dos_filetime_timespec(&mtime_ts);
4155 dos_filetime_timespec(&atime_ts);
4158 create_time = convert_timespec_to_time_t(create_time_ts);
4159 mtime = convert_timespec_to_time_t(mtime_ts);
4160 atime = convert_timespec_to_time_t(atime_ts);
4162 /* NT expects the name to be in an exact form of the *full*
4163 filename. See the trans2 torture test */
4164 if (ISDOT(base_name)) {
4165 dos_fname = talloc_strdup(ctx, "\\");
4166 if (!dos_fname) {
4167 reply_nterror(req, NT_STATUS_NO_MEMORY);
4168 return;
4170 } else {
4171 dos_fname = talloc_asprintf(ctx,
4172 "\\%s",
4173 fname);
4174 if (!dos_fname) {
4175 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 return;
4178 string_replace(dos_fname, '/', '\\');
4181 switch (info_level) {
4182 case SMB_INFO_STANDARD:
4183 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4184 data_size = 22;
4185 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4186 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4187 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4188 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4189 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4190 SSVAL(pdata,l1_attrFile,mode);
4191 break;
4193 case SMB_INFO_QUERY_EA_SIZE:
4195 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4196 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4197 data_size = 26;
4198 srv_put_dos_date2(pdata,0,create_time);
4199 srv_put_dos_date2(pdata,4,atime);
4200 srv_put_dos_date2(pdata,8,mtime); /* write time */
4201 SIVAL(pdata,12,(uint32)file_size);
4202 SIVAL(pdata,16,(uint32)allocation_size);
4203 SSVAL(pdata,20,mode);
4204 SIVAL(pdata,22,ea_size);
4205 break;
4208 case SMB_INFO_IS_NAME_VALID:
4209 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4210 if (tran_call == TRANSACT2_QFILEINFO) {
4211 /* os/2 needs this ? really ?*/
4212 reply_doserror(req, ERRDOS, ERRbadfunc);
4213 return;
4215 data_size = 0;
4216 param_size = 0;
4217 break;
4219 case SMB_INFO_QUERY_EAS_FROM_LIST:
4221 size_t total_ea_len = 0;
4222 struct ea_list *ea_file_list = NULL;
4224 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4226 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4227 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4229 if (!ea_list || (total_ea_len > data_size)) {
4230 data_size = 4;
4231 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4232 break;
4235 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4236 break;
4239 case SMB_INFO_QUERY_ALL_EAS:
4241 /* We have data_size bytes to put EA's into. */
4242 size_t total_ea_len = 0;
4244 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4246 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4247 if (!ea_list || (total_ea_len > data_size)) {
4248 data_size = 4;
4249 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4250 break;
4253 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4254 break;
4257 case SMB_FILE_BASIC_INFORMATION:
4258 case SMB_QUERY_FILE_BASIC_INFO:
4260 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4261 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4262 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4263 } else {
4264 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4265 data_size = 40;
4266 SIVAL(pdata,36,0);
4268 put_long_date_timespec(pdata,create_time_ts);
4269 put_long_date_timespec(pdata+8,atime_ts);
4270 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4271 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4272 SIVAL(pdata,32,mode);
4274 DEBUG(5,("SMB_QFBI - "));
4275 DEBUG(5,("create: %s ", ctime(&create_time)));
4276 DEBUG(5,("access: %s ", ctime(&atime)));
4277 DEBUG(5,("write: %s ", ctime(&mtime)));
4278 DEBUG(5,("change: %s ", ctime(&mtime)));
4279 DEBUG(5,("mode: %x\n", mode));
4280 break;
4282 case SMB_FILE_STANDARD_INFORMATION:
4283 case SMB_QUERY_FILE_STANDARD_INFO:
4285 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4286 data_size = 24;
4287 SOFF_T(pdata,0,allocation_size);
4288 SOFF_T(pdata,8,file_size);
4289 SIVAL(pdata,16,nlink);
4290 SCVAL(pdata,20,delete_pending?1:0);
4291 SCVAL(pdata,21,(mode&aDIR)?1:0);
4292 SSVAL(pdata,22,0); /* Padding. */
4293 break;
4295 case SMB_FILE_EA_INFORMATION:
4296 case SMB_QUERY_FILE_EA_INFO:
4298 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4299 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4300 data_size = 4;
4301 SIVAL(pdata,0,ea_size);
4302 break;
4305 /* Get the 8.3 name - used if NT SMB was negotiated. */
4306 case SMB_QUERY_FILE_ALT_NAME_INFO:
4307 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4309 char mangled_name[13];
4310 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4311 if (!name_to_8_3(base_name,mangled_name,
4312 True,conn->params)) {
4313 reply_nterror(
4314 req,
4315 NT_STATUS_NO_MEMORY);
4317 len = srvstr_push(dstart, req->flags2,
4318 pdata+4, mangled_name,
4319 PTR_DIFF(dend, pdata+4),
4320 STR_UNICODE);
4321 data_size = 4 + len;
4322 SIVAL(pdata,0,len);
4323 break;
4326 case SMB_QUERY_FILE_NAME_INFO:
4328 this must be *exactly* right for ACLs on mapped drives to work
4330 len = srvstr_push(dstart, req->flags2,
4331 pdata+4, dos_fname,
4332 PTR_DIFF(dend, pdata+4),
4333 STR_UNICODE);
4334 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4335 data_size = 4 + len;
4336 SIVAL(pdata,0,len);
4337 break;
4339 case SMB_FILE_ALLOCATION_INFORMATION:
4340 case SMB_QUERY_FILE_ALLOCATION_INFO:
4341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4342 data_size = 8;
4343 SOFF_T(pdata,0,allocation_size);
4344 break;
4346 case SMB_FILE_END_OF_FILE_INFORMATION:
4347 case SMB_QUERY_FILE_END_OF_FILEINFO:
4348 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4349 data_size = 8;
4350 SOFF_T(pdata,0,file_size);
4351 break;
4353 case SMB_QUERY_FILE_ALL_INFO:
4354 case SMB_FILE_ALL_INFORMATION:
4356 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4357 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4358 put_long_date_timespec(pdata,create_time_ts);
4359 put_long_date_timespec(pdata+8,atime_ts);
4360 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4361 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4362 SIVAL(pdata,32,mode);
4363 SIVAL(pdata,36,0); /* padding. */
4364 pdata += 40;
4365 SOFF_T(pdata,0,allocation_size);
4366 SOFF_T(pdata,8,file_size);
4367 SIVAL(pdata,16,nlink);
4368 SCVAL(pdata,20,delete_pending);
4369 SCVAL(pdata,21,(mode&aDIR)?1:0);
4370 SSVAL(pdata,22,0);
4371 pdata += 24;
4372 SIVAL(pdata,0,ea_size);
4373 pdata += 4; /* EA info */
4374 len = srvstr_push(dstart, req->flags2,
4375 pdata+4, dos_fname,
4376 PTR_DIFF(dend, pdata+4),
4377 STR_UNICODE);
4378 SIVAL(pdata,0,len);
4379 pdata += 4 + len;
4380 data_size = PTR_DIFF(pdata,(*ppdata));
4381 break;
4383 case SMB_FILE_INTERNAL_INFORMATION:
4384 /* This should be an index number - looks like
4385 dev/ino to me :-)
4387 I think this causes us to fail the IFSKIT
4388 BasicFileInformationTest. -tpot */
4390 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4391 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4392 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4393 data_size = 8;
4394 break;
4396 case SMB_FILE_ACCESS_INFORMATION:
4397 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4398 SIVAL(pdata,0,access_mask);
4399 data_size = 4;
4400 break;
4402 case SMB_FILE_NAME_INFORMATION:
4403 /* Pathname with leading '\'. */
4405 size_t byte_len;
4406 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4407 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4408 SIVAL(pdata,0,byte_len);
4409 data_size = 4 + byte_len;
4410 break;
4413 case SMB_FILE_DISPOSITION_INFORMATION:
4414 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4415 data_size = 1;
4416 SCVAL(pdata,0,delete_pending);
4417 break;
4419 case SMB_FILE_POSITION_INFORMATION:
4420 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4421 data_size = 8;
4422 SOFF_T(pdata,0,pos);
4423 break;
4425 case SMB_FILE_MODE_INFORMATION:
4426 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4427 SIVAL(pdata,0,mode);
4428 data_size = 4;
4429 break;
4431 case SMB_FILE_ALIGNMENT_INFORMATION:
4432 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4433 SIVAL(pdata,0,0); /* No alignment needed. */
4434 data_size = 4;
4435 break;
4438 * NT4 server just returns "invalid query" to this - if we try
4439 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4440 * want this. JRA.
4442 /* The first statement above is false - verified using Thursby
4443 * client against NT4 -- gcolley.
4445 case SMB_QUERY_FILE_STREAM_INFO:
4446 case SMB_FILE_STREAM_INFORMATION: {
4447 unsigned int num_streams;
4448 struct stream_struct *streams;
4449 NTSTATUS status;
4451 DEBUG(10,("call_trans2qfilepathinfo: "
4452 "SMB_FILE_STREAM_INFORMATION\n"));
4454 status = SMB_VFS_STREAMINFO(
4455 conn, fsp, fname, talloc_tos(),
4456 &num_streams, &streams);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 DEBUG(10, ("could not get stream info: %s\n",
4460 nt_errstr(status)));
4461 reply_nterror(req, status);
4462 return;
4465 status = marshall_stream_info(num_streams, streams,
4466 pdata, max_data_bytes,
4467 &data_size);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 DEBUG(10, ("marshall_stream_info failed: %s\n",
4471 nt_errstr(status)));
4472 reply_nterror(req, status);
4473 return;
4476 TALLOC_FREE(streams);
4478 break;
4480 case SMB_QUERY_COMPRESSION_INFO:
4481 case SMB_FILE_COMPRESSION_INFORMATION:
4482 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4483 SOFF_T(pdata,0,file_size);
4484 SIVAL(pdata,8,0); /* ??? */
4485 SIVAL(pdata,12,0); /* ??? */
4486 data_size = 16;
4487 break;
4489 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4490 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4491 put_long_date_timespec(pdata,create_time_ts);
4492 put_long_date_timespec(pdata+8,atime_ts);
4493 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4494 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4495 SOFF_T(pdata,32,allocation_size);
4496 SOFF_T(pdata,40,file_size);
4497 SIVAL(pdata,48,mode);
4498 SIVAL(pdata,52,0); /* ??? */
4499 data_size = 56;
4500 break;
4502 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4504 SIVAL(pdata,0,mode);
4505 SIVAL(pdata,4,0);
4506 data_size = 8;
4507 break;
4510 * CIFS UNIX Extensions.
4513 case SMB_QUERY_FILE_UNIX_BASIC:
4515 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4516 data_size = PTR_DIFF(pdata,(*ppdata));
4519 int i;
4520 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4522 for (i=0; i<100; i++)
4523 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4524 DEBUG(4,("\n"));
4527 break;
4529 case SMB_QUERY_FILE_UNIX_INFO2:
4531 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4532 data_size = PTR_DIFF(pdata,(*ppdata));
4535 int i;
4536 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4538 for (i=0; i<100; i++)
4539 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4540 DEBUG(4,("\n"));
4543 break;
4545 case SMB_QUERY_FILE_UNIX_LINK:
4547 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4549 if (!buffer) {
4550 reply_nterror(req, NT_STATUS_NO_MEMORY);
4551 return;
4554 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4555 #ifdef S_ISLNK
4556 if(!S_ISLNK(sbuf.st_mode)) {
4557 reply_unixerror(req, ERRSRV,
4558 ERRbadlink);
4559 return;
4561 #else
4562 reply_unixerror(req, ERRDOS, ERRbadlink);
4563 return;
4564 #endif
4565 len = SMB_VFS_READLINK(conn,fullpathname,
4566 buffer, PATH_MAX);
4567 if (len == -1) {
4568 reply_unixerror(req, ERRDOS,
4569 ERRnoaccess);
4570 return;
4572 buffer[len] = 0;
4573 len = srvstr_push(dstart, req->flags2,
4574 pdata, buffer,
4575 PTR_DIFF(dend, pdata),
4576 STR_TERMINATE);
4577 pdata += len;
4578 data_size = PTR_DIFF(pdata,(*ppdata));
4580 break;
4583 #if defined(HAVE_POSIX_ACLS)
4584 case SMB_QUERY_POSIX_ACL:
4586 SMB_ACL_T file_acl = NULL;
4587 SMB_ACL_T def_acl = NULL;
4588 uint16 num_file_acls = 0;
4589 uint16 num_def_acls = 0;
4591 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4592 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4593 } else {
4594 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4597 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4598 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4599 fname ));
4600 reply_nterror(
4601 req,
4602 NT_STATUS_NOT_IMPLEMENTED);
4603 return;
4606 if (S_ISDIR(sbuf.st_mode)) {
4607 if (fsp && fsp->is_directory) {
4608 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4609 } else {
4610 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4612 def_acl = free_empty_sys_acl(conn, def_acl);
4615 num_file_acls = count_acl_entries(conn, file_acl);
4616 num_def_acls = count_acl_entries(conn, def_acl);
4618 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4619 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4620 data_size,
4621 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4622 SMB_POSIX_ACL_HEADER_SIZE) ));
4623 if (file_acl) {
4624 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4626 if (def_acl) {
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4629 reply_nterror(
4630 req,
4631 NT_STATUS_BUFFER_TOO_SMALL);
4632 return;
4635 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4636 SSVAL(pdata,2,num_file_acls);
4637 SSVAL(pdata,4,num_def_acls);
4638 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4639 if (file_acl) {
4640 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4642 if (def_acl) {
4643 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4645 reply_nterror(
4646 req, NT_STATUS_INTERNAL_ERROR);
4647 return;
4649 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4650 if (file_acl) {
4651 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4653 if (def_acl) {
4654 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4656 reply_nterror(
4657 req,
4658 NT_STATUS_INTERNAL_ERROR);
4659 return;
4662 if (file_acl) {
4663 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4665 if (def_acl) {
4666 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4668 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4669 break;
4671 #endif
4674 case SMB_QUERY_POSIX_LOCK:
4676 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4677 SMB_BIG_UINT count;
4678 SMB_BIG_UINT offset;
4679 uint32 lock_pid;
4680 enum brl_type lock_type;
4682 if (total_data != POSIX_LOCK_DATA_SIZE) {
4683 reply_nterror(
4684 req, NT_STATUS_INVALID_PARAMETER);
4685 return;
4688 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4689 case POSIX_LOCK_TYPE_READ:
4690 lock_type = READ_LOCK;
4691 break;
4692 case POSIX_LOCK_TYPE_WRITE:
4693 lock_type = WRITE_LOCK;
4694 break;
4695 case POSIX_LOCK_TYPE_UNLOCK:
4696 default:
4697 /* There's no point in asking for an unlock... */
4698 reply_nterror(
4699 req,
4700 NT_STATUS_INVALID_PARAMETER);
4701 return;
4704 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4705 #if defined(HAVE_LONGLONG)
4706 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4707 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4708 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4709 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4710 #else /* HAVE_LONGLONG */
4711 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4712 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4713 #endif /* HAVE_LONGLONG */
4715 status = query_lock(fsp,
4716 &lock_pid,
4717 &count,
4718 &offset,
4719 &lock_type,
4720 POSIX_LOCK);
4722 if (ERROR_WAS_LOCK_DENIED(status)) {
4723 /* Here we need to report who has it locked... */
4724 data_size = POSIX_LOCK_DATA_SIZE;
4726 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4727 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4728 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4729 #if defined(HAVE_LONGLONG)
4730 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4731 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4732 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4733 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4734 #else /* HAVE_LONGLONG */
4735 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4736 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4737 #endif /* HAVE_LONGLONG */
4739 } else if (NT_STATUS_IS_OK(status)) {
4740 /* For success we just return a copy of what we sent
4741 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4742 data_size = POSIX_LOCK_DATA_SIZE;
4743 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4744 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4745 } else {
4746 reply_nterror(req, status);
4747 return;
4749 break;
4752 default:
4753 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4754 return;
4757 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4758 max_data_bytes);
4760 return;
4763 /****************************************************************************
4764 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4765 code.
4766 ****************************************************************************/
4768 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4769 connection_struct *conn,
4770 const char *oldname_in,
4771 const char *newname_in)
4773 SMB_STRUCT_STAT sbuf1, sbuf2;
4774 char *last_component_oldname = NULL;
4775 char *last_component_newname = NULL;
4776 char *oldname = NULL;
4777 char *newname = NULL;
4778 NTSTATUS status = NT_STATUS_OK;
4780 ZERO_STRUCT(sbuf1);
4781 ZERO_STRUCT(sbuf2);
4783 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4784 &last_component_oldname, &sbuf1);
4785 if (!NT_STATUS_IS_OK(status)) {
4786 return status;
4789 status = check_name(conn, oldname);
4790 if (!NT_STATUS_IS_OK(status)) {
4791 return status;
4794 /* source must already exist. */
4795 if (!VALID_STAT(sbuf1)) {
4796 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4799 status = unix_convert(ctx, conn, newname_in, False, &newname,
4800 &last_component_newname, &sbuf2);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 return status;
4805 status = check_name(conn, newname);
4806 if (!NT_STATUS_IS_OK(status)) {
4807 return status;
4810 /* Disallow if newname already exists. */
4811 if (VALID_STAT(sbuf2)) {
4812 return NT_STATUS_OBJECT_NAME_COLLISION;
4815 /* No links from a directory. */
4816 if (S_ISDIR(sbuf1.st_mode)) {
4817 return NT_STATUS_FILE_IS_A_DIRECTORY;
4820 /* Ensure this is within the share. */
4821 status = check_reduced_name(conn, oldname);
4822 if (!NT_STATUS_IS_OK(status)) {
4823 return status;
4826 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4828 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4829 status = map_nt_error_from_unix(errno);
4830 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4831 nt_errstr(status), newname, oldname));
4834 return status;
4837 /****************************************************************************
4838 Deal with setting the time from any of the setfilepathinfo functions.
4839 ****************************************************************************/
4841 NTSTATUS smb_set_file_time(connection_struct *conn,
4842 files_struct *fsp,
4843 const char *fname,
4844 const SMB_STRUCT_STAT *psbuf,
4845 struct timespec ts[2],
4846 bool setting_write_time)
4848 uint32 action =
4849 FILE_NOTIFY_CHANGE_LAST_ACCESS
4850 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4852 if (!VALID_STAT(*psbuf)) {
4853 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4856 /* get some defaults (no modifications) if any info is zero or -1. */
4857 if (null_timespec(ts[0])) {
4858 ts[0] = get_atimespec(psbuf);
4859 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4862 if (null_timespec(ts[1])) {
4863 ts[1] = get_mtimespec(psbuf);
4864 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4867 if (!setting_write_time) {
4868 /* ts[1] comes from change time, not write time. */
4869 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4872 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4873 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4876 * Try and set the times of this file if
4877 * they are different from the current values.
4881 struct timespec mts = get_mtimespec(psbuf);
4882 struct timespec ats = get_atimespec(psbuf);
4883 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4884 return NT_STATUS_OK;
4888 if (setting_write_time) {
4890 * This was a setfileinfo on an open file.
4891 * NT does this a lot. We also need to
4892 * set the time here, as it can be read by
4893 * FindFirst/FindNext and with the patch for bug #2045
4894 * in smbd/fileio.c it ensures that this timestamp is
4895 * kept sticky even after a write. We save the request
4896 * away and will set it on file close and after a write. JRA.
4899 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4900 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4902 if (fsp != NULL) {
4903 set_write_time_fsp(fsp, ts[1], true);
4904 } else {
4905 set_write_time_path(conn, fname,
4906 vfs_file_id_from_sbuf(conn, psbuf),
4907 ts[1], true);
4911 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4913 if(file_ntimes(conn, fname, ts)!=0) {
4914 return map_nt_error_from_unix(errno);
4916 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4918 return NT_STATUS_OK;
4921 /****************************************************************************
4922 Deal with setting the dosmode from any of the setfilepathinfo functions.
4923 ****************************************************************************/
4925 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4926 const char *fname,
4927 SMB_STRUCT_STAT *psbuf,
4928 uint32 dosmode)
4930 if (!VALID_STAT(*psbuf)) {
4931 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4934 if (dosmode) {
4935 if (S_ISDIR(psbuf->st_mode)) {
4936 dosmode |= aDIR;
4937 } else {
4938 dosmode &= ~aDIR;
4942 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4944 /* check the mode isn't different, before changing it */
4945 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4947 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4948 fname, (unsigned int)dosmode ));
4950 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4951 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4952 fname, strerror(errno)));
4953 return map_nt_error_from_unix(errno);
4956 return NT_STATUS_OK;
4959 /****************************************************************************
4960 Deal with setting the size from any of the setfilepathinfo functions.
4961 ****************************************************************************/
4963 static NTSTATUS smb_set_file_size(connection_struct *conn,
4964 struct smb_request *req,
4965 files_struct *fsp,
4966 const char *fname,
4967 SMB_STRUCT_STAT *psbuf,
4968 SMB_OFF_T size)
4970 NTSTATUS status = NT_STATUS_OK;
4971 files_struct *new_fsp = NULL;
4973 if (!VALID_STAT(*psbuf)) {
4974 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4977 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4979 if (size == get_file_size(*psbuf)) {
4980 return NT_STATUS_OK;
4983 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4984 fname, (double)size ));
4986 if (fsp && fsp->fh->fd != -1) {
4987 /* Handle based call. */
4988 if (vfs_set_filelen(fsp, size) == -1) {
4989 return map_nt_error_from_unix(errno);
4991 return NT_STATUS_OK;
4994 status = open_file_ntcreate(conn, req, fname, psbuf,
4995 FILE_WRITE_ATTRIBUTES,
4996 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4997 FILE_OPEN,
4999 FILE_ATTRIBUTE_NORMAL,
5000 FORCE_OPLOCK_BREAK_TO_NONE,
5001 NULL, &new_fsp);
5003 if (!NT_STATUS_IS_OK(status)) {
5004 /* NB. We check for open_was_deferred in the caller. */
5005 return status;
5008 if (vfs_set_filelen(new_fsp, size) == -1) {
5009 status = map_nt_error_from_unix(errno);
5010 close_file(new_fsp,NORMAL_CLOSE);
5011 return status;
5014 close_file(new_fsp,NORMAL_CLOSE);
5015 return NT_STATUS_OK;
5018 /****************************************************************************
5019 Deal with SMB_INFO_SET_EA.
5020 ****************************************************************************/
5022 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5023 const char *pdata,
5024 int total_data,
5025 files_struct *fsp,
5026 const char *fname)
5028 struct ea_list *ea_list = NULL;
5029 TALLOC_CTX *ctx = NULL;
5030 NTSTATUS status = NT_STATUS_OK;
5032 if (total_data < 10) {
5034 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5035 length. They seem to have no effect. Bug #3212. JRA */
5037 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5038 /* We're done. We only get EA info in this call. */
5039 return NT_STATUS_OK;
5042 return NT_STATUS_INVALID_PARAMETER;
5045 if (IVAL(pdata,0) > total_data) {
5046 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5047 IVAL(pdata,0), (unsigned int)total_data));
5048 return NT_STATUS_INVALID_PARAMETER;
5051 ctx = talloc_tos();
5052 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5053 if (!ea_list) {
5054 return NT_STATUS_INVALID_PARAMETER;
5056 status = set_ea(conn, fsp, fname, ea_list);
5058 return status;
5061 /****************************************************************************
5062 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5063 ****************************************************************************/
5065 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5066 const char *pdata,
5067 int total_data,
5068 files_struct *fsp,
5069 const char *fname,
5070 SMB_STRUCT_STAT *psbuf)
5072 NTSTATUS status = NT_STATUS_OK;
5073 bool delete_on_close;
5074 uint32 dosmode = 0;
5076 if (total_data < 1) {
5077 return NT_STATUS_INVALID_PARAMETER;
5080 if (fsp == NULL) {
5081 return NT_STATUS_INVALID_HANDLE;
5084 delete_on_close = (CVAL(pdata,0) ? True : False);
5085 dosmode = dos_mode(conn, fname, psbuf);
5087 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5088 "delete_on_close = %u\n",
5089 fsp->fsp_name,
5090 (unsigned int)dosmode,
5091 (unsigned int)delete_on_close ));
5093 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 return status;
5099 /* The set is across all open files on this dev/inode pair. */
5100 if (!set_delete_on_close(fsp, delete_on_close,
5101 &conn->server_info->utok)) {
5102 return NT_STATUS_ACCESS_DENIED;
5104 return NT_STATUS_OK;
5107 /****************************************************************************
5108 Deal with SMB_FILE_POSITION_INFORMATION.
5109 ****************************************************************************/
5111 static NTSTATUS smb_file_position_information(connection_struct *conn,
5112 const char *pdata,
5113 int total_data,
5114 files_struct *fsp)
5116 SMB_BIG_UINT position_information;
5118 if (total_data < 8) {
5119 return NT_STATUS_INVALID_PARAMETER;
5122 if (fsp == NULL) {
5123 /* Ignore on pathname based set. */
5124 return NT_STATUS_OK;
5127 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5128 #ifdef LARGE_SMB_OFF_T
5129 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5130 #else /* LARGE_SMB_OFF_T */
5131 if (IVAL(pdata,4) != 0) {
5132 /* more than 32 bits? */
5133 return NT_STATUS_INVALID_PARAMETER;
5135 #endif /* LARGE_SMB_OFF_T */
5137 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5138 fsp->fsp_name, (double)position_information ));
5139 fsp->fh->position_information = position_information;
5140 return NT_STATUS_OK;
5143 /****************************************************************************
5144 Deal with SMB_FILE_MODE_INFORMATION.
5145 ****************************************************************************/
5147 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5148 const char *pdata,
5149 int total_data)
5151 uint32 mode;
5153 if (total_data < 4) {
5154 return NT_STATUS_INVALID_PARAMETER;
5156 mode = IVAL(pdata,0);
5157 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5158 return NT_STATUS_INVALID_PARAMETER;
5160 return NT_STATUS_OK;
5163 /****************************************************************************
5164 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5165 ****************************************************************************/
5167 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5168 struct smb_request *req,
5169 const char *pdata,
5170 int total_data,
5171 const char *fname)
5173 char *link_target = NULL;
5174 const char *newname = fname;
5175 NTSTATUS status = NT_STATUS_OK;
5176 TALLOC_CTX *ctx = talloc_tos();
5178 /* Set a symbolic link. */
5179 /* Don't allow this if follow links is false. */
5181 if (total_data == 0) {
5182 return NT_STATUS_INVALID_PARAMETER;
5185 if (!lp_symlinks(SNUM(conn))) {
5186 return NT_STATUS_ACCESS_DENIED;
5189 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5190 total_data, STR_TERMINATE);
5192 if (!link_target) {
5193 return NT_STATUS_INVALID_PARAMETER;
5196 /* !widelinks forces the target path to be within the share. */
5197 /* This means we can interpret the target as a pathname. */
5198 if (!lp_widelinks(SNUM(conn))) {
5199 char *rel_name = NULL;
5200 char *last_dirp = NULL;
5202 if (*link_target == '/') {
5203 /* No absolute paths allowed. */
5204 return NT_STATUS_ACCESS_DENIED;
5206 rel_name = talloc_strdup(ctx,newname);
5207 if (!rel_name) {
5208 return NT_STATUS_NO_MEMORY;
5210 last_dirp = strrchr_m(rel_name, '/');
5211 if (last_dirp) {
5212 last_dirp[1] = '\0';
5213 } else {
5214 rel_name = talloc_strdup(ctx,"./");
5215 if (!rel_name) {
5216 return NT_STATUS_NO_MEMORY;
5219 rel_name = talloc_asprintf_append(rel_name,
5220 "%s",
5221 link_target);
5222 if (!rel_name) {
5223 return NT_STATUS_NO_MEMORY;
5226 status = check_name(conn, rel_name);
5227 if (!NT_STATUS_IS_OK(status)) {
5228 return status;
5232 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5233 newname, link_target ));
5235 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5236 return map_nt_error_from_unix(errno);
5239 return NT_STATUS_OK;
5242 /****************************************************************************
5243 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5244 ****************************************************************************/
5246 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5247 struct smb_request *req,
5248 const char *pdata, int total_data,
5249 const char *fname)
5251 char *oldname = NULL;
5252 TALLOC_CTX *ctx = talloc_tos();
5253 NTSTATUS status = NT_STATUS_OK;
5255 /* Set a hard link. */
5256 if (total_data == 0) {
5257 return NT_STATUS_INVALID_PARAMETER;
5260 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5261 total_data, STR_TERMINATE, &status);
5262 if (!NT_STATUS_IS_OK(status)) {
5263 return status;
5266 status = resolve_dfspath(ctx, conn,
5267 req->flags2 & FLAGS2_DFS_PATHNAMES,
5268 oldname,
5269 &oldname);
5270 if (!NT_STATUS_IS_OK(status)) {
5271 return status;
5274 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5275 fname, oldname));
5277 return hardlink_internals(ctx, conn, oldname, fname);
5280 /****************************************************************************
5281 Deal with SMB_FILE_RENAME_INFORMATION.
5282 ****************************************************************************/
5284 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5285 struct smb_request *req,
5286 const char *pdata,
5287 int total_data,
5288 files_struct *fsp,
5289 const char *fname)
5291 bool overwrite;
5292 uint32 root_fid;
5293 uint32 len;
5294 char *newname = NULL;
5295 char *base_name = NULL;
5296 bool dest_has_wcard = False;
5297 NTSTATUS status = NT_STATUS_OK;
5298 char *p;
5299 TALLOC_CTX *ctx = talloc_tos();
5301 if (total_data < 13) {
5302 return NT_STATUS_INVALID_PARAMETER;
5305 overwrite = (CVAL(pdata,0) ? True : False);
5306 root_fid = IVAL(pdata,4);
5307 len = IVAL(pdata,8);
5309 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5310 return NT_STATUS_INVALID_PARAMETER;
5313 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5314 len, 0, &status,
5315 &dest_has_wcard);
5316 if (!NT_STATUS_IS_OK(status)) {
5317 return status;
5320 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5321 newname));
5323 status = resolve_dfspath_wcard(ctx, conn,
5324 req->flags2 & FLAGS2_DFS_PATHNAMES,
5325 newname,
5326 &newname,
5327 &dest_has_wcard);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 return status;
5332 /* Check the new name has no '/' characters. */
5333 if (strchr_m(newname, '/')) {
5334 return NT_STATUS_NOT_SUPPORTED;
5337 /* Create the base directory. */
5338 base_name = talloc_strdup(ctx, fname);
5339 if (!base_name) {
5340 return NT_STATUS_NO_MEMORY;
5342 p = strrchr_m(base_name, '/');
5343 if (p) {
5344 p[1] = '\0';
5345 } else {
5346 base_name = talloc_strdup(ctx, "./");
5347 if (!base_name) {
5348 return NT_STATUS_NO_MEMORY;
5351 /* Append the new name. */
5352 base_name = talloc_asprintf_append(base_name,
5353 "%s",
5354 newname);
5355 if (!base_name) {
5356 return NT_STATUS_NO_MEMORY;
5359 if (fsp) {
5360 SMB_STRUCT_STAT sbuf;
5361 char *newname_last_component = NULL;
5363 ZERO_STRUCT(sbuf);
5365 status = unix_convert(ctx, conn, newname, False,
5366 &newname,
5367 &newname_last_component,
5368 &sbuf);
5370 /* If an error we expect this to be
5371 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5373 if (!NT_STATUS_IS_OK(status)
5374 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5375 status)) {
5376 return status;
5379 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5380 fsp->fnum, fsp->fsp_name, base_name ));
5381 status = rename_internals_fsp(conn, fsp, base_name,
5382 newname_last_component, 0,
5383 overwrite);
5384 } else {
5385 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5386 fname, base_name ));
5387 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5388 overwrite, False, dest_has_wcard,
5389 FILE_WRITE_ATTRIBUTES);
5392 return status;
5395 /****************************************************************************
5396 Deal with SMB_SET_POSIX_ACL.
5397 ****************************************************************************/
5399 #if defined(HAVE_POSIX_ACLS)
5400 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5401 const char *pdata,
5402 int total_data,
5403 files_struct *fsp,
5404 const char *fname,
5405 SMB_STRUCT_STAT *psbuf)
5407 uint16 posix_acl_version;
5408 uint16 num_file_acls;
5409 uint16 num_def_acls;
5410 bool valid_file_acls = True;
5411 bool valid_def_acls = True;
5413 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5414 return NT_STATUS_INVALID_PARAMETER;
5416 posix_acl_version = SVAL(pdata,0);
5417 num_file_acls = SVAL(pdata,2);
5418 num_def_acls = SVAL(pdata,4);
5420 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5421 valid_file_acls = False;
5422 num_file_acls = 0;
5425 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5426 valid_def_acls = False;
5427 num_def_acls = 0;
5430 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5431 return NT_STATUS_INVALID_PARAMETER;
5434 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5435 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5436 return NT_STATUS_INVALID_PARAMETER;
5439 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5440 fname ? fname : fsp->fsp_name,
5441 (unsigned int)num_file_acls,
5442 (unsigned int)num_def_acls));
5444 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5445 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5446 return map_nt_error_from_unix(errno);
5449 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5450 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5451 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5452 return map_nt_error_from_unix(errno);
5454 return NT_STATUS_OK;
5456 #endif
5458 /****************************************************************************
5459 Deal with SMB_SET_POSIX_LOCK.
5460 ****************************************************************************/
5462 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5463 const struct smb_request *req,
5464 const char *pdata,
5465 int total_data,
5466 files_struct *fsp)
5468 SMB_BIG_UINT count;
5469 SMB_BIG_UINT offset;
5470 uint32 lock_pid;
5471 bool blocking_lock = False;
5472 enum brl_type lock_type;
5474 NTSTATUS status = NT_STATUS_OK;
5476 if (fsp == NULL || fsp->fh->fd == -1) {
5477 return NT_STATUS_INVALID_HANDLE;
5480 if (total_data != POSIX_LOCK_DATA_SIZE) {
5481 return NT_STATUS_INVALID_PARAMETER;
5484 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5485 case POSIX_LOCK_TYPE_READ:
5486 lock_type = READ_LOCK;
5487 break;
5488 case POSIX_LOCK_TYPE_WRITE:
5489 /* Return the right POSIX-mappable error code for files opened read-only. */
5490 if (!fsp->can_write) {
5491 return NT_STATUS_INVALID_HANDLE;
5493 lock_type = WRITE_LOCK;
5494 break;
5495 case POSIX_LOCK_TYPE_UNLOCK:
5496 lock_type = UNLOCK_LOCK;
5497 break;
5498 default:
5499 return NT_STATUS_INVALID_PARAMETER;
5502 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5503 blocking_lock = False;
5504 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5505 blocking_lock = True;
5506 } else {
5507 return NT_STATUS_INVALID_PARAMETER;
5510 if (!lp_blocking_locks(SNUM(conn))) {
5511 blocking_lock = False;
5514 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5515 #if defined(HAVE_LONGLONG)
5516 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5517 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5518 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5519 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5520 #else /* HAVE_LONGLONG */
5521 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5522 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5523 #endif /* HAVE_LONGLONG */
5525 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5526 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5527 fsp->fsp_name,
5528 (unsigned int)lock_type,
5529 (unsigned int)lock_pid,
5530 (double)count,
5531 (double)offset ));
5533 if (lock_type == UNLOCK_LOCK) {
5534 status = do_unlock(smbd_messaging_context(),
5535 fsp,
5536 lock_pid,
5537 count,
5538 offset,
5539 POSIX_LOCK);
5540 } else {
5541 uint32 block_smbpid;
5543 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5544 fsp,
5545 lock_pid,
5546 count,
5547 offset,
5548 lock_type,
5549 POSIX_LOCK,
5550 blocking_lock,
5551 &status,
5552 &block_smbpid);
5554 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5556 * A blocking lock was requested. Package up
5557 * this smb into a queued request and push it
5558 * onto the blocking lock queue.
5560 if(push_blocking_lock_request(br_lck,
5561 req,
5562 fsp,
5563 -1, /* infinite timeout. */
5565 lock_pid,
5566 lock_type,
5567 POSIX_LOCK,
5568 offset,
5569 count,
5570 block_smbpid)) {
5571 TALLOC_FREE(br_lck);
5572 return status;
5575 TALLOC_FREE(br_lck);
5578 return status;
5581 /****************************************************************************
5582 Deal with SMB_INFO_STANDARD.
5583 ****************************************************************************/
5585 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5586 const char *pdata,
5587 int total_data,
5588 files_struct *fsp,
5589 const char *fname,
5590 const SMB_STRUCT_STAT *psbuf)
5592 struct timespec ts[2];
5594 if (total_data < 12) {
5595 return NT_STATUS_INVALID_PARAMETER;
5598 /* access time */
5599 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5600 /* write time */
5601 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5603 DEBUG(10,("smb_set_info_standard: file %s\n",
5604 fname ? fname : fsp->fsp_name ));
5606 return smb_set_file_time(conn,
5607 fsp,
5608 fname,
5609 psbuf,
5611 true);
5614 /****************************************************************************
5615 Deal with SMB_SET_FILE_BASIC_INFO.
5616 ****************************************************************************/
5618 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5619 const char *pdata,
5620 int total_data,
5621 files_struct *fsp,
5622 const char *fname,
5623 SMB_STRUCT_STAT *psbuf)
5625 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5626 struct timespec write_time;
5627 struct timespec changed_time;
5628 uint32 dosmode = 0;
5629 struct timespec ts[2];
5630 NTSTATUS status = NT_STATUS_OK;
5631 bool setting_write_time = true;
5633 if (total_data < 36) {
5634 return NT_STATUS_INVALID_PARAMETER;
5637 /* Set the attributes */
5638 dosmode = IVAL(pdata,32);
5639 status = smb_set_file_dosmode(conn,
5640 fname,
5641 psbuf,
5642 dosmode);
5643 if (!NT_STATUS_IS_OK(status)) {
5644 return status;
5647 /* Ignore create time at offset pdata. */
5649 /* access time */
5650 ts[0] = interpret_long_date(pdata+8);
5652 write_time = interpret_long_date(pdata+16);
5653 changed_time = interpret_long_date(pdata+24);
5655 /* mtime */
5656 ts[1] = timespec_min(&write_time, &changed_time);
5658 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5659 ts[1] = write_time;
5662 /* Prefer a defined time to an undefined one. */
5663 if (null_timespec(ts[1])) {
5664 if (null_timespec(write_time)) {
5665 ts[1] = changed_time;
5666 setting_write_time = false;
5667 } else {
5668 ts[1] = write_time;
5672 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5673 fname ? fname : fsp->fsp_name ));
5675 return smb_set_file_time(conn,
5676 fsp,
5677 fname,
5678 psbuf,
5680 setting_write_time);
5683 /****************************************************************************
5684 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5685 ****************************************************************************/
5687 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5688 struct smb_request *req,
5689 const char *pdata,
5690 int total_data,
5691 files_struct *fsp,
5692 const char *fname,
5693 SMB_STRUCT_STAT *psbuf)
5695 SMB_BIG_UINT allocation_size = 0;
5696 NTSTATUS status = NT_STATUS_OK;
5697 files_struct *new_fsp = NULL;
5699 if (!VALID_STAT(*psbuf)) {
5700 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5703 if (total_data < 8) {
5704 return NT_STATUS_INVALID_PARAMETER;
5707 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5708 #ifdef LARGE_SMB_OFF_T
5709 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5710 #else /* LARGE_SMB_OFF_T */
5711 if (IVAL(pdata,4) != 0) {
5712 /* more than 32 bits? */
5713 return NT_STATUS_INVALID_PARAMETER;
5715 #endif /* LARGE_SMB_OFF_T */
5717 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5718 fname, (double)allocation_size ));
5720 if (allocation_size) {
5721 allocation_size = smb_roundup(conn, allocation_size);
5724 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5725 fname, (double)allocation_size ));
5727 if (fsp && fsp->fh->fd != -1) {
5728 /* Open file handle. */
5729 /* Only change if needed. */
5730 if (allocation_size != get_file_size(*psbuf)) {
5731 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5732 return map_nt_error_from_unix(errno);
5735 /* But always update the time. */
5737 * This is equivalent to a write. Ensure it's seen immediately
5738 * if there are no pending writes.
5740 trigger_write_time_update(fsp);
5741 return NT_STATUS_OK;
5744 /* Pathname or stat or directory file. */
5746 status = open_file_ntcreate(conn, req, fname, psbuf,
5747 FILE_WRITE_DATA,
5748 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5749 FILE_OPEN,
5751 FILE_ATTRIBUTE_NORMAL,
5752 FORCE_OPLOCK_BREAK_TO_NONE,
5753 NULL, &new_fsp);
5755 if (!NT_STATUS_IS_OK(status)) {
5756 /* NB. We check for open_was_deferred in the caller. */
5757 return status;
5760 /* Only change if needed. */
5761 if (allocation_size != get_file_size(*psbuf)) {
5762 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5763 status = map_nt_error_from_unix(errno);
5764 close_file(new_fsp,NORMAL_CLOSE);
5765 return status;
5769 /* Changing the allocation size should set the last mod time. */
5771 * This is equivalent to a write. Ensure it's seen immediately
5772 * if there are no pending writes.
5774 trigger_write_time_update(new_fsp);
5776 close_file(new_fsp,NORMAL_CLOSE);
5777 return NT_STATUS_OK;
5780 /****************************************************************************
5781 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5782 ****************************************************************************/
5784 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5785 struct smb_request *req,
5786 const char *pdata,
5787 int total_data,
5788 files_struct *fsp,
5789 const char *fname,
5790 SMB_STRUCT_STAT *psbuf)
5792 SMB_OFF_T size;
5794 if (total_data < 8) {
5795 return NT_STATUS_INVALID_PARAMETER;
5798 size = IVAL(pdata,0);
5799 #ifdef LARGE_SMB_OFF_T
5800 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5801 #else /* LARGE_SMB_OFF_T */
5802 if (IVAL(pdata,4) != 0) {
5803 /* more than 32 bits? */
5804 return NT_STATUS_INVALID_PARAMETER;
5806 #endif /* LARGE_SMB_OFF_T */
5807 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5808 "file %s to %.0f\n", fname, (double)size ));
5810 return smb_set_file_size(conn, req,
5811 fsp,
5812 fname,
5813 psbuf,
5814 size);
5817 /****************************************************************************
5818 Allow a UNIX info mknod.
5819 ****************************************************************************/
5821 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5822 const char *pdata,
5823 int total_data,
5824 const char *fname,
5825 SMB_STRUCT_STAT *psbuf)
5827 uint32 file_type = IVAL(pdata,56);
5828 #if defined(HAVE_MAKEDEV)
5829 uint32 dev_major = IVAL(pdata,60);
5830 uint32 dev_minor = IVAL(pdata,68);
5831 #endif
5832 SMB_DEV_T dev = (SMB_DEV_T)0;
5833 uint32 raw_unixmode = IVAL(pdata,84);
5834 NTSTATUS status;
5835 mode_t unixmode;
5837 if (total_data < 100) {
5838 return NT_STATUS_INVALID_PARAMETER;
5841 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 return status;
5846 #if defined(HAVE_MAKEDEV)
5847 dev = makedev(dev_major, dev_minor);
5848 #endif
5850 switch (file_type) {
5851 #if defined(S_IFIFO)
5852 case UNIX_TYPE_FIFO:
5853 unixmode |= S_IFIFO;
5854 break;
5855 #endif
5856 #if defined(S_IFSOCK)
5857 case UNIX_TYPE_SOCKET:
5858 unixmode |= S_IFSOCK;
5859 break;
5860 #endif
5861 #if defined(S_IFCHR)
5862 case UNIX_TYPE_CHARDEV:
5863 unixmode |= S_IFCHR;
5864 break;
5865 #endif
5866 #if defined(S_IFBLK)
5867 case UNIX_TYPE_BLKDEV:
5868 unixmode |= S_IFBLK;
5869 break;
5870 #endif
5871 default:
5872 return NT_STATUS_INVALID_PARAMETER;
5875 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5876 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5878 /* Ok - do the mknod. */
5879 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5880 return map_nt_error_from_unix(errno);
5883 /* If any of the other "set" calls fail we
5884 * don't want to end up with a half-constructed mknod.
5887 if (lp_inherit_perms(SNUM(conn))) {
5888 inherit_access_posix_acl(
5889 conn, parent_dirname(fname),
5890 fname, unixmode);
5893 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5894 status = map_nt_error_from_unix(errno);
5895 SMB_VFS_UNLINK(conn,fname);
5896 return status;
5898 return NT_STATUS_OK;
5901 /****************************************************************************
5902 Deal with SMB_SET_FILE_UNIX_BASIC.
5903 ****************************************************************************/
5905 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5906 struct smb_request *req,
5907 const char *pdata,
5908 int total_data,
5909 files_struct *fsp,
5910 const char *fname,
5911 SMB_STRUCT_STAT *psbuf)
5913 struct timespec ts[2];
5914 uint32 raw_unixmode;
5915 mode_t unixmode;
5916 SMB_OFF_T size = 0;
5917 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5918 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5919 NTSTATUS status = NT_STATUS_OK;
5920 bool delete_on_fail = False;
5921 enum perm_type ptype;
5923 if (total_data < 100) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5928 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5929 size=IVAL(pdata,0); /* first 8 Bytes are size */
5930 #ifdef LARGE_SMB_OFF_T
5931 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5932 #else /* LARGE_SMB_OFF_T */
5933 if (IVAL(pdata,4) != 0) {
5934 /* more than 32 bits? */
5935 return NT_STATUS_INVALID_PARAMETER;
5937 #endif /* LARGE_SMB_OFF_T */
5940 ts[0] = interpret_long_date(pdata+24); /* access_time */
5941 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5942 set_owner = (uid_t)IVAL(pdata,40);
5943 set_grp = (gid_t)IVAL(pdata,48);
5944 raw_unixmode = IVAL(pdata,84);
5946 if (VALID_STAT(*psbuf)) {
5947 if (S_ISDIR(psbuf->st_mode)) {
5948 ptype = PERM_EXISTING_DIR;
5949 } else {
5950 ptype = PERM_EXISTING_FILE;
5952 } else {
5953 ptype = PERM_NEW_FILE;
5956 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5957 if (!NT_STATUS_IS_OK(status)) {
5958 return status;
5961 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5962 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5963 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5965 if (!VALID_STAT(*psbuf)) {
5967 * The only valid use of this is to create character and block
5968 * devices, and named pipes. This is deprecated (IMHO) and
5969 * a new info level should be used for mknod. JRA.
5972 status = smb_unix_mknod(conn,
5973 pdata,
5974 total_data,
5975 fname,
5976 psbuf);
5977 if (!NT_STATUS_IS_OK(status)) {
5978 return status;
5981 /* Ensure we don't try and change anything else. */
5982 raw_unixmode = SMB_MODE_NO_CHANGE;
5983 size = get_file_size(*psbuf);
5984 ts[0] = get_atimespec(psbuf);
5985 ts[1] = get_mtimespec(psbuf);
5987 * We continue here as we might want to change the
5988 * owner uid/gid.
5990 delete_on_fail = True;
5993 #if 1
5994 /* Horrible backwards compatibility hack as an old server bug
5995 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5996 * */
5998 if (!size) {
5999 size = get_file_size(*psbuf);
6001 #endif
6004 * Deal with the UNIX specific mode set.
6007 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6008 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6009 (unsigned int)unixmode, fname ));
6010 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6011 return map_nt_error_from_unix(errno);
6016 * Deal with the UNIX specific uid set.
6019 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6020 int ret;
6022 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6023 (unsigned int)set_owner, fname ));
6025 if (S_ISLNK(psbuf->st_mode)) {
6026 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6027 } else {
6028 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6031 if (ret != 0) {
6032 status = map_nt_error_from_unix(errno);
6033 if (delete_on_fail) {
6034 SMB_VFS_UNLINK(conn,fname);
6036 return status;
6041 * Deal with the UNIX specific gid set.
6044 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6045 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6046 (unsigned int)set_owner, fname ));
6047 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6048 status = map_nt_error_from_unix(errno);
6049 if (delete_on_fail) {
6050 SMB_VFS_UNLINK(conn,fname);
6052 return status;
6056 /* Deal with any size changes. */
6058 status = smb_set_file_size(conn, req,
6059 fsp,
6060 fname,
6061 psbuf,
6062 size);
6063 if (!NT_STATUS_IS_OK(status)) {
6064 return status;
6067 /* Deal with any time changes. */
6069 return smb_set_file_time(conn,
6070 fsp,
6071 fname,
6072 psbuf,
6074 true);
6077 /****************************************************************************
6078 Deal with SMB_SET_FILE_UNIX_INFO2.
6079 ****************************************************************************/
6081 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6082 struct smb_request *req,
6083 const char *pdata,
6084 int total_data,
6085 files_struct *fsp,
6086 const char *fname,
6087 SMB_STRUCT_STAT *psbuf)
6089 NTSTATUS status;
6090 uint32 smb_fflags;
6091 uint32 smb_fmask;
6093 if (total_data < 116) {
6094 return NT_STATUS_INVALID_PARAMETER;
6097 /* Start by setting all the fields that are common between UNIX_BASIC
6098 * and UNIX_INFO2.
6100 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6101 fsp, fname, psbuf);
6102 if (!NT_STATUS_IS_OK(status)) {
6103 return status;
6106 smb_fflags = IVAL(pdata, 108);
6107 smb_fmask = IVAL(pdata, 112);
6109 /* NB: We should only attempt to alter the file flags if the client
6110 * sends a non-zero mask.
6112 if (smb_fmask != 0) {
6113 int stat_fflags = 0;
6115 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6116 &stat_fflags)) {
6117 /* Client asked to alter a flag we don't understand. */
6118 return NT_STATUS_INVALID_PARAMETER;
6121 if (fsp && fsp->fh->fd != -1) {
6122 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6123 return NT_STATUS_NOT_SUPPORTED;
6124 } else {
6125 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6126 return map_nt_error_from_unix(errno);
6131 /* XXX: need to add support for changing the create_time here. You
6132 * can do this for paths on Darwin with setattrlist(2). The right way
6133 * to hook this up is probably by extending the VFS utimes interface.
6136 return NT_STATUS_OK;
6139 /****************************************************************************
6140 Create a directory with POSIX semantics.
6141 ****************************************************************************/
6143 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6144 struct smb_request *req,
6145 char **ppdata,
6146 int total_data,
6147 const char *fname,
6148 SMB_STRUCT_STAT *psbuf,
6149 int *pdata_return_size)
6151 NTSTATUS status = NT_STATUS_OK;
6152 uint32 raw_unixmode = 0;
6153 uint32 mod_unixmode = 0;
6154 mode_t unixmode = (mode_t)0;
6155 files_struct *fsp = NULL;
6156 uint16 info_level_return = 0;
6157 int info;
6158 char *pdata = *ppdata;
6160 if (total_data < 18) {
6161 return NT_STATUS_INVALID_PARAMETER;
6164 raw_unixmode = IVAL(pdata,8);
6165 /* Next 4 bytes are not yet defined. */
6167 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 return status;
6172 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6174 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6175 fname, (unsigned int)unixmode ));
6177 status = open_directory(conn, req,
6178 fname,
6179 psbuf,
6180 FILE_READ_ATTRIBUTES, /* Just a stat open */
6181 FILE_SHARE_NONE, /* Ignored for stat opens */
6182 FILE_CREATE,
6184 mod_unixmode,
6185 &info,
6186 &fsp);
6188 if (NT_STATUS_IS_OK(status)) {
6189 close_file(fsp, NORMAL_CLOSE);
6192 info_level_return = SVAL(pdata,16);
6194 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6195 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6196 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6197 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6198 } else {
6199 *pdata_return_size = 12;
6202 /* Realloc the data size */
6203 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6204 if (*ppdata == NULL) {
6205 *pdata_return_size = 0;
6206 return NT_STATUS_NO_MEMORY;
6208 pdata = *ppdata;
6210 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6211 SSVAL(pdata,2,0); /* No fnum. */
6212 SIVAL(pdata,4,info); /* Was directory created. */
6214 switch (info_level_return) {
6215 case SMB_QUERY_FILE_UNIX_BASIC:
6216 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6217 SSVAL(pdata,10,0); /* Padding. */
6218 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6219 break;
6220 case SMB_QUERY_FILE_UNIX_INFO2:
6221 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6222 SSVAL(pdata,10,0); /* Padding. */
6223 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6224 break;
6225 default:
6226 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6227 SSVAL(pdata,10,0); /* Padding. */
6228 break;
6231 return status;
6234 /****************************************************************************
6235 Open/Create a file with POSIX semantics.
6236 ****************************************************************************/
6238 static NTSTATUS smb_posix_open(connection_struct *conn,
6239 struct smb_request *req,
6240 char **ppdata,
6241 int total_data,
6242 const char *fname,
6243 SMB_STRUCT_STAT *psbuf,
6244 int *pdata_return_size)
6246 bool extended_oplock_granted = False;
6247 char *pdata = *ppdata;
6248 uint32 flags = 0;
6249 uint32 wire_open_mode = 0;
6250 uint32 raw_unixmode = 0;
6251 uint32 mod_unixmode = 0;
6252 uint32 create_disp = 0;
6253 uint32 access_mask = 0;
6254 uint32 create_options = 0;
6255 NTSTATUS status = NT_STATUS_OK;
6256 mode_t unixmode = (mode_t)0;
6257 files_struct *fsp = NULL;
6258 int oplock_request = 0;
6259 int info = 0;
6260 uint16 info_level_return = 0;
6262 if (total_data < 18) {
6263 return NT_STATUS_INVALID_PARAMETER;
6266 flags = IVAL(pdata,0);
6267 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6268 if (oplock_request) {
6269 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6272 wire_open_mode = IVAL(pdata,4);
6274 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6275 return smb_posix_mkdir(conn, req,
6276 ppdata,
6277 total_data,
6278 fname,
6279 psbuf,
6280 pdata_return_size);
6283 switch (wire_open_mode & SMB_ACCMODE) {
6284 case SMB_O_RDONLY:
6285 access_mask = FILE_READ_DATA;
6286 break;
6287 case SMB_O_WRONLY:
6288 access_mask = FILE_WRITE_DATA;
6289 break;
6290 case SMB_O_RDWR:
6291 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6292 break;
6293 default:
6294 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6295 (unsigned int)wire_open_mode ));
6296 return NT_STATUS_INVALID_PARAMETER;
6299 wire_open_mode &= ~SMB_ACCMODE;
6301 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6302 create_disp = FILE_CREATE;
6303 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6304 create_disp = FILE_OVERWRITE_IF;
6305 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6306 create_disp = FILE_OPEN_IF;
6307 } else {
6308 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6309 (unsigned int)wire_open_mode ));
6310 return NT_STATUS_INVALID_PARAMETER;
6313 raw_unixmode = IVAL(pdata,8);
6314 /* Next 4 bytes are not yet defined. */
6316 status = unix_perms_from_wire(conn,
6317 psbuf,
6318 raw_unixmode,
6319 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6320 &unixmode);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 return status;
6326 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6328 if (wire_open_mode & SMB_O_SYNC) {
6329 create_options |= FILE_WRITE_THROUGH;
6331 if (wire_open_mode & SMB_O_APPEND) {
6332 access_mask |= FILE_APPEND_DATA;
6334 if (wire_open_mode & SMB_O_DIRECT) {
6335 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6338 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6339 fname,
6340 (unsigned int)wire_open_mode,
6341 (unsigned int)unixmode ));
6343 status = open_file_ntcreate(conn, req,
6344 fname,
6345 psbuf,
6346 access_mask,
6347 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6348 create_disp,
6349 0, /* no create options yet. */
6350 mod_unixmode,
6351 oplock_request,
6352 &info,
6353 &fsp);
6355 if (!NT_STATUS_IS_OK(status)) {
6356 return status;
6359 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6360 extended_oplock_granted = True;
6363 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6364 extended_oplock_granted = True;
6367 info_level_return = SVAL(pdata,16);
6369 /* Allocate the correct return size. */
6371 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6372 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6373 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6374 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6375 } else {
6376 *pdata_return_size = 12;
6379 /* Realloc the data size */
6380 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6381 if (*ppdata == NULL) {
6382 close_file(fsp,ERROR_CLOSE);
6383 *pdata_return_size = 0;
6384 return NT_STATUS_NO_MEMORY;
6386 pdata = *ppdata;
6388 if (extended_oplock_granted) {
6389 if (flags & REQUEST_BATCH_OPLOCK) {
6390 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6391 } else {
6392 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6394 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6395 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6396 } else {
6397 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6400 SSVAL(pdata,2,fsp->fnum);
6401 SIVAL(pdata,4,info); /* Was file created etc. */
6403 switch (info_level_return) {
6404 case SMB_QUERY_FILE_UNIX_BASIC:
6405 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6406 SSVAL(pdata,10,0); /* padding. */
6407 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6408 break;
6409 case SMB_QUERY_FILE_UNIX_INFO2:
6410 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6411 SSVAL(pdata,10,0); /* padding. */
6412 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6413 break;
6414 default:
6415 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6416 SSVAL(pdata,10,0); /* padding. */
6417 break;
6419 return NT_STATUS_OK;
6422 /****************************************************************************
6423 Delete a file with POSIX semantics.
6424 ****************************************************************************/
6426 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6427 struct smb_request *req,
6428 const char *pdata,
6429 int total_data,
6430 const char *fname,
6431 SMB_STRUCT_STAT *psbuf)
6433 NTSTATUS status = NT_STATUS_OK;
6434 files_struct *fsp = NULL;
6435 uint16 flags = 0;
6436 char del = 1;
6437 int info = 0;
6438 int i;
6439 struct share_mode_lock *lck = NULL;
6441 if (total_data < 2) {
6442 return NT_STATUS_INVALID_PARAMETER;
6445 flags = SVAL(pdata,0);
6447 if (!VALID_STAT(*psbuf)) {
6448 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6451 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6452 !VALID_STAT_OF_DIR(*psbuf)) {
6453 return NT_STATUS_NOT_A_DIRECTORY;
6456 DEBUG(10,("smb_posix_unlink: %s %s\n",
6457 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6458 fname));
6460 if (VALID_STAT_OF_DIR(*psbuf)) {
6461 status = open_directory(conn, req,
6462 fname,
6463 psbuf,
6464 DELETE_ACCESS,
6465 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6466 FILE_OPEN,
6468 FILE_FLAG_POSIX_SEMANTICS|0777,
6469 &info,
6470 &fsp);
6471 } else {
6473 status = open_file_ntcreate(conn, req,
6474 fname,
6475 psbuf,
6476 DELETE_ACCESS,
6477 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6478 FILE_OPEN,
6480 FILE_FLAG_POSIX_SEMANTICS|0777,
6481 0, /* No oplock, but break existing ones. */
6482 &info,
6483 &fsp);
6486 if (!NT_STATUS_IS_OK(status)) {
6487 return status;
6491 * Don't lie to client. If we can't really delete due to
6492 * non-POSIX opens return SHARING_VIOLATION.
6495 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6496 NULL);
6497 if (lck == NULL) {
6498 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6499 "lock for file %s\n", fsp->fsp_name));
6500 close_file(fsp, NORMAL_CLOSE);
6501 return NT_STATUS_INVALID_PARAMETER;
6505 * See if others still have the file open. If this is the case, then
6506 * don't delete. If all opens are POSIX delete we can set the delete
6507 * on close disposition.
6509 for (i=0; i<lck->num_share_modes; i++) {
6510 struct share_mode_entry *e = &lck->share_modes[i];
6511 if (is_valid_share_mode_entry(e)) {
6512 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6513 continue;
6515 /* Fail with sharing violation. */
6516 close_file(fsp, NORMAL_CLOSE);
6517 TALLOC_FREE(lck);
6518 return NT_STATUS_SHARING_VIOLATION;
6523 * Set the delete on close.
6525 status = smb_set_file_disposition_info(conn,
6526 &del,
6528 fsp,
6529 fname,
6530 psbuf);
6532 if (!NT_STATUS_IS_OK(status)) {
6533 close_file(fsp, NORMAL_CLOSE);
6534 TALLOC_FREE(lck);
6535 return status;
6537 TALLOC_FREE(lck);
6538 return close_file(fsp, NORMAL_CLOSE);
6541 /****************************************************************************
6542 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6543 ****************************************************************************/
6545 static void call_trans2setfilepathinfo(connection_struct *conn,
6546 struct smb_request *req,
6547 unsigned int tran_call,
6548 char **pparams, int total_params,
6549 char **ppdata, int total_data,
6550 unsigned int max_data_bytes)
6552 char *params = *pparams;
6553 char *pdata = *ppdata;
6554 uint16 info_level;
6555 SMB_STRUCT_STAT sbuf;
6556 char *fname = NULL;
6557 files_struct *fsp = NULL;
6558 NTSTATUS status = NT_STATUS_OK;
6559 int data_return_size = 0;
6560 TALLOC_CTX *ctx = talloc_tos();
6562 if (!params) {
6563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6564 return;
6567 ZERO_STRUCT(sbuf);
6569 if (tran_call == TRANSACT2_SETFILEINFO) {
6570 if (total_params < 4) {
6571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6572 return;
6575 fsp = file_fsp(SVAL(params,0));
6576 /* Basic check for non-null fsp. */
6577 if (!check_fsp_open(conn, req, fsp)) {
6578 return;
6580 info_level = SVAL(params,2);
6582 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6583 if (!fname) {
6584 reply_nterror(req, NT_STATUS_NO_MEMORY);
6585 return;
6588 if(fsp->is_directory || fsp->fh->fd == -1) {
6590 * This is actually a SETFILEINFO on a directory
6591 * handle (returned from an NT SMB). NT5.0 seems
6592 * to do this call. JRA.
6594 if (INFO_LEVEL_IS_UNIX(info_level)) {
6595 /* Always do lstat for UNIX calls. */
6596 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6597 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6598 reply_unixerror(req,ERRDOS,ERRbadpath);
6599 return;
6601 } else {
6602 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6603 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6604 reply_unixerror(req,ERRDOS,ERRbadpath);
6605 return;
6608 } else if (fsp->print_file) {
6610 * Doing a DELETE_ON_CLOSE should cancel a print job.
6612 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6613 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6615 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6617 SSVAL(params,0,0);
6618 send_trans2_replies(conn, req, params, 2,
6619 *ppdata, 0,
6620 max_data_bytes);
6621 return;
6622 } else {
6623 reply_unixerror(req, ERRDOS, ERRbadpath);
6624 return;
6626 } else {
6628 * Original code - this is an open file.
6630 if (!check_fsp(conn, req, fsp)) {
6631 return;
6634 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6635 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6636 reply_unixerror(req, ERRDOS, ERRbadfid);
6637 return;
6640 } else {
6641 /* set path info */
6642 if (total_params < 7) {
6643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6644 return;
6647 info_level = SVAL(params,0);
6648 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6649 total_params - 6, STR_TERMINATE,
6650 &status);
6651 if (!NT_STATUS_IS_OK(status)) {
6652 reply_nterror(req, status);
6653 return;
6656 status = resolve_dfspath(ctx, conn,
6657 req->flags2 & FLAGS2_DFS_PATHNAMES,
6658 fname,
6659 &fname);
6660 if (!NT_STATUS_IS_OK(status)) {
6661 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6662 reply_botherror(req,
6663 NT_STATUS_PATH_NOT_COVERED,
6664 ERRSRV, ERRbadpath);
6665 return;
6667 reply_nterror(req, status);
6668 return;
6671 status = unix_convert(ctx, conn, fname, False,
6672 &fname, NULL, &sbuf);
6673 if (!NT_STATUS_IS_OK(status)) {
6674 reply_nterror(req, status);
6675 return;
6678 status = check_name(conn, fname);
6679 if (!NT_STATUS_IS_OK(status)) {
6680 reply_nterror(req, status);
6681 return;
6684 if (INFO_LEVEL_IS_UNIX(info_level)) {
6686 * For CIFS UNIX extensions the target name may not exist.
6689 /* Always do lstat for UNIX calls. */
6690 SMB_VFS_LSTAT(conn,fname,&sbuf);
6692 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6693 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6694 reply_unixerror(req, ERRDOS, ERRbadpath);
6695 return;
6699 if (!CAN_WRITE(conn)) {
6700 reply_doserror(req, ERRSRV, ERRaccess);
6701 return;
6704 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6705 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6706 return;
6709 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6710 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6712 /* Realloc the parameter size */
6713 *pparams = (char *)SMB_REALLOC(*pparams,2);
6714 if (*pparams == NULL) {
6715 reply_nterror(req, NT_STATUS_NO_MEMORY);
6716 return;
6718 params = *pparams;
6720 SSVAL(params,0,0);
6722 switch (info_level) {
6724 case SMB_INFO_STANDARD:
6726 status = smb_set_info_standard(conn,
6727 pdata,
6728 total_data,
6729 fsp,
6730 fname,
6731 &sbuf);
6732 break;
6735 case SMB_INFO_SET_EA:
6737 status = smb_info_set_ea(conn,
6738 pdata,
6739 total_data,
6740 fsp,
6741 fname);
6742 break;
6745 case SMB_SET_FILE_BASIC_INFO:
6746 case SMB_FILE_BASIC_INFORMATION:
6748 status = smb_set_file_basic_info(conn,
6749 pdata,
6750 total_data,
6751 fsp,
6752 fname,
6753 &sbuf);
6754 break;
6757 case SMB_FILE_ALLOCATION_INFORMATION:
6758 case SMB_SET_FILE_ALLOCATION_INFO:
6760 status = smb_set_file_allocation_info(conn, req,
6761 pdata,
6762 total_data,
6763 fsp,
6764 fname,
6765 &sbuf);
6766 break;
6769 case SMB_FILE_END_OF_FILE_INFORMATION:
6770 case SMB_SET_FILE_END_OF_FILE_INFO:
6772 status = smb_set_file_end_of_file_info(conn, req,
6773 pdata,
6774 total_data,
6775 fsp,
6776 fname,
6777 &sbuf);
6778 break;
6781 case SMB_FILE_DISPOSITION_INFORMATION:
6782 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6784 #if 0
6785 /* JRA - We used to just ignore this on a path ?
6786 * Shouldn't this be invalid level on a pathname
6787 * based call ?
6789 if (tran_call != TRANSACT2_SETFILEINFO) {
6790 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6792 #endif
6793 status = smb_set_file_disposition_info(conn,
6794 pdata,
6795 total_data,
6796 fsp,
6797 fname,
6798 &sbuf);
6799 break;
6802 case SMB_FILE_POSITION_INFORMATION:
6804 status = smb_file_position_information(conn,
6805 pdata,
6806 total_data,
6807 fsp);
6808 break;
6811 /* From tridge Samba4 :
6812 * MODE_INFORMATION in setfileinfo (I have no
6813 * idea what "mode information" on a file is - it takes a value of 0,
6814 * 2, 4 or 6. What could it be?).
6817 case SMB_FILE_MODE_INFORMATION:
6819 status = smb_file_mode_information(conn,
6820 pdata,
6821 total_data);
6822 break;
6826 * CIFS UNIX extensions.
6829 case SMB_SET_FILE_UNIX_BASIC:
6831 status = smb_set_file_unix_basic(conn, req,
6832 pdata,
6833 total_data,
6834 fsp,
6835 fname,
6836 &sbuf);
6837 break;
6840 case SMB_SET_FILE_UNIX_INFO2:
6842 status = smb_set_file_unix_info2(conn, req,
6843 pdata,
6844 total_data,
6845 fsp,
6846 fname,
6847 &sbuf);
6848 break;
6851 case SMB_SET_FILE_UNIX_LINK:
6853 if (tran_call != TRANSACT2_SETPATHINFO) {
6854 /* We must have a pathname for this. */
6855 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6856 return;
6858 status = smb_set_file_unix_link(conn, req, pdata,
6859 total_data, fname);
6860 break;
6863 case SMB_SET_FILE_UNIX_HLINK:
6865 if (tran_call != TRANSACT2_SETPATHINFO) {
6866 /* We must have a pathname for this. */
6867 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6868 return;
6870 status = smb_set_file_unix_hlink(conn, req,
6871 pdata, total_data,
6872 fname);
6873 break;
6876 case SMB_FILE_RENAME_INFORMATION:
6878 status = smb_file_rename_information(conn, req,
6879 pdata, total_data,
6880 fsp, fname);
6881 break;
6884 #if defined(HAVE_POSIX_ACLS)
6885 case SMB_SET_POSIX_ACL:
6887 status = smb_set_posix_acl(conn,
6888 pdata,
6889 total_data,
6890 fsp,
6891 fname,
6892 &sbuf);
6893 break;
6895 #endif
6897 case SMB_SET_POSIX_LOCK:
6899 if (tran_call != TRANSACT2_SETFILEINFO) {
6900 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6901 return;
6903 status = smb_set_posix_lock(conn, req,
6904 pdata, total_data, fsp);
6905 break;
6908 case SMB_POSIX_PATH_OPEN:
6910 if (tran_call != TRANSACT2_SETPATHINFO) {
6911 /* We must have a pathname for this. */
6912 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6913 return;
6916 status = smb_posix_open(conn, req,
6917 ppdata,
6918 total_data,
6919 fname,
6920 &sbuf,
6921 &data_return_size);
6922 break;
6925 case SMB_POSIX_PATH_UNLINK:
6927 if (tran_call != TRANSACT2_SETPATHINFO) {
6928 /* We must have a pathname for this. */
6929 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6930 return;
6933 status = smb_posix_unlink(conn, req,
6934 pdata,
6935 total_data,
6936 fname,
6937 &sbuf);
6938 break;
6941 default:
6942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6943 return;
6947 if (!NT_STATUS_IS_OK(status)) {
6948 if (open_was_deferred(req->mid)) {
6949 /* We have re-scheduled this call. */
6950 return;
6952 if (blocking_lock_was_deferred(req->mid)) {
6953 /* We have re-scheduled this call. */
6954 return;
6956 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6957 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6958 ERRSRV, ERRbadpath);
6959 return;
6961 if (info_level == SMB_POSIX_PATH_OPEN) {
6962 reply_openerror(req, status);
6963 return;
6966 reply_nterror(req, status);
6967 return;
6970 SSVAL(params,0,0);
6971 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6972 max_data_bytes);
6974 return;
6977 /****************************************************************************
6978 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6979 ****************************************************************************/
6981 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6982 char **pparams, int total_params,
6983 char **ppdata, int total_data,
6984 unsigned int max_data_bytes)
6986 char *params = *pparams;
6987 char *pdata = *ppdata;
6988 char *directory = NULL;
6989 SMB_STRUCT_STAT sbuf;
6990 NTSTATUS status = NT_STATUS_OK;
6991 struct ea_list *ea_list = NULL;
6992 TALLOC_CTX *ctx = talloc_tos();
6994 if (!CAN_WRITE(conn)) {
6995 reply_doserror(req, ERRSRV, ERRaccess);
6996 return;
6999 if (total_params < 5) {
7000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7001 return;
7004 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7005 total_params - 4, STR_TERMINATE,
7006 &status);
7007 if (!NT_STATUS_IS_OK(status)) {
7008 reply_nterror(req, status);
7009 return;
7012 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7014 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7015 if (!NT_STATUS_IS_OK(status)) {
7016 reply_nterror(req, status);
7017 return;
7020 status = check_name(conn, directory);
7021 if (!NT_STATUS_IS_OK(status)) {
7022 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7023 reply_nterror(req, status);
7024 return;
7027 /* Any data in this call is an EA list. */
7028 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7029 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7030 return;
7034 * OS/2 workplace shell seems to send SET_EA requests of "null"
7035 * length (4 bytes containing IVAL 4).
7036 * They seem to have no effect. Bug #3212. JRA.
7039 if (total_data != 4) {
7040 if (total_data < 10) {
7041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7042 return;
7045 if (IVAL(pdata,0) > total_data) {
7046 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7047 IVAL(pdata,0), (unsigned int)total_data));
7048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7049 return;
7052 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7053 total_data - 4);
7054 if (!ea_list) {
7055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7056 return;
7058 } else if (IVAL(pdata,0) != 4) {
7059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7060 return;
7063 status = create_directory(conn, req, directory);
7065 if (!NT_STATUS_IS_OK(status)) {
7066 reply_nterror(req, status);
7067 return;
7070 /* Try and set any given EA. */
7071 if (ea_list) {
7072 status = set_ea(conn, NULL, directory, ea_list);
7073 if (!NT_STATUS_IS_OK(status)) {
7074 reply_nterror(req, status);
7075 return;
7079 /* Realloc the parameter and data sizes */
7080 *pparams = (char *)SMB_REALLOC(*pparams,2);
7081 if(*pparams == NULL) {
7082 reply_nterror(req, NT_STATUS_NO_MEMORY);
7083 return;
7085 params = *pparams;
7087 SSVAL(params,0,0);
7089 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7091 return;
7094 /****************************************************************************
7095 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7096 We don't actually do this - we just send a null response.
7097 ****************************************************************************/
7099 static void call_trans2findnotifyfirst(connection_struct *conn,
7100 struct smb_request *req,
7101 char **pparams, int total_params,
7102 char **ppdata, int total_data,
7103 unsigned int max_data_bytes)
7105 static uint16 fnf_handle = 257;
7106 char *params = *pparams;
7107 uint16 info_level;
7109 if (total_params < 6) {
7110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7111 return;
7114 info_level = SVAL(params,4);
7115 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7117 switch (info_level) {
7118 case 1:
7119 case 2:
7120 break;
7121 default:
7122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7123 return;
7126 /* Realloc the parameter and data sizes */
7127 *pparams = (char *)SMB_REALLOC(*pparams,6);
7128 if (*pparams == NULL) {
7129 reply_nterror(req, NT_STATUS_NO_MEMORY);
7130 return;
7132 params = *pparams;
7134 SSVAL(params,0,fnf_handle);
7135 SSVAL(params,2,0); /* No changes */
7136 SSVAL(params,4,0); /* No EA errors */
7138 fnf_handle++;
7140 if(fnf_handle == 0)
7141 fnf_handle = 257;
7143 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7145 return;
7148 /****************************************************************************
7149 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7150 changes). Currently this does nothing.
7151 ****************************************************************************/
7153 static void call_trans2findnotifynext(connection_struct *conn,
7154 struct smb_request *req,
7155 char **pparams, int total_params,
7156 char **ppdata, int total_data,
7157 unsigned int max_data_bytes)
7159 char *params = *pparams;
7161 DEBUG(3,("call_trans2findnotifynext\n"));
7163 /* Realloc the parameter and data sizes */
7164 *pparams = (char *)SMB_REALLOC(*pparams,4);
7165 if (*pparams == NULL) {
7166 reply_nterror(req, NT_STATUS_NO_MEMORY);
7167 return;
7169 params = *pparams;
7171 SSVAL(params,0,0); /* No changes */
7172 SSVAL(params,2,0); /* No EA errors */
7174 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7176 return;
7179 /****************************************************************************
7180 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7181 ****************************************************************************/
7183 static void call_trans2getdfsreferral(connection_struct *conn,
7184 struct smb_request *req,
7185 char **pparams, int total_params,
7186 char **ppdata, int total_data,
7187 unsigned int max_data_bytes)
7189 char *params = *pparams;
7190 char *pathname = NULL;
7191 int reply_size = 0;
7192 int max_referral_level;
7193 NTSTATUS status = NT_STATUS_OK;
7194 TALLOC_CTX *ctx = talloc_tos();
7196 DEBUG(10,("call_trans2getdfsreferral\n"));
7198 if (total_params < 3) {
7199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7200 return;
7203 max_referral_level = SVAL(params,0);
7205 if(!lp_host_msdfs()) {
7206 reply_doserror(req, ERRDOS, ERRbadfunc);
7207 return;
7210 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7211 total_params - 2, STR_TERMINATE);
7212 if (!pathname) {
7213 reply_nterror(req, NT_STATUS_NOT_FOUND);
7214 return;
7216 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7217 ppdata,&status)) < 0) {
7218 reply_nterror(req, status);
7219 return;
7222 SSVAL(req->inbuf, smb_flg2,
7223 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7224 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7226 return;
7229 #define LMCAT_SPL 0x53
7230 #define LMFUNC_GETJOBID 0x60
7232 /****************************************************************************
7233 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7234 ****************************************************************************/
7236 static void call_trans2ioctl(connection_struct *conn,
7237 struct smb_request *req,
7238 char **pparams, int total_params,
7239 char **ppdata, int total_data,
7240 unsigned int max_data_bytes)
7242 char *pdata = *ppdata;
7243 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7245 /* check for an invalid fid before proceeding */
7247 if (!fsp) {
7248 reply_doserror(req, ERRDOS, ERRbadfid);
7249 return;
7252 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7253 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7254 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7255 if (*ppdata == NULL) {
7256 reply_nterror(req, NT_STATUS_NO_MEMORY);
7257 return;
7259 pdata = *ppdata;
7261 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7262 CAN ACCEPT THIS IN UNICODE. JRA. */
7264 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7265 srvstr_push(pdata, req->flags2, pdata + 2,
7266 global_myname(), 15,
7267 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7268 srvstr_push(pdata, req->flags2, pdata+18,
7269 lp_servicename(SNUM(conn)), 13,
7270 STR_ASCII|STR_TERMINATE); /* Service name */
7271 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7272 max_data_bytes);
7273 return;
7276 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7277 reply_doserror(req, ERRSRV, ERRerror);
7280 /****************************************************************************
7281 Reply to a SMBfindclose (stop trans2 directory search).
7282 ****************************************************************************/
7284 void reply_findclose(struct smb_request *req)
7286 int dptr_num;
7288 START_PROFILE(SMBfindclose);
7290 if (req->wct < 1) {
7291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7292 END_PROFILE(SMBfindclose);
7293 return;
7296 dptr_num = SVALS(req->inbuf,smb_vwv0);
7298 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7300 dptr_close(&dptr_num);
7302 reply_outbuf(req, 0, 0);
7304 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7306 END_PROFILE(SMBfindclose);
7307 return;
7310 /****************************************************************************
7311 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7312 ****************************************************************************/
7314 void reply_findnclose(struct smb_request *req)
7316 int dptr_num;
7318 START_PROFILE(SMBfindnclose);
7320 if (req->wct < 1) {
7321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7322 END_PROFILE(SMBfindnclose);
7323 return;
7326 dptr_num = SVAL(req->inbuf,smb_vwv0);
7328 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7330 /* We never give out valid handles for a
7331 findnotifyfirst - so any dptr_num is ok here.
7332 Just ignore it. */
7334 reply_outbuf(req, 0, 0);
7336 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7338 END_PROFILE(SMBfindnclose);
7339 return;
7342 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7343 struct trans_state *state)
7345 if (Protocol >= PROTOCOL_NT1) {
7346 req->flags2 |= 0x40; /* IS_LONG_NAME */
7347 SSVAL(req->inbuf,smb_flg2,req->flags2);
7350 if (conn->encrypt_level == Required && !req->encrypted) {
7351 if (state->call != TRANSACT2_QFSINFO &&
7352 state->call != TRANSACT2_SETFSINFO) {
7353 DEBUG(0,("handle_trans2: encryption required "
7354 "with call 0x%x\n",
7355 (unsigned int)state->call));
7356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7357 return;
7361 /* Now we must call the relevant TRANS2 function */
7362 switch(state->call) {
7363 case TRANSACT2_OPEN:
7365 START_PROFILE(Trans2_open);
7366 call_trans2open(conn, req,
7367 &state->param, state->total_param,
7368 &state->data, state->total_data,
7369 state->max_data_return);
7370 END_PROFILE(Trans2_open);
7371 break;
7374 case TRANSACT2_FINDFIRST:
7376 START_PROFILE(Trans2_findfirst);
7377 call_trans2findfirst(conn, req,
7378 &state->param, state->total_param,
7379 &state->data, state->total_data,
7380 state->max_data_return);
7381 END_PROFILE(Trans2_findfirst);
7382 break;
7385 case TRANSACT2_FINDNEXT:
7387 START_PROFILE(Trans2_findnext);
7388 call_trans2findnext(conn, req,
7389 &state->param, state->total_param,
7390 &state->data, state->total_data,
7391 state->max_data_return);
7392 END_PROFILE(Trans2_findnext);
7393 break;
7396 case TRANSACT2_QFSINFO:
7398 START_PROFILE(Trans2_qfsinfo);
7399 call_trans2qfsinfo(conn, req,
7400 &state->param, state->total_param,
7401 &state->data, state->total_data,
7402 state->max_data_return);
7403 END_PROFILE(Trans2_qfsinfo);
7404 break;
7407 case TRANSACT2_SETFSINFO:
7409 START_PROFILE(Trans2_setfsinfo);
7410 call_trans2setfsinfo(conn, req,
7411 &state->param, state->total_param,
7412 &state->data, state->total_data,
7413 state->max_data_return);
7414 END_PROFILE(Trans2_setfsinfo);
7415 break;
7418 case TRANSACT2_QPATHINFO:
7419 case TRANSACT2_QFILEINFO:
7421 START_PROFILE(Trans2_qpathinfo);
7422 call_trans2qfilepathinfo(conn, req, state->call,
7423 &state->param, state->total_param,
7424 &state->data, state->total_data,
7425 state->max_data_return);
7426 END_PROFILE(Trans2_qpathinfo);
7427 break;
7430 case TRANSACT2_SETPATHINFO:
7431 case TRANSACT2_SETFILEINFO:
7433 START_PROFILE(Trans2_setpathinfo);
7434 call_trans2setfilepathinfo(conn, req, state->call,
7435 &state->param, state->total_param,
7436 &state->data, state->total_data,
7437 state->max_data_return);
7438 END_PROFILE(Trans2_setpathinfo);
7439 break;
7442 case TRANSACT2_FINDNOTIFYFIRST:
7444 START_PROFILE(Trans2_findnotifyfirst);
7445 call_trans2findnotifyfirst(conn, req,
7446 &state->param, state->total_param,
7447 &state->data, state->total_data,
7448 state->max_data_return);
7449 END_PROFILE(Trans2_findnotifyfirst);
7450 break;
7453 case TRANSACT2_FINDNOTIFYNEXT:
7455 START_PROFILE(Trans2_findnotifynext);
7456 call_trans2findnotifynext(conn, req,
7457 &state->param, state->total_param,
7458 &state->data, state->total_data,
7459 state->max_data_return);
7460 END_PROFILE(Trans2_findnotifynext);
7461 break;
7464 case TRANSACT2_MKDIR:
7466 START_PROFILE(Trans2_mkdir);
7467 call_trans2mkdir(conn, req,
7468 &state->param, state->total_param,
7469 &state->data, state->total_data,
7470 state->max_data_return);
7471 END_PROFILE(Trans2_mkdir);
7472 break;
7475 case TRANSACT2_GET_DFS_REFERRAL:
7477 START_PROFILE(Trans2_get_dfs_referral);
7478 call_trans2getdfsreferral(conn, req,
7479 &state->param, state->total_param,
7480 &state->data, state->total_data,
7481 state->max_data_return);
7482 END_PROFILE(Trans2_get_dfs_referral);
7483 break;
7486 case TRANSACT2_IOCTL:
7488 START_PROFILE(Trans2_ioctl);
7489 call_trans2ioctl(conn, req,
7490 &state->param, state->total_param,
7491 &state->data, state->total_data,
7492 state->max_data_return);
7493 END_PROFILE(Trans2_ioctl);
7494 break;
7497 default:
7498 /* Error in request */
7499 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7500 reply_doserror(req, ERRSRV,ERRerror);
7504 /****************************************************************************
7505 Reply to a SMBtrans2.
7506 ****************************************************************************/
7508 void reply_trans2(struct smb_request *req)
7510 connection_struct *conn = req->conn;
7511 unsigned int dsoff;
7512 unsigned int dscnt;
7513 unsigned int psoff;
7514 unsigned int pscnt;
7515 unsigned int tran_call;
7516 unsigned int size;
7517 unsigned int av_size;
7518 struct trans_state *state;
7519 NTSTATUS result;
7521 START_PROFILE(SMBtrans2);
7523 if (req->wct < 14) {
7524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7525 END_PROFILE(SMBtrans2);
7526 return;
7529 dsoff = SVAL(req->inbuf, smb_dsoff);
7530 dscnt = SVAL(req->inbuf, smb_dscnt);
7531 psoff = SVAL(req->inbuf, smb_psoff);
7532 pscnt = SVAL(req->inbuf, smb_pscnt);
7533 tran_call = SVAL(req->inbuf, smb_setup0);
7534 size = smb_len(req->inbuf) + 4;
7535 av_size = smb_len(req->inbuf);
7537 result = allow_new_trans(conn->pending_trans, req->mid);
7538 if (!NT_STATUS_IS_OK(result)) {
7539 DEBUG(2, ("Got invalid trans2 request: %s\n",
7540 nt_errstr(result)));
7541 reply_nterror(req, result);
7542 END_PROFILE(SMBtrans2);
7543 return;
7546 if (IS_IPC(conn)) {
7547 switch (tran_call) {
7548 /* List the allowed trans2 calls on IPC$ */
7549 case TRANSACT2_OPEN:
7550 case TRANSACT2_GET_DFS_REFERRAL:
7551 case TRANSACT2_QFILEINFO:
7552 case TRANSACT2_QFSINFO:
7553 case TRANSACT2_SETFSINFO:
7554 break;
7555 default:
7556 reply_doserror(req, ERRSRV, ERRaccess);
7557 END_PROFILE(SMBtrans2);
7558 return;
7562 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7563 DEBUG(0, ("talloc failed\n"));
7564 reply_nterror(req, NT_STATUS_NO_MEMORY);
7565 END_PROFILE(SMBtrans2);
7566 return;
7569 state->cmd = SMBtrans2;
7571 state->mid = req->mid;
7572 state->vuid = req->vuid;
7573 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7574 state->setup = NULL;
7575 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7576 state->param = NULL;
7577 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7578 state->data = NULL;
7579 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7580 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7581 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7582 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7583 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7585 state->call = tran_call;
7587 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7588 is so as a sanity check */
7589 if (state->setup_count != 1) {
7591 * Need to have rc=0 for ioctl to get job id for OS/2.
7592 * Network printing will fail if function is not successful.
7593 * Similar function in reply.c will be used if protocol
7594 * is LANMAN1.0 instead of LM1.2X002.
7595 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7596 * outbuf doesn't have to be set(only job id is used).
7598 if ( (state->setup_count == 4)
7599 && (tran_call == TRANSACT2_IOCTL)
7600 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7601 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7602 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7603 } else {
7604 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7605 DEBUG(2,("Transaction is %d\n",tran_call));
7606 TALLOC_FREE(state);
7607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7608 END_PROFILE(SMBtrans2);
7609 return;
7613 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7614 goto bad_param;
7616 if (state->total_data) {
7617 /* Can't use talloc here, the core routines do realloc on the
7618 * params and data. */
7619 state->data = (char *)SMB_MALLOC(state->total_data);
7620 if (state->data == NULL) {
7621 DEBUG(0,("reply_trans2: data malloc fail for %u "
7622 "bytes !\n", (unsigned int)state->total_data));
7623 TALLOC_FREE(state);
7624 reply_nterror(req, NT_STATUS_NO_MEMORY);
7625 END_PROFILE(SMBtrans2);
7626 return;
7629 if (dscnt > state->total_data ||
7630 dsoff+dscnt < dsoff) {
7631 goto bad_param;
7634 if (dsoff > av_size ||
7635 dscnt > av_size ||
7636 dsoff+dscnt > av_size) {
7637 goto bad_param;
7640 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7643 if (state->total_param) {
7644 /* Can't use talloc here, the core routines do realloc on the
7645 * params and data. */
7646 state->param = (char *)SMB_MALLOC(state->total_param);
7647 if (state->param == NULL) {
7648 DEBUG(0,("reply_trans: param malloc fail for %u "
7649 "bytes !\n", (unsigned int)state->total_param));
7650 SAFE_FREE(state->data);
7651 TALLOC_FREE(state);
7652 reply_nterror(req, NT_STATUS_NO_MEMORY);
7653 END_PROFILE(SMBtrans2);
7654 return;
7657 if (pscnt > state->total_param ||
7658 psoff+pscnt < psoff) {
7659 goto bad_param;
7662 if (psoff > av_size ||
7663 pscnt > av_size ||
7664 psoff+pscnt > av_size) {
7665 goto bad_param;
7668 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7671 state->received_data = dscnt;
7672 state->received_param = pscnt;
7674 if ((state->received_param == state->total_param) &&
7675 (state->received_data == state->total_data)) {
7677 handle_trans2(conn, req, state);
7679 SAFE_FREE(state->data);
7680 SAFE_FREE(state->param);
7681 TALLOC_FREE(state);
7682 END_PROFILE(SMBtrans2);
7683 return;
7686 DLIST_ADD(conn->pending_trans, state);
7688 /* We need to send an interim response then receive the rest
7689 of the parameter/data bytes */
7690 reply_outbuf(req, 0, 0);
7691 show_msg((char *)req->outbuf);
7692 END_PROFILE(SMBtrans2);
7693 return;
7695 bad_param:
7697 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7698 SAFE_FREE(state->data);
7699 SAFE_FREE(state->param);
7700 TALLOC_FREE(state);
7701 END_PROFILE(SMBtrans2);
7702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7706 /****************************************************************************
7707 Reply to a SMBtranss2
7708 ****************************************************************************/
7710 void reply_transs2(struct smb_request *req)
7712 connection_struct *conn = req->conn;
7713 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7714 struct trans_state *state;
7715 unsigned int size;
7716 unsigned int av_size;
7718 START_PROFILE(SMBtranss2);
7720 show_msg((char *)req->inbuf);
7722 if (req->wct < 8) {
7723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7724 END_PROFILE(SMBtranss2);
7725 return;
7728 size = smb_len(req->inbuf)+4;
7729 av_size = smb_len(req->inbuf);
7731 for (state = conn->pending_trans; state != NULL;
7732 state = state->next) {
7733 if (state->mid == req->mid) {
7734 break;
7738 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7740 END_PROFILE(SMBtranss2);
7741 return;
7744 /* Revise state->total_param and state->total_data in case they have
7745 changed downwards */
7747 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7748 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7749 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7750 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7752 pcnt = SVAL(req->inbuf, smb_spscnt);
7753 poff = SVAL(req->inbuf, smb_spsoff);
7754 pdisp = SVAL(req->inbuf, smb_spsdisp);
7756 dcnt = SVAL(req->inbuf, smb_sdscnt);
7757 doff = SVAL(req->inbuf, smb_sdsoff);
7758 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7760 state->received_param += pcnt;
7761 state->received_data += dcnt;
7763 if ((state->received_data > state->total_data) ||
7764 (state->received_param > state->total_param))
7765 goto bad_param;
7767 if (pcnt) {
7768 if (pdisp > state->total_param ||
7769 pcnt > state->total_param ||
7770 pdisp+pcnt > state->total_param ||
7771 pdisp+pcnt < pdisp) {
7772 goto bad_param;
7775 if (poff > av_size ||
7776 pcnt > av_size ||
7777 poff+pcnt > av_size ||
7778 poff+pcnt < poff) {
7779 goto bad_param;
7782 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7783 pcnt);
7786 if (dcnt) {
7787 if (ddisp > state->total_data ||
7788 dcnt > state->total_data ||
7789 ddisp+dcnt > state->total_data ||
7790 ddisp+dcnt < ddisp) {
7791 goto bad_param;
7794 if (ddisp > av_size ||
7795 dcnt > av_size ||
7796 ddisp+dcnt > av_size ||
7797 ddisp+dcnt < ddisp) {
7798 goto bad_param;
7801 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7802 dcnt);
7805 if ((state->received_param < state->total_param) ||
7806 (state->received_data < state->total_data)) {
7807 END_PROFILE(SMBtranss2);
7808 return;
7812 * construct_reply_common will copy smb_com from inbuf to
7813 * outbuf. SMBtranss2 is wrong here.
7815 SCVAL(req->inbuf,smb_com,SMBtrans2);
7817 handle_trans2(conn, req, state);
7819 DLIST_REMOVE(conn->pending_trans, state);
7820 SAFE_FREE(state->data);
7821 SAFE_FREE(state->param);
7822 TALLOC_FREE(state);
7824 END_PROFILE(SMBtranss2);
7825 return;
7827 bad_param:
7829 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7830 DLIST_REMOVE(conn->pending_trans, state);
7831 SAFE_FREE(state->data);
7832 SAFE_FREE(state->param);
7833 TALLOC_FREE(state);
7834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7835 END_PROFILE(SMBtranss2);
7836 return;