r23727: Explicitly pass down FLAGS2 to srvstr_get_path.
[Samba.git] / source / smbd / trans2.c
blob15394cd8638fdec52f0ac7f15a0603dc79cbbfa2
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
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 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 2 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, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "includes.h"
29 extern int max_send;
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
62 return val;
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
67 account sparse files.
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 SMB_BIG_UINT ret;
74 if(S_ISDIR(sbuf->st_mode)) {
75 return 0;
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 #else
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 #endif
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
97 NULL
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
106 int i;
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 return True;
112 return False;
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
124 char *val = NULL;
125 ssize_t sizeret;
127 again:
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
130 if (!val) {
131 return False;
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 } else {
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
141 attr_size = 65536;
142 goto again;
145 if (sizeret == -1) {
146 return False;
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, (uint8 *)val, sizeret);
152 pea->flags = 0;
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
155 } else {
156 pea->name = ea_name;
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
160 return True;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
172 char *ea_namelist;
173 char *p;
174 ssize_t sizeret;
175 int i;
176 struct ea_list *ea_list_head = NULL;
178 *pea_total_len = 0;
180 if (!lp_ea_support(SNUM(conn))) {
181 return NULL;
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
187 if (!ea_namelist) {
188 return NULL;
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 } else {
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
199 } else {
200 break;
204 if (sizeret == -1)
205 return NULL;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 if (sizeret) {
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 continue;
216 listp = TALLOC_P(mem_ctx, struct ea_list);
217 if (!listp)
218 return NULL;
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
221 return NULL;
225 fstring dos_ea_name;
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
236 *pea_total_len += 4;
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
241 return ea_list_head;
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 that was filled.
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
253 char *p = pdata;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
258 SIVAL(pdata,4,0);
259 return 4;
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 size_t dos_namelen;
264 fstring dos_ea_name;
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
268 break;
270 if (ea_list->ea.value.length > 65535) {
271 break;
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274 break;
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
300 return 0;
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
305 return total_ea_len;
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 size_t total_ea_len;
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
323 break;
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
340 int ret;
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 } else {
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 #ifdef ENOATTR
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
370 unix_ea_name));
371 ret = 0;
373 #endif
374 } else {
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 } else {
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (ret == -1) {
389 #ifdef ENOTSUP
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
393 #endif
394 return map_nt_error_from_unix(errno);
398 return NT_STATUS_OK;
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
407 size_t offset = 0;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
419 break;
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
423 return NULL;
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
426 if (!eal->ea.name) {
427 return NULL;
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
435 return ea_list_head;
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 uint16 val_len;
446 unsigned int namelen;
448 if (!eal) {
449 return NULL;
452 if (data_size < 6) {
453 return NULL;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
461 return NULL;
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
466 return NULL;
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
469 if (!eal->ea.name) {
470 return NULL;
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
475 return NULL;
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
485 if (pbytes_used) {
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, eal->ea.value.data, eal->ea.value.length);
492 return eal;
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
502 size_t offset = 0;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
508 if (!eal) {
509 return NULL;
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
516 return ea_list_head;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
525 fstring dos_ea_name;
526 struct ea_list *listp;
527 size_t ret = 0;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
534 if (ret) {
535 ret += 4;
538 return ret;
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
554 break;
558 if (flistp) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
562 } else {
563 /* Null entry. */
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
570 return name_list;
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(const char *inbuf,
581 char *outbuf,
582 int bufsize,
583 const char *params,
584 int paramsize,
585 const char *pdata,
586 int datasize,
587 int max_data_bytes)
589 /* As we are using a protocol > LANMAN1 then the max_send
590 variable must have been set in the sessetupX call.
591 This takes precedence over the max_xmit field in the
592 global struct. These different max_xmit variables should
593 be merged as this is now too confusing */
595 int data_to_send = datasize;
596 int params_to_send = paramsize;
597 int useable_space;
598 const char *pp = params;
599 const char *pd = pdata;
600 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
601 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
602 int data_alignment_offset = 0;
604 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
606 set_message(inbuf,outbuf,10,0,True);
608 /* Modify the data_to_send and datasize and set the error if
609 we're trying to send more than max_data_bytes. We still send
610 the part of the packet(s) that fit. Strange, but needed
611 for OS/2. */
613 if (max_data_bytes > 0 && datasize > max_data_bytes) {
614 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
615 max_data_bytes, datasize ));
616 datasize = data_to_send = max_data_bytes;
617 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
620 /* If there genuinely are no parameters or data to send just send the empty packet */
622 if(params_to_send == 0 && data_to_send == 0) {
623 show_msg(outbuf);
624 if (!send_smb(smbd_server_fd(),outbuf))
625 exit_server_cleanly("send_trans2_replies: send_smb failed.");
626 return 0;
629 /* When sending params and data ensure that both are nicely aligned */
630 /* Only do this alignment when there is also data to send - else
631 can cause NT redirector problems. */
633 if (((params_to_send % 4) != 0) && (data_to_send != 0))
634 data_alignment_offset = 4 - (params_to_send % 4);
636 /* Space is bufsize minus Netbios over TCP header minus SMB header */
637 /* The alignment_offset is to align the param bytes on an even byte
638 boundary. NT 4.0 Beta needs this to work correctly. */
640 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
642 /* useable_space can never be more than max_send minus the alignment offset. */
644 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
646 while (params_to_send || data_to_send) {
647 /* Calculate whether we will totally or partially fill this packet */
649 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
651 /* We can never send more than useable_space */
653 * Note that 'useable_space' does not include the alignment offsets,
654 * but we must include the alignment offsets in the calculation of
655 * the length of the data we send over the wire, as the alignment offsets
656 * are sent here. Fix from Marc_Jacobsen@hp.com.
659 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
661 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
663 /* Set total params and data to be sent */
664 SSVAL(outbuf,smb_tprcnt,paramsize);
665 SSVAL(outbuf,smb_tdrcnt,datasize);
667 /* Calculate how many parameters and data we can fit into
668 * this packet. Parameters get precedence
671 params_sent_thistime = MIN(params_to_send,useable_space);
672 data_sent_thistime = useable_space - params_sent_thistime;
673 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
675 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
677 /* smb_proff is the offset from the start of the SMB header to the
678 parameter bytes, however the first 4 bytes of outbuf are
679 the Netbios over TCP header. Thus use smb_base() to subtract
680 them from the calculation */
682 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
684 if(params_sent_thistime == 0)
685 SSVAL(outbuf,smb_prdisp,0);
686 else
687 /* Absolute displacement of param bytes sent in this packet */
688 SSVAL(outbuf,smb_prdisp,pp - params);
690 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
691 if(data_sent_thistime == 0) {
692 SSVAL(outbuf,smb_droff,0);
693 SSVAL(outbuf,smb_drdisp, 0);
694 } else {
695 /* The offset of the data bytes is the offset of the
696 parameter bytes plus the number of parameters being sent this time */
697 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
698 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
699 SSVAL(outbuf,smb_drdisp, pd - pdata);
702 /* Copy the param bytes into the packet */
704 if(params_sent_thistime)
705 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
707 /* Copy in the data bytes */
708 if(data_sent_thistime)
709 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
710 data_alignment_offset,pd,data_sent_thistime);
712 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
713 params_sent_thistime, data_sent_thistime, useable_space));
714 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
715 params_to_send, data_to_send, paramsize, datasize));
717 /* Send the packet */
718 show_msg(outbuf);
719 if (!send_smb(smbd_server_fd(),outbuf))
720 exit_server_cleanly("send_trans2_replies: send_smb failed.");
722 pp += params_sent_thistime;
723 pd += data_sent_thistime;
725 params_to_send -= params_sent_thistime;
726 data_to_send -= data_sent_thistime;
728 /* Sanity check */
729 if(params_to_send < 0 || data_to_send < 0) {
730 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
731 params_to_send, data_to_send));
732 return -1;
736 return 0;
739 /****************************************************************************
740 Reply to a TRANSACT2_OPEN.
741 ****************************************************************************/
743 static int call_trans2open(connection_struct *conn,
744 struct smb_request *req,
745 char *inbuf, char *outbuf, int bufsize,
746 char **pparams, int total_params,
747 char **ppdata, int total_data,
748 unsigned int max_data_bytes)
750 char *params = *pparams;
751 char *pdata = *ppdata;
752 int deny_mode;
753 int32 open_attr;
754 BOOL oplock_request;
755 #if 0
756 BOOL return_additional_info;
757 int16 open_sattr;
758 time_t open_time;
759 #endif
760 int open_ofun;
761 uint32 open_size;
762 char *pname;
763 pstring fname;
764 SMB_OFF_T size=0;
765 int fattr=0,mtime=0;
766 SMB_INO_T inode = 0;
767 SMB_STRUCT_STAT sbuf;
768 int smb_action = 0;
769 files_struct *fsp;
770 struct ea_list *ea_list = NULL;
771 uint16 flags = 0;
772 NTSTATUS status;
773 uint32 access_mask;
774 uint32 share_mode;
775 uint32 create_disposition;
776 uint32 create_options = 0;
779 * Ensure we have enough parameters to perform the operation.
782 if (total_params < 29) {
783 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
786 flags = SVAL(params, 0);
787 deny_mode = SVAL(params, 2);
788 open_attr = SVAL(params,6);
789 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
790 if (oplock_request) {
791 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
794 #if 0
795 return_additional_info = BITSETW(params,0);
796 open_sattr = SVAL(params, 4);
797 open_time = make_unix_date3(params+8);
798 #endif
799 open_ofun = SVAL(params,12);
800 open_size = IVAL(params,14);
801 pname = &params[28];
803 if (IS_IPC(conn)) {
804 return(ERROR_DOS(ERRSRV,ERRaccess));
807 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, pname,
808 sizeof(fname), total_params - 28, STR_TERMINATE,
809 &status);
810 if (!NT_STATUS_IS_OK(status)) {
811 return ERROR_NT(status);
814 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
815 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
816 (unsigned int)open_ofun, open_size));
818 /* XXXX we need to handle passed times, sattr and flags */
820 status = unix_convert(conn, fname, False, NULL, &sbuf);
821 if (!NT_STATUS_IS_OK(status)) {
822 return ERROR_NT(status);
825 status = check_name(conn, fname);
826 if (!NT_STATUS_IS_OK(status)) {
827 return ERROR_NT(status);
830 if (open_ofun == 0) {
831 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
834 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
835 &access_mask,
836 &share_mode,
837 &create_disposition,
838 &create_options)) {
839 return ERROR_DOS(ERRDOS, ERRbadaccess);
842 /* Any data in this call is an EA list. */
843 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
844 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
847 if (total_data != 4) {
848 if (total_data < 10) {
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 if (IVAL(pdata,0) > total_data) {
853 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
854 IVAL(pdata,0), (unsigned int)total_data));
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
858 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
859 total_data - 4);
860 if (!ea_list) {
861 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
863 } else if (IVAL(pdata,0) != 4) {
864 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
867 status = open_file_ntcreate(conn, req, fname, &sbuf,
868 access_mask,
869 share_mode,
870 create_disposition,
871 create_options,
872 open_attr,
873 oplock_request,
874 &smb_action, &fsp);
876 if (!NT_STATUS_IS_OK(status)) {
877 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
878 /* We have re-scheduled this call. */
879 return -1;
881 return ERROR_NT(status);
884 size = get_file_size(sbuf);
885 fattr = dos_mode(conn,fname,&sbuf);
886 mtime = sbuf.st_mtime;
887 inode = sbuf.st_ino;
888 if (fattr & aDIR) {
889 close_file(fsp,ERROR_CLOSE);
890 return(ERROR_DOS(ERRDOS,ERRnoaccess));
893 /* Save the requested allocation size. */
894 /* Allocate space for the file if a size hint is supplied */
895 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
896 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
897 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
898 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
899 if (fsp->is_directory) {
900 close_file(fsp,ERROR_CLOSE);
901 /* Can't set allocation size on a directory. */
902 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
904 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
905 close_file(fsp,ERROR_CLOSE);
906 return ERROR_NT(NT_STATUS_DISK_FULL);
909 /* Adjust size here to return the right size in the reply.
910 Windows does it this way. */
911 size = fsp->initial_allocation_size;
912 } else {
913 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
917 if (ea_list && smb_action == FILE_WAS_CREATED) {
918 status = set_ea(conn, fsp, fname, ea_list);
919 if (!NT_STATUS_IS_OK(status)) {
920 close_file(fsp,ERROR_CLOSE);
921 return ERROR_NT(status);
925 /* Realloc the size of parameters and data we will return */
926 *pparams = (char *)SMB_REALLOC(*pparams, 30);
927 if(*pparams == NULL ) {
928 return ERROR_NT(NT_STATUS_NO_MEMORY);
930 params = *pparams;
932 SSVAL(params,0,fsp->fnum);
933 SSVAL(params,2,fattr);
934 srv_put_dos_date2(params,4, mtime);
935 SIVAL(params,8, (uint32)size);
936 SSVAL(params,12,deny_mode);
937 SSVAL(params,14,0); /* open_type - file or directory. */
938 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
940 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
941 smb_action |= EXTENDED_OPLOCK_GRANTED;
944 SSVAL(params,18,smb_action);
947 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
949 SIVAL(params,20,inode);
950 SSVAL(params,24,0); /* Padding. */
951 if (flags & 8) {
952 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
953 SIVAL(params, 26, ea_size);
954 } else {
955 SIVAL(params, 26, 0);
958 /* Send the required number of replies */
959 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
961 return -1;
964 /*********************************************************
965 Routine to check if a given string matches exactly.
966 as a special case a mask of "." does NOT match. That
967 is required for correct wildcard semantics
968 Case can be significant or not.
969 **********************************************************/
971 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
973 if (mask[0] == '.' && mask[1] == 0)
974 return False;
975 if (conn->case_sensitive)
976 return strcmp(str,mask)==0;
977 if (StrCaseCmp(str,mask) != 0) {
978 return False;
980 if (dptr_has_wild(conn->dirptr)) {
981 return False;
983 return True;
986 /****************************************************************************
987 Return the filetype for UNIX extensions.
988 ****************************************************************************/
990 static uint32 unix_filetype(mode_t mode)
992 if(S_ISREG(mode))
993 return UNIX_TYPE_FILE;
994 else if(S_ISDIR(mode))
995 return UNIX_TYPE_DIR;
996 #ifdef S_ISLNK
997 else if(S_ISLNK(mode))
998 return UNIX_TYPE_SYMLINK;
999 #endif
1000 #ifdef S_ISCHR
1001 else if(S_ISCHR(mode))
1002 return UNIX_TYPE_CHARDEV;
1003 #endif
1004 #ifdef S_ISBLK
1005 else if(S_ISBLK(mode))
1006 return UNIX_TYPE_BLKDEV;
1007 #endif
1008 #ifdef S_ISFIFO
1009 else if(S_ISFIFO(mode))
1010 return UNIX_TYPE_FIFO;
1011 #endif
1012 #ifdef S_ISSOCK
1013 else if(S_ISSOCK(mode))
1014 return UNIX_TYPE_SOCKET;
1015 #endif
1017 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1018 return UNIX_TYPE_UNKNOWN;
1021 /****************************************************************************
1022 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1023 ****************************************************************************/
1025 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1027 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1028 SMB_STRUCT_STAT *psbuf,
1029 uint32 perms,
1030 enum perm_type ptype,
1031 mode_t *ret_perms)
1033 mode_t ret = 0;
1035 if (perms == SMB_MODE_NO_CHANGE) {
1036 if (!VALID_STAT(*psbuf)) {
1037 return NT_STATUS_INVALID_PARAMETER;
1038 } else {
1039 *ret_perms = psbuf->st_mode;
1040 return NT_STATUS_OK;
1044 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1045 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1046 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1047 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1048 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1049 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1050 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1051 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1052 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1053 #ifdef S_ISVTX
1054 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1055 #endif
1056 #ifdef S_ISGID
1057 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1058 #endif
1059 #ifdef S_ISUID
1060 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1061 #endif
1063 switch (ptype) {
1064 case PERM_NEW_FILE:
1065 /* Apply mode mask */
1066 ret &= lp_create_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_create_mode(SNUM(conn));
1069 break;
1070 case PERM_NEW_DIR:
1071 ret &= lp_dir_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_dir_mode(SNUM(conn));
1074 break;
1075 case PERM_EXISTING_FILE:
1076 /* Apply mode mask */
1077 ret &= lp_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_security_mode(SNUM(conn));
1080 break;
1081 case PERM_EXISTING_DIR:
1082 /* Apply mode mask */
1083 ret &= lp_dir_security_mask(SNUM(conn));
1084 /* Add in force bits */
1085 ret |= lp_force_dir_security_mode(SNUM(conn));
1086 break;
1089 *ret_perms = ret;
1090 return NT_STATUS_OK;
1093 /****************************************************************************
1094 Get a level dependent lanman2 dir entry.
1095 ****************************************************************************/
1097 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1098 void *inbuf, char *outbuf,
1099 char *path_mask,uint32 dirtype,int info_level,
1100 int requires_resume_key,
1101 BOOL dont_descend,char **ppdata,
1102 char *base_data, int space_remaining,
1103 BOOL *out_of_space, BOOL *got_exact_match,
1104 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1106 const char *dname;
1107 BOOL found = False;
1108 SMB_STRUCT_STAT sbuf;
1109 pstring mask;
1110 pstring pathreal;
1111 pstring fname;
1112 char *p, *q, *pdata = *ppdata;
1113 uint32 reskey=0;
1114 long prev_dirpos=0;
1115 uint32 mode=0;
1116 SMB_OFF_T file_size = 0;
1117 SMB_BIG_UINT allocation_size = 0;
1118 uint32 len;
1119 struct timespec mdate_ts, adate_ts, create_date_ts;
1120 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1121 char *nameptr;
1122 char *last_entry_ptr;
1123 BOOL was_8_3;
1124 uint32 nt_extmode; /* Used for NT connections instead of mode */
1125 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1126 BOOL check_mangled_names = lp_manglednames(conn->params);
1128 *fname = 0;
1129 *out_of_space = False;
1130 *got_exact_match = False;
1132 ZERO_STRUCT(mdate_ts);
1133 ZERO_STRUCT(adate_ts);
1134 ZERO_STRUCT(create_date_ts);
1136 if (!conn->dirptr)
1137 return(False);
1139 p = strrchr_m(path_mask,'/');
1140 if(p != NULL) {
1141 if(p[1] == '\0')
1142 pstrcpy(mask,"*.*");
1143 else
1144 pstrcpy(mask, p+1);
1145 } else
1146 pstrcpy(mask, path_mask);
1149 while (!found) {
1150 BOOL got_match;
1151 BOOL ms_dfs_link = False;
1153 /* Needed if we run out of space */
1154 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1155 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1158 * Due to bugs in NT client redirectors we are not using
1159 * resume keys any more - set them to zero.
1160 * Check out the related comments in findfirst/findnext.
1161 * JRA.
1164 reskey = 0;
1166 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1167 (long)conn->dirptr,curr_dirpos));
1169 if (!dname) {
1170 return(False);
1174 * fname may get mangled, dname is never mangled.
1175 * Whenever we're accessing the filesystem we use
1176 * pathreal which is composed from dname.
1179 pstrcpy(fname,dname);
1181 /* This will mangle fname if it's an illegal name. */
1182 mangle_map(fname,False,True,conn->params);
1184 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1185 got_match = mask_match(fname, mask, conn->case_sensitive);
1188 if(!got_match && check_mangled_names &&
1189 !mangle_is_8_3(fname, False, conn->params)) {
1190 pstring mangled_name;
1193 * It turns out that NT matches wildcards against
1194 * both long *and* short names. This may explain some
1195 * of the wildcard wierdness from old DOS clients
1196 * that some people have been seeing.... JRA.
1199 pstrcpy(mangled_name, fname);
1201 /* Force the mangling into 8.3. */
1202 mangle_map( mangled_name, True, False, conn->params);
1203 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1204 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1208 if (got_match) {
1209 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1210 if (dont_descend && !isdots) {
1211 continue;
1214 pstrcpy(pathreal,conn->dirpath);
1215 if(needslash) {
1216 pstrcat(pathreal,"/");
1218 pstrcat(pathreal,dname);
1220 if (INFO_LEVEL_IS_UNIX(info_level)) {
1221 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1222 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1223 pathreal,strerror(errno)));
1224 continue;
1226 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1227 pstring link_target;
1229 /* Needed to show the msdfs symlinks as
1230 * directories */
1232 if(lp_host_msdfs() &&
1233 lp_msdfs_root(SNUM(conn)) &&
1234 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1235 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1236 "as a directory\n",
1237 pathreal));
1238 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1240 } else {
1242 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1243 pathreal,strerror(errno)));
1244 continue;
1248 if (ms_dfs_link) {
1249 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1250 } else {
1251 mode = dos_mode(conn,pathreal,&sbuf);
1254 if (!dir_check_ftype(conn,mode,dirtype)) {
1255 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1256 continue;
1259 if (!(mode & aDIR)) {
1260 file_size = get_file_size(sbuf);
1262 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1264 mdate_ts = get_mtimespec(&sbuf);
1265 adate_ts = get_atimespec(&sbuf);
1266 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1268 if (lp_dos_filetime_resolution(SNUM(conn))) {
1269 dos_filetime_timespec(&create_date_ts);
1270 dos_filetime_timespec(&mdate_ts);
1271 dos_filetime_timespec(&adate_ts);
1274 create_date = convert_timespec_to_time_t(create_date_ts);
1275 mdate = convert_timespec_to_time_t(mdate_ts);
1276 adate = convert_timespec_to_time_t(adate_ts);
1278 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1280 found = True;
1282 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1286 p = pdata;
1287 last_entry_ptr = p;
1289 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1291 switch (info_level) {
1292 case SMB_FIND_INFO_STANDARD:
1293 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1294 if(requires_resume_key) {
1295 SIVAL(p,0,reskey);
1296 p += 4;
1298 srv_put_dos_date2(p,0,create_date);
1299 srv_put_dos_date2(p,4,adate);
1300 srv_put_dos_date2(p,8,mdate);
1301 SIVAL(p,12,(uint32)file_size);
1302 SIVAL(p,16,(uint32)allocation_size);
1303 SSVAL(p,20,mode);
1304 p += 23;
1305 nameptr = p;
1306 p += align_string(outbuf, p, 0);
1307 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1308 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1309 if (len > 2) {
1310 SCVAL(nameptr, -1, len - 2);
1311 } else {
1312 SCVAL(nameptr, -1, 0);
1314 } else {
1315 if (len > 1) {
1316 SCVAL(nameptr, -1, len - 1);
1317 } else {
1318 SCVAL(nameptr, -1, 0);
1321 p += len;
1322 break;
1324 case SMB_FIND_EA_SIZE:
1325 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1326 if(requires_resume_key) {
1327 SIVAL(p,0,reskey);
1328 p += 4;
1330 srv_put_dos_date2(p,0,create_date);
1331 srv_put_dos_date2(p,4,adate);
1332 srv_put_dos_date2(p,8,mdate);
1333 SIVAL(p,12,(uint32)file_size);
1334 SIVAL(p,16,(uint32)allocation_size);
1335 SSVAL(p,20,mode);
1337 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1338 SIVAL(p,22,ea_size); /* Extended attributes */
1340 p += 27;
1341 nameptr = p - 1;
1342 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1343 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1344 if (len > 2) {
1345 len -= 2;
1346 } else {
1347 len = 0;
1349 } else {
1350 if (len > 1) {
1351 len -= 1;
1352 } else {
1353 len = 0;
1356 SCVAL(nameptr,0,len);
1357 p += len;
1358 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1359 break;
1361 case SMB_FIND_EA_LIST:
1363 struct ea_list *file_list = NULL;
1364 size_t ea_len = 0;
1366 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1367 if (!name_list) {
1368 return False;
1370 if(requires_resume_key) {
1371 SIVAL(p,0,reskey);
1372 p += 4;
1374 srv_put_dos_date2(p,0,create_date);
1375 srv_put_dos_date2(p,4,adate);
1376 srv_put_dos_date2(p,8,mdate);
1377 SIVAL(p,12,(uint32)file_size);
1378 SIVAL(p,16,(uint32)allocation_size);
1379 SSVAL(p,20,mode);
1380 p += 22; /* p now points to the EA area. */
1382 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1383 name_list = ea_list_union(name_list, file_list, &ea_len);
1385 /* We need to determine if this entry will fit in the space available. */
1386 /* Max string size is 255 bytes. */
1387 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1388 /* Move the dirptr back to prev_dirpos */
1389 dptr_SeekDir(conn->dirptr, prev_dirpos);
1390 *out_of_space = True;
1391 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1392 return False; /* Not finished - just out of space */
1395 /* Push the ea_data followed by the name. */
1396 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1397 nameptr = p;
1398 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1399 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1400 if (len > 2) {
1401 len -= 2;
1402 } else {
1403 len = 0;
1405 } else {
1406 if (len > 1) {
1407 len -= 1;
1408 } else {
1409 len = 0;
1412 SCVAL(nameptr,0,len);
1413 p += len + 1;
1414 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1415 break;
1418 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1419 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1420 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1421 p += 4;
1422 SIVAL(p,0,reskey); p += 4;
1423 put_long_date_timespec(p,create_date_ts); p += 8;
1424 put_long_date_timespec(p,adate_ts); p += 8;
1425 put_long_date_timespec(p,mdate_ts); p += 8;
1426 put_long_date_timespec(p,mdate_ts); p += 8;
1427 SOFF_T(p,0,file_size); p += 8;
1428 SOFF_T(p,0,allocation_size); p += 8;
1429 SIVAL(p,0,nt_extmode); p += 4;
1430 q = p; p += 4; /* q is placeholder for name length. */
1432 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1433 SIVAL(p,0,ea_size); /* Extended attributes */
1434 p += 4;
1436 /* Clear the short name buffer. This is
1437 * IMPORTANT as not doing so will trigger
1438 * a Win2k client bug. JRA.
1440 if (!was_8_3 && check_mangled_names) {
1441 pstring mangled_name;
1442 pstrcpy(mangled_name, fname);
1443 mangle_map(mangled_name,True,True,
1444 conn->params);
1445 mangled_name[12] = 0;
1446 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1447 if (len < 24) {
1448 memset(p + 2 + len,'\0',24 - len);
1450 SSVAL(p, 0, len);
1451 } else {
1452 memset(p,'\0',26);
1454 p += 2 + 24;
1455 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1456 SIVAL(q,0,len);
1457 p += len;
1458 SIVAL(p,0,0); /* Ensure any padding is null. */
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1461 SIVAL(pdata,0,len);
1462 p = pdata + len;
1463 break;
1465 case SMB_FIND_FILE_DIRECTORY_INFO:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1467 p += 4;
1468 SIVAL(p,0,reskey); p += 4;
1469 put_long_date_timespec(p,create_date_ts); p += 8;
1470 put_long_date_timespec(p,adate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 put_long_date_timespec(p,mdate_ts); p += 8;
1473 SOFF_T(p,0,file_size); p += 8;
1474 SOFF_T(p,0,allocation_size); p += 8;
1475 SIVAL(p,0,nt_extmode); p += 4;
1476 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1477 SIVAL(p,0,len);
1478 p += 4 + len;
1479 SIVAL(p,0,0); /* Ensure any padding is null. */
1480 len = PTR_DIFF(p, pdata);
1481 len = (len + 3) & ~3;
1482 SIVAL(pdata,0,len);
1483 p = pdata + len;
1484 break;
1486 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1487 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1488 p += 4;
1489 SIVAL(p,0,reskey); p += 4;
1490 put_long_date_timespec(p,create_date_ts); p += 8;
1491 put_long_date_timespec(p,adate_ts); p += 8;
1492 put_long_date_timespec(p,mdate_ts); p += 8;
1493 put_long_date_timespec(p,mdate_ts); p += 8;
1494 SOFF_T(p,0,file_size); p += 8;
1495 SOFF_T(p,0,allocation_size); p += 8;
1496 SIVAL(p,0,nt_extmode); p += 4;
1497 q = p; p += 4; /* q is placeholder for name length. */
1499 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1500 SIVAL(p,0,ea_size); /* Extended attributes */
1501 p +=4;
1503 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1504 SIVAL(q, 0, len);
1505 p += len;
1507 SIVAL(p,0,0); /* Ensure any padding is null. */
1508 len = PTR_DIFF(p, pdata);
1509 len = (len + 3) & ~3;
1510 SIVAL(pdata,0,len);
1511 p = pdata + len;
1512 break;
1514 case SMB_FIND_FILE_NAMES_INFO:
1515 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1516 p += 4;
1517 SIVAL(p,0,reskey); p += 4;
1518 p += 4;
1519 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1520 acl on a dir (tridge) */
1521 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1522 SIVAL(p, -4, len);
1523 p += len;
1524 SIVAL(p,0,0); /* Ensure any padding is null. */
1525 len = PTR_DIFF(p, pdata);
1526 len = (len + 3) & ~3;
1527 SIVAL(pdata,0,len);
1528 p = pdata + len;
1529 break;
1531 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1532 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1533 p += 4;
1534 SIVAL(p,0,reskey); p += 4;
1535 put_long_date_timespec(p,create_date_ts); p += 8;
1536 put_long_date_timespec(p,adate_ts); p += 8;
1537 put_long_date_timespec(p,mdate_ts); p += 8;
1538 put_long_date_timespec(p,mdate_ts); p += 8;
1539 SOFF_T(p,0,file_size); p += 8;
1540 SOFF_T(p,0,allocation_size); p += 8;
1541 SIVAL(p,0,nt_extmode); p += 4;
1542 q = p; p += 4; /* q is placeholder for name length. */
1544 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1545 SIVAL(p,0,ea_size); /* Extended attributes */
1546 p +=4;
1548 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1549 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1550 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1551 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1552 SIVAL(q, 0, len);
1553 p += len;
1554 SIVAL(p,0,0); /* Ensure any padding is null. */
1555 len = PTR_DIFF(p, pdata);
1556 len = (len + 3) & ~3;
1557 SIVAL(pdata,0,len);
1558 p = pdata + len;
1559 break;
1561 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1562 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1563 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1564 p += 4;
1565 SIVAL(p,0,reskey); p += 4;
1566 put_long_date_timespec(p,create_date_ts); p += 8;
1567 put_long_date_timespec(p,adate_ts); p += 8;
1568 put_long_date_timespec(p,mdate_ts); p += 8;
1569 put_long_date_timespec(p,mdate_ts); p += 8;
1570 SOFF_T(p,0,file_size); p += 8;
1571 SOFF_T(p,0,allocation_size); p += 8;
1572 SIVAL(p,0,nt_extmode); p += 4;
1573 q = p; p += 4; /* q is placeholder for name length */
1575 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1576 SIVAL(p,0,ea_size); /* Extended attributes */
1577 p +=4;
1579 /* Clear the short name buffer. This is
1580 * IMPORTANT as not doing so will trigger
1581 * a Win2k client bug. JRA.
1583 if (!was_8_3 && check_mangled_names) {
1584 pstring mangled_name;
1585 pstrcpy(mangled_name, fname);
1586 mangle_map(mangled_name,True,True,
1587 conn->params);
1588 mangled_name[12] = 0;
1589 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1590 SSVAL(p, 0, len);
1591 if (len < 24) {
1592 memset(p + 2 + len,'\0',24 - len);
1594 SSVAL(p, 0, len);
1595 } else {
1596 memset(p,'\0',26);
1598 p += 26;
1599 SSVAL(p,0,0); p += 2; /* Reserved ? */
1600 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1601 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1602 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1603 SIVAL(q,0,len);
1604 p += len;
1605 SIVAL(p,0,0); /* Ensure any padding is null. */
1606 len = PTR_DIFF(p, pdata);
1607 len = (len + 3) & ~3;
1608 SIVAL(pdata,0,len);
1609 p = pdata + len;
1610 break;
1612 /* CIFS UNIX Extension. */
1614 case SMB_FIND_FILE_UNIX:
1615 case SMB_FIND_FILE_UNIX_INFO2:
1616 p+= 4;
1617 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1619 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1621 if (info_level == SMB_FIND_FILE_UNIX) {
1622 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1623 p = store_file_unix_basic(conn, p,
1624 NULL, &sbuf);
1625 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1626 } else {
1627 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1628 p = store_file_unix_basic_info2(conn, p,
1629 NULL, &sbuf);
1630 nameptr = p;
1631 p += 4;
1632 len = srvstr_push(outbuf, p, fname, -1, 0);
1633 SIVAL(nameptr, 0, len);
1636 p += len;
1637 SIVAL(p,0,0); /* Ensure any padding is null. */
1639 len = PTR_DIFF(p, pdata);
1640 len = (len + 3) & ~3;
1641 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1642 p = pdata + len;
1643 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1645 break;
1647 default:
1648 return(False);
1652 if (PTR_DIFF(p,pdata) > space_remaining) {
1653 /* Move the dirptr back to prev_dirpos */
1654 dptr_SeekDir(conn->dirptr, prev_dirpos);
1655 *out_of_space = True;
1656 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1657 return False; /* Not finished - just out of space */
1660 /* Setup the last entry pointer, as an offset from base_data */
1661 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1662 /* Advance the data pointer to the next slot */
1663 *ppdata = p;
1665 return(found);
1668 /****************************************************************************
1669 Reply to a TRANS2_FINDFIRST.
1670 ****************************************************************************/
1672 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1673 char **pparams, int total_params, char **ppdata, int total_data,
1674 unsigned int max_data_bytes)
1676 /* We must be careful here that we don't return more than the
1677 allowed number of data bytes. If this means returning fewer than
1678 maxentries then so be it. We assume that the redirector has
1679 enough room for the fixed number of parameter bytes it has
1680 requested. */
1681 char *params = *pparams;
1682 char *pdata = *ppdata;
1683 uint32 dirtype;
1684 int maxentries;
1685 uint16 findfirst_flags;
1686 BOOL close_after_first;
1687 BOOL close_if_end;
1688 BOOL requires_resume_key;
1689 int info_level;
1690 pstring directory;
1691 pstring mask;
1692 char *p;
1693 int last_entry_off=0;
1694 int dptr_num = -1;
1695 int numentries = 0;
1696 int i;
1697 BOOL finished = False;
1698 BOOL dont_descend = False;
1699 BOOL out_of_space = False;
1700 int space_remaining;
1701 BOOL mask_contains_wcard = False;
1702 SMB_STRUCT_STAT sbuf;
1703 TALLOC_CTX *ea_ctx = NULL;
1704 struct ea_list *ea_list = NULL;
1705 NTSTATUS ntstatus = NT_STATUS_OK;
1707 if (total_params < 13) {
1708 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1711 dirtype = SVAL(params,0);
1712 maxentries = SVAL(params,2);
1713 findfirst_flags = SVAL(params,4);
1714 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1715 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1716 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1717 info_level = SVAL(params,6);
1719 *directory = *mask = 0;
1721 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1722 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1723 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1724 info_level, max_data_bytes));
1726 if (!maxentries) {
1727 /* W2K3 seems to treat zero as 1. */
1728 maxentries = 1;
1731 switch (info_level) {
1732 case SMB_FIND_INFO_STANDARD:
1733 case SMB_FIND_EA_SIZE:
1734 case SMB_FIND_EA_LIST:
1735 case SMB_FIND_FILE_DIRECTORY_INFO:
1736 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1737 case SMB_FIND_FILE_NAMES_INFO:
1738 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1739 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1740 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1741 break;
1742 case SMB_FIND_FILE_UNIX:
1743 case SMB_FIND_FILE_UNIX_INFO2:
1744 if (!lp_unix_extensions()) {
1745 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1747 break;
1748 default:
1749 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1752 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory,
1753 params+12, sizeof(directory), total_params - 12,
1754 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1755 if (!NT_STATUS_IS_OK(ntstatus)) {
1756 return ERROR_NT(ntstatus);
1759 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1760 if (!NT_STATUS_IS_OK(ntstatus)) {
1761 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1762 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1764 return ERROR_NT(ntstatus);
1767 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1768 if (!NT_STATUS_IS_OK(ntstatus)) {
1769 return ERROR_NT(ntstatus);
1771 ntstatus = check_name(conn, directory);
1772 if (!NT_STATUS_IS_OK(ntstatus)) {
1773 return ERROR_NT(ntstatus);
1776 p = strrchr_m(directory,'/');
1777 if(p == NULL) {
1778 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1779 if((directory[0] == '.') && (directory[1] == '\0')) {
1780 pstrcpy(mask,"*");
1781 mask_contains_wcard = True;
1782 } else {
1783 pstrcpy(mask,directory);
1785 pstrcpy(directory,"./");
1786 } else {
1787 pstrcpy(mask,p+1);
1788 *p = 0;
1791 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1793 if (info_level == SMB_FIND_EA_LIST) {
1794 uint32 ea_size;
1796 if (total_data < 4) {
1797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 ea_size = IVAL(pdata,0);
1801 if (ea_size != total_data) {
1802 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1803 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1804 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1807 if (!lp_ea_support(SNUM(conn))) {
1808 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1811 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1812 return ERROR_NT(NT_STATUS_NO_MEMORY);
1815 /* Pull out the list of names. */
1816 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1817 if (!ea_list) {
1818 talloc_destroy(ea_ctx);
1819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1823 *ppdata = (char *)SMB_REALLOC(
1824 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1825 if(*ppdata == NULL ) {
1826 talloc_destroy(ea_ctx);
1827 return ERROR_NT(NT_STATUS_NO_MEMORY);
1829 pdata = *ppdata;
1831 /* Realloc the params space */
1832 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1833 if (*pparams == NULL) {
1834 talloc_destroy(ea_ctx);
1835 return ERROR_NT(NT_STATUS_NO_MEMORY);
1837 params = *pparams;
1839 /* Save the wildcard match and attribs we are using on this directory -
1840 needed as lanman2 assumes these are being saved between calls */
1842 ntstatus = dptr_create(conn,
1843 directory,
1844 False,
1845 True,
1846 SVAL(inbuf,smb_pid),
1847 mask,
1848 mask_contains_wcard,
1849 dirtype,
1850 &conn->dirptr);
1852 if (!NT_STATUS_IS_OK(ntstatus)) {
1853 talloc_destroy(ea_ctx);
1854 return ERROR_NT(ntstatus);
1857 dptr_num = dptr_dnum(conn->dirptr);
1858 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1860 /* We don't need to check for VOL here as this is returned by
1861 a different TRANS2 call. */
1863 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1864 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1865 dont_descend = True;
1867 p = pdata;
1868 space_remaining = max_data_bytes;
1869 out_of_space = False;
1871 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1872 BOOL got_exact_match = False;
1874 /* this is a heuristic to avoid seeking the dirptr except when
1875 absolutely necessary. It allows for a filename of about 40 chars */
1876 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1877 out_of_space = True;
1878 finished = False;
1879 } else {
1880 finished = !get_lanman2_dir_entry(conn,
1881 inbuf, outbuf,
1882 mask,dirtype,info_level,
1883 requires_resume_key,dont_descend,
1884 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1885 &last_entry_off, ea_list, ea_ctx);
1888 if (finished && out_of_space)
1889 finished = False;
1891 if (!finished && !out_of_space)
1892 numentries++;
1895 * As an optimisation if we know we aren't looking
1896 * for a wildcard name (ie. the name matches the wildcard exactly)
1897 * then we can finish on any (first) match.
1898 * This speeds up large directory searches. JRA.
1901 if(got_exact_match)
1902 finished = True;
1904 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1907 talloc_destroy(ea_ctx);
1909 /* Check if we can close the dirptr */
1910 if(close_after_first || (finished && close_if_end)) {
1911 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1912 dptr_close(&dptr_num);
1916 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1917 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1918 * the protocol level is less than NT1. Tested with smbclient. JRA.
1919 * This should fix the OS/2 client bug #2335.
1922 if(numentries == 0) {
1923 dptr_close(&dptr_num);
1924 if (Protocol < PROTOCOL_NT1) {
1925 return ERROR_DOS(ERRDOS,ERRnofiles);
1926 } else {
1927 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1931 /* At this point pdata points to numentries directory entries. */
1933 /* Set up the return parameter block */
1934 SSVAL(params,0,dptr_num);
1935 SSVAL(params,2,numentries);
1936 SSVAL(params,4,finished);
1937 SSVAL(params,6,0); /* Never an EA error */
1938 SSVAL(params,8,last_entry_off);
1940 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1942 if ((! *directory) && dptr_path(dptr_num))
1943 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1945 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1946 smb_fn_name(CVAL(inbuf,smb_com)),
1947 mask, directory, dirtype, numentries ) );
1950 * Force a name mangle here to ensure that the
1951 * mask as an 8.3 name is top of the mangled cache.
1952 * The reasons for this are subtle. Don't remove
1953 * this code unless you know what you are doing
1954 * (see PR#13758). JRA.
1957 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1958 mangle_map(mask, True, True, conn->params);
1960 return(-1);
1963 /****************************************************************************
1964 Reply to a TRANS2_FINDNEXT.
1965 ****************************************************************************/
1967 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1968 char **pparams, int total_params, char **ppdata, int total_data,
1969 unsigned int max_data_bytes)
1971 /* We must be careful here that we don't return more than the
1972 allowed number of data bytes. If this means returning fewer than
1973 maxentries then so be it. We assume that the redirector has
1974 enough room for the fixed number of parameter bytes it has
1975 requested. */
1976 char *params = *pparams;
1977 char *pdata = *ppdata;
1978 int dptr_num;
1979 int maxentries;
1980 uint16 info_level;
1981 uint32 resume_key;
1982 uint16 findnext_flags;
1983 BOOL close_after_request;
1984 BOOL close_if_end;
1985 BOOL requires_resume_key;
1986 BOOL continue_bit;
1987 BOOL mask_contains_wcard = False;
1988 pstring resume_name;
1989 pstring mask;
1990 pstring directory;
1991 char *p;
1992 uint16 dirtype;
1993 int numentries = 0;
1994 int i, last_entry_off=0;
1995 BOOL finished = False;
1996 BOOL dont_descend = False;
1997 BOOL out_of_space = False;
1998 int space_remaining;
1999 TALLOC_CTX *ea_ctx = NULL;
2000 struct ea_list *ea_list = NULL;
2001 NTSTATUS ntstatus = NT_STATUS_OK;
2003 if (total_params < 13) {
2004 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2007 dptr_num = SVAL(params,0);
2008 maxentries = SVAL(params,2);
2009 info_level = SVAL(params,4);
2010 resume_key = IVAL(params,6);
2011 findnext_flags = SVAL(params,10);
2012 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2013 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2014 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2015 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2017 *mask = *directory = *resume_name = 0;
2019 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name,
2020 params+12, sizeof(resume_name),
2021 total_params - 12, STR_TERMINATE, &ntstatus,
2022 &mask_contains_wcard);
2023 if (!NT_STATUS_IS_OK(ntstatus)) {
2024 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2025 complain (it thinks we're asking for the directory above the shared
2026 path or an invalid name). Catch this as the resume name is only compared, never used in
2027 a file access. JRA. */
2028 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2029 pstrcpy(resume_name, "..");
2030 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2031 pstrcpy(resume_name, ".");
2032 } else {
2033 return ERROR_NT(ntstatus);
2037 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2038 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2039 resume_key = %d resume name = %s continue=%d level = %d\n",
2040 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2041 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2043 if (!maxentries) {
2044 /* W2K3 seems to treat zero as 1. */
2045 maxentries = 1;
2048 switch (info_level) {
2049 case SMB_FIND_INFO_STANDARD:
2050 case SMB_FIND_EA_SIZE:
2051 case SMB_FIND_EA_LIST:
2052 case SMB_FIND_FILE_DIRECTORY_INFO:
2053 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2054 case SMB_FIND_FILE_NAMES_INFO:
2055 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2056 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2057 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2058 break;
2059 case SMB_FIND_FILE_UNIX:
2060 case SMB_FIND_FILE_UNIX_INFO2:
2061 if (!lp_unix_extensions()) {
2062 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2064 break;
2065 default:
2066 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2069 if (info_level == SMB_FIND_EA_LIST) {
2070 uint32 ea_size;
2072 if (total_data < 4) {
2073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2076 ea_size = IVAL(pdata,0);
2077 if (ea_size != total_data) {
2078 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2079 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2080 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2083 if (!lp_ea_support(SNUM(conn))) {
2084 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2087 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2088 return ERROR_NT(NT_STATUS_NO_MEMORY);
2091 /* Pull out the list of names. */
2092 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2093 if (!ea_list) {
2094 talloc_destroy(ea_ctx);
2095 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2099 *ppdata = (char *)SMB_REALLOC(
2100 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2101 if(*ppdata == NULL) {
2102 talloc_destroy(ea_ctx);
2103 return ERROR_NT(NT_STATUS_NO_MEMORY);
2106 pdata = *ppdata;
2108 /* Realloc the params space */
2109 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2110 if(*pparams == NULL ) {
2111 talloc_destroy(ea_ctx);
2112 return ERROR_NT(NT_STATUS_NO_MEMORY);
2115 params = *pparams;
2117 /* Check that the dptr is valid */
2118 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2119 talloc_destroy(ea_ctx);
2120 return ERROR_DOS(ERRDOS,ERRnofiles);
2123 string_set(&conn->dirpath,dptr_path(dptr_num));
2125 /* Get the wildcard mask from the dptr */
2126 if((p = dptr_wcard(dptr_num))== NULL) {
2127 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2128 talloc_destroy(ea_ctx);
2129 return ERROR_DOS(ERRDOS,ERRnofiles);
2132 pstrcpy(mask, p);
2133 pstrcpy(directory,conn->dirpath);
2135 /* Get the attr mask from the dptr */
2136 dirtype = dptr_attr(dptr_num);
2138 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2139 dptr_num, mask, dirtype,
2140 (long)conn->dirptr,
2141 dptr_TellDir(conn->dirptr)));
2143 /* We don't need to check for VOL here as this is returned by
2144 a different TRANS2 call. */
2146 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2147 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2148 dont_descend = True;
2150 p = pdata;
2151 space_remaining = max_data_bytes;
2152 out_of_space = False;
2155 * Seek to the correct position. We no longer use the resume key but
2156 * depend on the last file name instead.
2159 if(*resume_name && !continue_bit) {
2160 SMB_STRUCT_STAT st;
2162 long current_pos = 0;
2164 * Remember, mangle_map is called by
2165 * get_lanman2_dir_entry(), so the resume name
2166 * could be mangled. Ensure we check the unmangled name.
2169 if (mangle_is_mangled(resume_name, conn->params)) {
2170 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2171 conn->params);
2175 * Fix for NT redirector problem triggered by resume key indexes
2176 * changing between directory scans. We now return a resume key of 0
2177 * and instead look for the filename to continue from (also given
2178 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2179 * findfirst/findnext (as is usual) then the directory pointer
2180 * should already be at the correct place.
2183 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2184 } /* end if resume_name && !continue_bit */
2186 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2187 BOOL got_exact_match = False;
2189 /* this is a heuristic to avoid seeking the dirptr except when
2190 absolutely necessary. It allows for a filename of about 40 chars */
2191 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2192 out_of_space = True;
2193 finished = False;
2194 } else {
2195 finished = !get_lanman2_dir_entry(conn,
2196 inbuf, outbuf,
2197 mask,dirtype,info_level,
2198 requires_resume_key,dont_descend,
2199 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2200 &last_entry_off, ea_list, ea_ctx);
2203 if (finished && out_of_space)
2204 finished = False;
2206 if (!finished && !out_of_space)
2207 numentries++;
2210 * As an optimisation if we know we aren't looking
2211 * for a wildcard name (ie. the name matches the wildcard exactly)
2212 * then we can finish on any (first) match.
2213 * This speeds up large directory searches. JRA.
2216 if(got_exact_match)
2217 finished = True;
2219 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2222 talloc_destroy(ea_ctx);
2224 /* Check if we can close the dirptr */
2225 if(close_after_request || (finished && close_if_end)) {
2226 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2227 dptr_close(&dptr_num); /* This frees up the saved mask */
2230 /* Set up the return parameter block */
2231 SSVAL(params,0,numentries);
2232 SSVAL(params,2,finished);
2233 SSVAL(params,4,0); /* Never an EA error */
2234 SSVAL(params,6,last_entry_off);
2236 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2238 if ((! *directory) && dptr_path(dptr_num))
2239 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2241 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2242 smb_fn_name(CVAL(inbuf,smb_com)),
2243 mask, directory, dirtype, numentries ) );
2245 return(-1);
2248 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2250 E_md4hash(lp_servicename(SNUM(conn)),objid);
2251 return objid;
2254 /****************************************************************************
2255 Reply to a TRANS2_QFSINFO (query filesystem info).
2256 ****************************************************************************/
2258 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2259 char **pparams, int total_params, char **ppdata, int total_data,
2260 unsigned int max_data_bytes)
2262 char *pdata;
2263 char *params = *pparams;
2264 uint16 info_level;
2265 int data_len, len;
2266 SMB_STRUCT_STAT st;
2267 const char *vname = volume_label(SNUM(conn));
2268 int snum = SNUM(conn);
2269 char *fstype = lp_fstype(SNUM(conn));
2270 int quota_flag = 0;
2272 if (total_params < 2) {
2273 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2276 info_level = SVAL(params,0);
2278 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2280 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2281 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2282 return ERROR_DOS(ERRSRV,ERRinvdevice);
2285 *ppdata = (char *)SMB_REALLOC(
2286 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2287 if (*ppdata == NULL ) {
2288 return ERROR_NT(NT_STATUS_NO_MEMORY);
2291 pdata = *ppdata;
2292 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2294 switch (info_level) {
2295 case SMB_INFO_ALLOCATION:
2297 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2298 data_len = 18;
2299 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2300 return(UNIXERROR(ERRHRD,ERRgeneral));
2303 block_size = lp_block_size(snum);
2304 if (bsize < block_size) {
2305 SMB_BIG_UINT factor = block_size/bsize;
2306 bsize = block_size;
2307 dsize /= factor;
2308 dfree /= factor;
2310 if (bsize > block_size) {
2311 SMB_BIG_UINT factor = bsize/block_size;
2312 bsize = block_size;
2313 dsize *= factor;
2314 dfree *= factor;
2316 bytes_per_sector = 512;
2317 sectors_per_unit = bsize/bytes_per_sector;
2319 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2321 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2323 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2324 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2325 SIVAL(pdata,l1_cUnit,dsize);
2326 SIVAL(pdata,l1_cUnitAvail,dfree);
2327 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2328 break;
2331 case SMB_INFO_VOLUME:
2332 /* Return volume name */
2334 * Add volume serial number - hash of a combination of
2335 * the called hostname and the service name.
2337 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2339 * Win2k3 and previous mess this up by sending a name length
2340 * one byte short. I believe only older clients (OS/2 Win9x) use
2341 * this call so try fixing this by adding a terminating null to
2342 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2344 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2345 SCVAL(pdata,l2_vol_cch,len);
2346 data_len = l2_vol_szVolLabel + len;
2347 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2348 (unsigned)st.st_ctime, len, vname));
2349 break;
2351 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2352 case SMB_FS_ATTRIBUTE_INFORMATION:
2355 #if defined(HAVE_SYS_QUOTAS)
2356 quota_flag = FILE_VOLUME_QUOTAS;
2357 #endif
2359 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2360 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2361 FILE_SUPPORTS_OBJECT_IDS|
2362 FILE_UNICODE_ON_DISK|
2363 quota_flag); /* FS ATTRIBUTES */
2365 SIVAL(pdata,4,255); /* Max filename component length */
2366 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2367 and will think we can't do long filenames */
2368 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2369 SIVAL(pdata,8,len);
2370 data_len = 12 + len;
2371 break;
2373 case SMB_QUERY_FS_LABEL_INFO:
2374 case SMB_FS_LABEL_INFORMATION:
2375 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2376 data_len = 4 + len;
2377 SIVAL(pdata,0,len);
2378 break;
2380 case SMB_QUERY_FS_VOLUME_INFO:
2381 case SMB_FS_VOLUME_INFORMATION:
2384 * Add volume serial number - hash of a combination of
2385 * the called hostname and the service name.
2387 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2388 (str_checksum(get_local_machine_name())<<16));
2390 /* Max label len is 32 characters. */
2391 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2392 SIVAL(pdata,12,len);
2393 data_len = 18+len;
2395 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2396 (int)strlen(vname),vname, lp_servicename(snum)));
2397 break;
2399 case SMB_QUERY_FS_SIZE_INFO:
2400 case SMB_FS_SIZE_INFORMATION:
2402 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2403 data_len = 24;
2404 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2405 return(UNIXERROR(ERRHRD,ERRgeneral));
2407 block_size = lp_block_size(snum);
2408 if (bsize < block_size) {
2409 SMB_BIG_UINT factor = block_size/bsize;
2410 bsize = block_size;
2411 dsize /= factor;
2412 dfree /= factor;
2414 if (bsize > block_size) {
2415 SMB_BIG_UINT factor = bsize/block_size;
2416 bsize = block_size;
2417 dsize *= factor;
2418 dfree *= factor;
2420 bytes_per_sector = 512;
2421 sectors_per_unit = bsize/bytes_per_sector;
2422 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2423 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2424 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2425 SBIG_UINT(pdata,0,dsize);
2426 SBIG_UINT(pdata,8,dfree);
2427 SIVAL(pdata,16,sectors_per_unit);
2428 SIVAL(pdata,20,bytes_per_sector);
2429 break;
2432 case SMB_FS_FULL_SIZE_INFORMATION:
2434 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2435 data_len = 32;
2436 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2437 return(UNIXERROR(ERRHRD,ERRgeneral));
2439 block_size = lp_block_size(snum);
2440 if (bsize < block_size) {
2441 SMB_BIG_UINT factor = block_size/bsize;
2442 bsize = block_size;
2443 dsize /= factor;
2444 dfree /= factor;
2446 if (bsize > block_size) {
2447 SMB_BIG_UINT factor = bsize/block_size;
2448 bsize = block_size;
2449 dsize *= factor;
2450 dfree *= factor;
2452 bytes_per_sector = 512;
2453 sectors_per_unit = bsize/bytes_per_sector;
2454 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2455 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2456 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2457 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2458 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2459 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2460 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2461 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2462 break;
2465 case SMB_QUERY_FS_DEVICE_INFO:
2466 case SMB_FS_DEVICE_INFORMATION:
2467 data_len = 8;
2468 SIVAL(pdata,0,0); /* dev type */
2469 SIVAL(pdata,4,0); /* characteristics */
2470 break;
2472 #ifdef HAVE_SYS_QUOTAS
2473 case SMB_FS_QUOTA_INFORMATION:
2475 * what we have to send --metze:
2477 * Unknown1: 24 NULL bytes
2478 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2479 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2480 * Quota Flags: 2 byte :
2481 * Unknown3: 6 NULL bytes
2483 * 48 bytes total
2485 * details for Quota Flags:
2487 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2488 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2489 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2490 * 0x0001 Enable Quotas: enable quota for this fs
2494 /* we need to fake up a fsp here,
2495 * because its not send in this call
2497 files_struct fsp;
2498 SMB_NTQUOTA_STRUCT quotas;
2500 ZERO_STRUCT(fsp);
2501 ZERO_STRUCT(quotas);
2503 fsp.conn = conn;
2504 fsp.fnum = -1;
2506 /* access check */
2507 if (current_user.ut.uid != 0) {
2508 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2509 lp_servicename(SNUM(conn)),conn->user));
2510 return ERROR_DOS(ERRDOS,ERRnoaccess);
2513 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2514 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2515 return ERROR_DOS(ERRSRV,ERRerror);
2518 data_len = 48;
2520 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2522 /* Unknown1 24 NULL bytes*/
2523 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2524 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2525 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2527 /* Default Soft Quota 8 bytes */
2528 SBIG_UINT(pdata,24,quotas.softlim);
2530 /* Default Hard Quota 8 bytes */
2531 SBIG_UINT(pdata,32,quotas.hardlim);
2533 /* Quota flag 2 bytes */
2534 SSVAL(pdata,40,quotas.qflags);
2536 /* Unknown3 6 NULL bytes */
2537 SSVAL(pdata,42,0);
2538 SIVAL(pdata,44,0);
2540 break;
2542 #endif /* HAVE_SYS_QUOTAS */
2543 case SMB_FS_OBJECTID_INFORMATION:
2545 unsigned char objid[16];
2546 memcpy(pdata,create_volume_objectid(conn, objid),16);
2547 data_len = 64;
2548 break;
2552 * Query the version and capabilities of the CIFS UNIX extensions
2553 * in use.
2556 case SMB_QUERY_CIFS_UNIX_INFO:
2557 if (!lp_unix_extensions()) {
2558 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2560 data_len = 12;
2561 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2562 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2563 /* We have POSIX ACLs, pathname and locking capability. */
2564 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2565 CIFS_UNIX_POSIX_ACLS_CAP|
2566 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2567 CIFS_UNIX_FCNTL_LOCKS_CAP|
2568 CIFS_UNIX_EXTATTR_CAP|
2569 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2570 /* Ensure we don't do this on signed or sealed data. */
2571 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2572 )));
2573 break;
2575 case SMB_QUERY_POSIX_FS_INFO:
2577 int rc;
2578 vfs_statvfs_struct svfs;
2580 if (!lp_unix_extensions()) {
2581 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2584 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2586 if (!rc) {
2587 data_len = 56;
2588 SIVAL(pdata,0,svfs.OptimalTransferSize);
2589 SIVAL(pdata,4,svfs.BlockSize);
2590 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2591 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2592 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2593 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2594 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2595 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2596 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2597 #ifdef EOPNOTSUPP
2598 } else if (rc == EOPNOTSUPP) {
2599 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2600 #endif /* EOPNOTSUPP */
2601 } else {
2602 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2603 return ERROR_DOS(ERRSRV,ERRerror);
2605 break;
2608 case SMB_QUERY_POSIX_WHOAMI:
2610 uint32_t flags = 0;
2611 uint32_t sid_bytes;
2612 int i;
2614 if (!lp_unix_extensions()) {
2615 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2618 if (max_data_bytes < 40) {
2619 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2622 /* We ARE guest if global_sid_Builtin_Guests is
2623 * in our list of SIDs.
2625 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2626 current_user.nt_user_token)) {
2627 flags |= SMB_WHOAMI_GUEST;
2630 /* We are NOT guest if global_sid_Authenticated_Users
2631 * is in our list of SIDs.
2633 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2634 current_user.nt_user_token)) {
2635 flags &= ~SMB_WHOAMI_GUEST;
2638 /* NOTE: 8 bytes for UID/GID, irrespective of native
2639 * platform size. This matches
2640 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2642 data_len = 4 /* flags */
2643 + 4 /* flag mask */
2644 + 8 /* uid */
2645 + 8 /* gid */
2646 + 4 /* ngroups */
2647 + 4 /* num_sids */
2648 + 4 /* SID bytes */
2649 + 4 /* pad/reserved */
2650 + (current_user.ut.ngroups * 8)
2651 /* groups list */
2652 + (current_user.nt_user_token->num_sids *
2653 SID_MAX_SIZE)
2654 /* SID list */;
2656 SIVAL(pdata, 0, flags);
2657 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2658 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2659 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2662 if (data_len >= max_data_bytes) {
2663 /* Potential overflow, skip the GIDs and SIDs. */
2665 SIVAL(pdata, 24, 0); /* num_groups */
2666 SIVAL(pdata, 28, 0); /* num_sids */
2667 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2668 SIVAL(pdata, 36, 0); /* reserved */
2670 data_len = 40;
2671 break;
2674 SIVAL(pdata, 24, current_user.ut.ngroups);
2675 SIVAL(pdata, 28,
2676 current_user.nt_user_token->num_sids);
2678 /* We walk the SID list twice, but this call is fairly
2679 * infrequent, and I don't expect that it's performance
2680 * sensitive -- jpeach
2682 for (i = 0, sid_bytes = 0;
2683 i < current_user.nt_user_token->num_sids; ++i) {
2684 sid_bytes +=
2685 sid_size(&current_user.nt_user_token->user_sids[i]);
2688 /* SID list byte count */
2689 SIVAL(pdata, 32, sid_bytes);
2691 /* 4 bytes pad/reserved - must be zero */
2692 SIVAL(pdata, 36, 0);
2693 data_len = 40;
2695 /* GID list */
2696 for (i = 0; i < current_user.ut.ngroups; ++i) {
2697 SBIG_UINT(pdata, data_len,
2698 (SMB_BIG_UINT)current_user.ut.groups[i]);
2699 data_len += 8;
2702 /* SID list */
2703 for (i = 0;
2704 i < current_user.nt_user_token->num_sids; ++i) {
2705 int sid_len =
2706 sid_size(&current_user.nt_user_token->user_sids[i]);
2708 sid_linearize(pdata + data_len, sid_len,
2709 &current_user.nt_user_token->user_sids[i]);
2710 data_len += sid_len;
2713 break;
2716 case SMB_MAC_QUERY_FS_INFO:
2718 * Thursby MAC extension... ONLY on NTFS filesystems
2719 * once we do streams then we don't need this
2721 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2722 data_len = 88;
2723 SIVAL(pdata,84,0x100); /* Don't support mac... */
2724 break;
2726 /* drop through */
2727 default:
2728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2732 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2734 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2736 return -1;
2739 /****************************************************************************
2740 Reply to a TRANS2_SETFSINFO (set filesystem info).
2741 ****************************************************************************/
2743 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2744 char **pparams, int total_params, char **ppdata, int total_data,
2745 unsigned int max_data_bytes)
2747 char *pdata = *ppdata;
2748 char *params = *pparams;
2749 uint16 info_level;
2750 int outsize;
2752 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2754 /* */
2755 if (total_params < 4) {
2756 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2757 total_params));
2758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2761 info_level = SVAL(params,2);
2763 switch(info_level) {
2764 case SMB_SET_CIFS_UNIX_INFO:
2766 uint16 client_unix_major;
2767 uint16 client_unix_minor;
2768 uint32 client_unix_cap_low;
2769 uint32 client_unix_cap_high;
2771 if (!lp_unix_extensions()) {
2772 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2775 /* There should be 12 bytes of capabilities set. */
2776 if (total_data < 8) {
2777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2779 client_unix_major = SVAL(pdata,0);
2780 client_unix_minor = SVAL(pdata,2);
2781 client_unix_cap_low = IVAL(pdata,4);
2782 client_unix_cap_high = IVAL(pdata,8);
2783 /* Just print these values for now. */
2784 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2785 cap_low = 0x%x, cap_high = 0x%x\n",
2786 (unsigned int)client_unix_major,
2787 (unsigned int)client_unix_minor,
2788 (unsigned int)client_unix_cap_low,
2789 (unsigned int)client_unix_cap_high ));
2791 /* Here is where we must switch to posix pathname processing... */
2792 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2793 lp_set_posix_pathnames();
2794 mangle_change_to_posix();
2797 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2798 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2799 /* Client that knows how to do posix locks,
2800 * but not posix open/mkdir operations. Set a
2801 * default type for read/write checks. */
2803 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2806 break;
2808 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2810 NTSTATUS status;
2811 size_t param_len = 0;
2812 size_t data_len = total_data;
2814 if (!lp_unix_extensions()) {
2815 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2818 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2820 status = srv_request_encryption_setup(conn,
2821 (unsigned char **)ppdata,
2822 &data_len,
2823 (unsigned char **)pparams,
2824 &param_len
2827 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2828 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2829 } else if (!NT_STATUS_IS_OK(status)) {
2830 return ERROR_NT(status);
2833 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2835 if (NT_STATUS_IS_OK(status)) {
2836 /* Server-side transport encryption is now *on*. */
2837 status = srv_encryption_start(conn);
2838 if (!NT_STATUS_IS_OK(status)) {
2839 exit_server_cleanly("Failure in setting up encrypted transport");
2842 return -1;
2844 case SMB_FS_QUOTA_INFORMATION:
2846 files_struct *fsp = NULL;
2847 SMB_NTQUOTA_STRUCT quotas;
2849 ZERO_STRUCT(quotas);
2851 /* access check */
2852 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2853 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2854 lp_servicename(SNUM(conn)),conn->user));
2855 return ERROR_DOS(ERRSRV,ERRaccess);
2858 /* note: normaly there're 48 bytes,
2859 * but we didn't use the last 6 bytes for now
2860 * --metze
2862 fsp = file_fsp(params,0);
2863 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2864 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2865 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2868 if (total_data < 42) {
2869 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2870 total_data));
2871 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2874 /* unknown_1 24 NULL bytes in pdata*/
2876 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2877 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2878 #ifdef LARGE_SMB_OFF_T
2879 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2880 #else /* LARGE_SMB_OFF_T */
2881 if ((IVAL(pdata,28) != 0)&&
2882 ((quotas.softlim != 0xFFFFFFFF)||
2883 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2884 /* more than 32 bits? */
2885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2887 #endif /* LARGE_SMB_OFF_T */
2889 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2890 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2891 #ifdef LARGE_SMB_OFF_T
2892 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2893 #else /* LARGE_SMB_OFF_T */
2894 if ((IVAL(pdata,36) != 0)&&
2895 ((quotas.hardlim != 0xFFFFFFFF)||
2896 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2897 /* more than 32 bits? */
2898 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2900 #endif /* LARGE_SMB_OFF_T */
2902 /* quota_flags 2 bytes **/
2903 quotas.qflags = SVAL(pdata,40);
2905 /* unknown_2 6 NULL bytes follow*/
2907 /* now set the quotas */
2908 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2909 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2910 return ERROR_DOS(ERRSRV,ERRerror);
2913 break;
2915 default:
2916 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2917 info_level));
2918 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2919 break;
2923 * sending this reply works fine,
2924 * but I'm not sure it's the same
2925 * like windows do...
2926 * --metze
2928 outsize = set_message(inbuf, outbuf,10,0,True);
2930 return outsize;
2933 #if defined(HAVE_POSIX_ACLS)
2934 /****************************************************************************
2935 Utility function to count the number of entries in a POSIX acl.
2936 ****************************************************************************/
2938 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2940 unsigned int ace_count = 0;
2941 int entry_id = SMB_ACL_FIRST_ENTRY;
2942 SMB_ACL_ENTRY_T entry;
2944 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2945 /* get_next... */
2946 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2947 entry_id = SMB_ACL_NEXT_ENTRY;
2949 ace_count++;
2951 return ace_count;
2954 /****************************************************************************
2955 Utility function to marshall a POSIX acl into wire format.
2956 ****************************************************************************/
2958 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2960 int entry_id = SMB_ACL_FIRST_ENTRY;
2961 SMB_ACL_ENTRY_T entry;
2963 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2964 SMB_ACL_TAG_T tagtype;
2965 SMB_ACL_PERMSET_T permset;
2966 unsigned char perms = 0;
2967 unsigned int own_grp;
2969 /* get_next... */
2970 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2971 entry_id = SMB_ACL_NEXT_ENTRY;
2974 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2975 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2976 return False;
2979 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2980 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2981 return False;
2984 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2985 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2986 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2988 SCVAL(pdata,1,perms);
2990 switch (tagtype) {
2991 case SMB_ACL_USER_OBJ:
2992 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2993 own_grp = (unsigned int)pst->st_uid;
2994 SIVAL(pdata,2,own_grp);
2995 SIVAL(pdata,6,0);
2996 break;
2997 case SMB_ACL_USER:
2999 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3000 if (!puid) {
3001 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3003 own_grp = (unsigned int)*puid;
3004 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3005 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3006 SIVAL(pdata,2,own_grp);
3007 SIVAL(pdata,6,0);
3008 break;
3010 case SMB_ACL_GROUP_OBJ:
3011 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3012 own_grp = (unsigned int)pst->st_gid;
3013 SIVAL(pdata,2,own_grp);
3014 SIVAL(pdata,6,0);
3015 break;
3016 case SMB_ACL_GROUP:
3018 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3019 if (!pgid) {
3020 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3022 own_grp = (unsigned int)*pgid;
3023 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3024 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3025 SIVAL(pdata,2,own_grp);
3026 SIVAL(pdata,6,0);
3027 break;
3029 case SMB_ACL_MASK:
3030 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3031 SIVAL(pdata,2,0xFFFFFFFF);
3032 SIVAL(pdata,6,0xFFFFFFFF);
3033 break;
3034 case SMB_ACL_OTHER:
3035 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3036 SIVAL(pdata,2,0xFFFFFFFF);
3037 SIVAL(pdata,6,0xFFFFFFFF);
3038 break;
3039 default:
3040 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3041 return False;
3043 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3046 return True;
3048 #endif
3050 /****************************************************************************
3051 Store the FILE_UNIX_BASIC info.
3052 ****************************************************************************/
3054 static char *store_file_unix_basic(connection_struct *conn,
3055 char *pdata,
3056 files_struct *fsp,
3057 const SMB_STRUCT_STAT *psbuf)
3059 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3060 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3062 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3063 pdata += 8;
3065 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3066 pdata += 8;
3068 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3069 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3070 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3071 pdata += 24;
3073 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3074 SIVAL(pdata,4,0);
3075 pdata += 8;
3077 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3078 SIVAL(pdata,4,0);
3079 pdata += 8;
3081 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3082 pdata += 4;
3084 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3085 SIVAL(pdata,4,0);
3086 pdata += 8;
3088 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3089 SIVAL(pdata,4,0);
3090 pdata += 8;
3092 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3093 pdata += 8;
3095 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3096 SIVAL(pdata,4,0);
3097 pdata += 8;
3099 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3100 SIVAL(pdata,4,0);
3101 pdata += 8;
3103 return pdata;
3106 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3107 * the chflags(2) (or equivalent) flags.
3109 * XXX: this really should be behind the VFS interface. To do this, we would
3110 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3111 * Each VFS module could then implement it's own mapping as appropriate for the
3112 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3114 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3115 info2_flags_map[] =
3117 #ifdef UF_NODUMP
3118 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3119 #endif
3121 #ifdef UF_IMMUTABLE
3122 { UF_IMMUTABLE, EXT_IMMUTABLE },
3123 #endif
3125 #ifdef UF_APPEND
3126 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3127 #endif
3129 #ifdef UF_HIDDEN
3130 { UF_HIDDEN, EXT_HIDDEN },
3131 #endif
3133 /* Do not remove. We need to guarantee that this array has at least one
3134 * entry to build on HP-UX.
3136 { 0, 0 }
3140 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3141 uint32 *smb_fflags, uint32 *smb_fmask)
3143 #ifdef HAVE_STAT_ST_FLAGS
3144 int i;
3146 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3147 *smb_fmask |= info2_flags_map[i].smb_fflag;
3148 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3149 *smb_fflags |= info2_flags_map[i].smb_fflag;
3152 #endif /* HAVE_STAT_ST_FLAGS */
3155 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3156 const uint32 smb_fflags,
3157 const uint32 smb_fmask,
3158 int *stat_fflags)
3160 #ifdef HAVE_STAT_ST_FLAGS
3161 uint32 max_fmask = 0;
3162 int i;
3164 *stat_fflags = psbuf->st_flags;
3166 /* For each flags requested in smb_fmask, check the state of the
3167 * corresponding flag in smb_fflags and set or clear the matching
3168 * stat flag.
3171 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3172 max_fmask |= info2_flags_map[i].smb_fflag;
3173 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3174 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3175 *stat_fflags |= info2_flags_map[i].stat_fflag;
3176 } else {
3177 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3182 /* If smb_fmask is asking to set any bits that are not supported by
3183 * our flag mappings, we should fail.
3185 if ((smb_fmask & max_fmask) != smb_fmask) {
3186 return False;
3189 return True;
3190 #else
3191 return False;
3192 #endif /* HAVE_STAT_ST_FLAGS */
3196 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3197 * of file flags and birth (create) time.
3199 static char *store_file_unix_basic_info2(connection_struct *conn,
3200 char *pdata,
3201 files_struct *fsp,
3202 const SMB_STRUCT_STAT *psbuf)
3204 uint32 file_flags = 0;
3205 uint32 flags_mask = 0;
3207 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3209 /* Create (birth) time 64 bit */
3210 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3211 pdata += 8;
3213 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3214 SIVAL(pdata, 0, file_flags); /* flags */
3215 SIVAL(pdata, 4, flags_mask); /* mask */
3216 pdata += 8;
3218 return pdata;
3221 /****************************************************************************
3222 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3223 ****************************************************************************/
3225 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3226 unsigned int tran_call,
3227 char **pparams, int total_params, char **ppdata, int total_data,
3228 unsigned int max_data_bytes)
3230 char *params = *pparams;
3231 char *pdata = *ppdata;
3232 unsigned int data_size = 0;
3233 unsigned int param_size = 2;
3234 uint16 info_level;
3235 smb_np_struct *p_pipe = NULL;
3237 if (!params) {
3238 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3241 if (total_params < 4) {
3242 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3245 p_pipe = get_rpc_pipe_p(params,0);
3246 if (p_pipe == NULL) {
3247 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3250 info_level = SVAL(params,2);
3252 *pparams = (char *)SMB_REALLOC(*pparams,2);
3253 if (*pparams == NULL) {
3254 return ERROR_NT(NT_STATUS_NO_MEMORY);
3256 params = *pparams;
3257 SSVAL(params,0,0);
3258 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3259 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3260 if (*ppdata == NULL ) {
3261 return ERROR_NT(NT_STATUS_NO_MEMORY);
3263 pdata = *ppdata;
3265 switch (info_level) {
3266 case SMB_FILE_STANDARD_INFORMATION:
3267 memset(pdata,24,0);
3268 SOFF_T(pdata,0,4096LL);
3269 SIVAL(pdata,16,1);
3270 SIVAL(pdata,20,1);
3271 data_size = 24;
3272 break;
3274 default:
3275 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3278 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3280 return(-1);
3283 /****************************************************************************
3284 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3285 file name or file id).
3286 ****************************************************************************/
3288 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3289 unsigned int tran_call,
3290 char **pparams, int total_params, char **ppdata, int total_data,
3291 unsigned int max_data_bytes)
3293 char *params = *pparams;
3294 char *pdata = *ppdata;
3295 uint16 info_level;
3296 int mode=0;
3297 int nlink;
3298 SMB_OFF_T file_size=0;
3299 SMB_BIG_UINT allocation_size=0;
3300 unsigned int data_size = 0;
3301 unsigned int param_size = 2;
3302 SMB_STRUCT_STAT sbuf;
3303 pstring fname, dos_fname;
3304 char *fullpathname;
3305 char *base_name;
3306 char *p;
3307 SMB_OFF_T pos = 0;
3308 BOOL delete_pending = False;
3309 int len;
3310 time_t create_time, mtime, atime;
3311 struct timespec create_time_ts, mtime_ts, atime_ts;
3312 files_struct *fsp = NULL;
3313 TALLOC_CTX *data_ctx = NULL;
3314 struct ea_list *ea_list = NULL;
3315 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3316 char *lock_data = NULL;
3318 if (!params)
3319 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3321 ZERO_STRUCT(sbuf);
3323 if (tran_call == TRANSACT2_QFILEINFO) {
3324 if (total_params < 4) {
3325 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3328 if (IS_IPC(conn)) {
3329 return call_trans2qpipeinfo(conn,
3330 inbuf,
3331 outbuf,
3332 length,
3333 bufsize,
3334 tran_call,
3335 pparams,
3336 total_params,
3337 ppdata,
3338 total_data,
3339 max_data_bytes);
3342 fsp = file_fsp(params,0);
3343 info_level = SVAL(params,2);
3345 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3347 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3348 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3351 if(fsp && (fsp->fake_file_handle)) {
3353 * This is actually for the QUOTA_FAKE_FILE --metze
3356 pstrcpy(fname, fsp->fsp_name);
3357 /* We know this name is ok, it's already passed the checks. */
3359 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3361 * This is actually a QFILEINFO on a directory
3362 * handle (returned from an NT SMB). NT5.0 seems
3363 * to do this call. JRA.
3365 /* We know this name is ok, it's already passed the checks. */
3366 pstrcpy(fname, fsp->fsp_name);
3368 if (INFO_LEVEL_IS_UNIX(info_level)) {
3369 /* Always do lstat for UNIX calls. */
3370 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3371 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3372 return UNIXERROR(ERRDOS,ERRbadpath);
3374 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3375 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3376 return UNIXERROR(ERRDOS,ERRbadpath);
3379 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3380 } else {
3382 * Original code - this is an open file.
3384 CHECK_FSP(fsp,conn);
3386 pstrcpy(fname, fsp->fsp_name);
3387 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3388 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3389 return(UNIXERROR(ERRDOS,ERRbadfid));
3391 pos = fsp->fh->position_information;
3392 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3393 access_mask = fsp->access_mask;
3395 } else {
3396 NTSTATUS status = NT_STATUS_OK;
3398 /* qpathinfo */
3399 if (total_params < 7) {
3400 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3403 info_level = SVAL(params,0);
3405 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3407 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3408 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3411 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
3412 sizeof(fname), total_params - 6,
3413 STR_TERMINATE, &status);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 return ERROR_NT(status);
3418 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3421 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3423 return ERROR_NT(status);
3426 status = unix_convert(conn, fname, False, NULL, &sbuf);
3427 if (!NT_STATUS_IS_OK(status)) {
3428 return ERROR_NT(status);
3430 status = check_name(conn, fname);
3431 if (!NT_STATUS_IS_OK(status)) {
3432 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3433 return ERROR_NT(status);
3436 if (INFO_LEVEL_IS_UNIX(info_level)) {
3437 /* Always do lstat for UNIX calls. */
3438 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3439 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3440 return UNIXERROR(ERRDOS,ERRbadpath);
3442 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3443 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3444 return UNIXERROR(ERRDOS,ERRbadpath);
3447 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3448 if (delete_pending) {
3449 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3453 nlink = sbuf.st_nlink;
3455 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3456 /* NTFS does not seem to count ".." */
3457 nlink -= 1;
3460 if ((nlink > 0) && delete_pending) {
3461 nlink -= 1;
3464 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3465 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3468 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3469 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3471 p = strrchr_m(fname,'/');
3472 if (!p)
3473 base_name = fname;
3474 else
3475 base_name = p+1;
3477 mode = dos_mode(conn,fname,&sbuf);
3478 if (!mode)
3479 mode = FILE_ATTRIBUTE_NORMAL;
3481 fullpathname = fname;
3482 if (!(mode & aDIR))
3483 file_size = get_file_size(sbuf);
3485 /* Pull out any data sent here before we realloc. */
3486 switch (info_level) {
3487 case SMB_INFO_QUERY_EAS_FROM_LIST:
3489 /* Pull any EA list from the data portion. */
3490 uint32 ea_size;
3492 if (total_data < 4) {
3493 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3495 ea_size = IVAL(pdata,0);
3497 if (total_data > 0 && ea_size != total_data) {
3498 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3499 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3500 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3503 if (!lp_ea_support(SNUM(conn))) {
3504 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3507 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3508 return ERROR_NT(NT_STATUS_NO_MEMORY);
3511 /* Pull out the list of names. */
3512 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3513 if (!ea_list) {
3514 talloc_destroy(data_ctx);
3515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3517 break;
3520 case SMB_QUERY_POSIX_LOCK:
3522 if (fsp == NULL || fsp->fh->fd == -1) {
3523 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3526 if (total_data != POSIX_LOCK_DATA_SIZE) {
3527 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3530 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3531 return ERROR_NT(NT_STATUS_NO_MEMORY);
3534 /* Copy the lock range data. */
3535 lock_data = (char *)TALLOC_MEMDUP(
3536 data_ctx, pdata, total_data);
3537 if (!lock_data) {
3538 talloc_destroy(data_ctx);
3539 return ERROR_NT(NT_STATUS_NO_MEMORY);
3542 default:
3543 break;
3546 *pparams = (char *)SMB_REALLOC(*pparams,2);
3547 if (*pparams == NULL) {
3548 talloc_destroy(data_ctx);
3549 return ERROR_NT(NT_STATUS_NO_MEMORY);
3551 params = *pparams;
3552 SSVAL(params,0,0);
3553 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3554 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3555 if (*ppdata == NULL ) {
3556 talloc_destroy(data_ctx);
3557 return ERROR_NT(NT_STATUS_NO_MEMORY);
3559 pdata = *ppdata;
3561 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3562 mtime_ts = get_mtimespec(&sbuf);
3563 atime_ts = get_atimespec(&sbuf);
3565 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3567 if (fsp) {
3568 if (!null_timespec(fsp->pending_modtime)) {
3569 /* the pending modtime overrides the current modtime */
3570 mtime_ts = fsp->pending_modtime;
3572 } else {
3573 /* Do we have this path open ? */
3574 files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf));
3575 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3576 /* the pending modtime overrides the current modtime */
3577 mtime_ts = fsp1->pending_modtime;
3579 if (fsp1 && fsp1->initial_allocation_size) {
3580 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3584 if (lp_dos_filetime_resolution(SNUM(conn))) {
3585 dos_filetime_timespec(&create_time_ts);
3586 dos_filetime_timespec(&mtime_ts);
3587 dos_filetime_timespec(&atime_ts);
3590 create_time = convert_timespec_to_time_t(create_time_ts);
3591 mtime = convert_timespec_to_time_t(mtime_ts);
3592 atime = convert_timespec_to_time_t(atime_ts);
3594 /* NT expects the name to be in an exact form of the *full*
3595 filename. See the trans2 torture test */
3596 if (strequal(base_name,".")) {
3597 pstrcpy(dos_fname, "\\");
3598 } else {
3599 pstr_sprintf(dos_fname, "\\%s", fname);
3600 string_replace(dos_fname, '/', '\\');
3603 switch (info_level) {
3604 case SMB_INFO_STANDARD:
3605 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3606 data_size = 22;
3607 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3608 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3609 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3610 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3611 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3612 SSVAL(pdata,l1_attrFile,mode);
3613 break;
3615 case SMB_INFO_QUERY_EA_SIZE:
3617 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3618 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3619 data_size = 26;
3620 srv_put_dos_date2(pdata,0,create_time);
3621 srv_put_dos_date2(pdata,4,atime);
3622 srv_put_dos_date2(pdata,8,mtime); /* write time */
3623 SIVAL(pdata,12,(uint32)file_size);
3624 SIVAL(pdata,16,(uint32)allocation_size);
3625 SSVAL(pdata,20,mode);
3626 SIVAL(pdata,22,ea_size);
3627 break;
3630 case SMB_INFO_IS_NAME_VALID:
3631 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3632 if (tran_call == TRANSACT2_QFILEINFO) {
3633 /* os/2 needs this ? really ?*/
3634 return ERROR_DOS(ERRDOS,ERRbadfunc);
3636 data_size = 0;
3637 param_size = 0;
3638 break;
3640 case SMB_INFO_QUERY_EAS_FROM_LIST:
3642 size_t total_ea_len = 0;
3643 struct ea_list *ea_file_list = NULL;
3645 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3647 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3648 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3650 if (!ea_list || (total_ea_len > data_size)) {
3651 talloc_destroy(data_ctx);
3652 data_size = 4;
3653 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3654 break;
3657 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3658 talloc_destroy(data_ctx);
3659 break;
3662 case SMB_INFO_QUERY_ALL_EAS:
3664 /* We have data_size bytes to put EA's into. */
3665 size_t total_ea_len = 0;
3667 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3669 data_ctx = talloc_init("ea_ctx");
3670 if (!data_ctx) {
3671 return ERROR_NT(NT_STATUS_NO_MEMORY);
3674 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3675 if (!ea_list || (total_ea_len > data_size)) {
3676 talloc_destroy(data_ctx);
3677 data_size = 4;
3678 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3679 break;
3682 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3683 talloc_destroy(data_ctx);
3684 break;
3687 case SMB_FILE_BASIC_INFORMATION:
3688 case SMB_QUERY_FILE_BASIC_INFO:
3690 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3691 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3692 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3693 } else {
3694 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3695 data_size = 40;
3696 SIVAL(pdata,36,0);
3698 put_long_date_timespec(pdata,create_time_ts);
3699 put_long_date_timespec(pdata+8,atime_ts);
3700 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3701 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3702 SIVAL(pdata,32,mode);
3704 DEBUG(5,("SMB_QFBI - "));
3705 DEBUG(5,("create: %s ", ctime(&create_time)));
3706 DEBUG(5,("access: %s ", ctime(&atime)));
3707 DEBUG(5,("write: %s ", ctime(&mtime)));
3708 DEBUG(5,("change: %s ", ctime(&mtime)));
3709 DEBUG(5,("mode: %x\n", mode));
3710 break;
3712 case SMB_FILE_STANDARD_INFORMATION:
3713 case SMB_QUERY_FILE_STANDARD_INFO:
3715 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3716 data_size = 24;
3717 SOFF_T(pdata,0,allocation_size);
3718 SOFF_T(pdata,8,file_size);
3719 SIVAL(pdata,16,nlink);
3720 SCVAL(pdata,20,delete_pending?1:0);
3721 SCVAL(pdata,21,(mode&aDIR)?1:0);
3722 SSVAL(pdata,22,0); /* Padding. */
3723 break;
3725 case SMB_FILE_EA_INFORMATION:
3726 case SMB_QUERY_FILE_EA_INFO:
3728 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3729 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3730 data_size = 4;
3731 SIVAL(pdata,0,ea_size);
3732 break;
3735 /* Get the 8.3 name - used if NT SMB was negotiated. */
3736 case SMB_QUERY_FILE_ALT_NAME_INFO:
3737 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3739 pstring short_name;
3741 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3742 pstrcpy(short_name,base_name);
3743 /* Mangle if not already 8.3 */
3744 if(!mangle_is_8_3(short_name, True, conn->params)) {
3745 mangle_map(short_name,True,True,conn->params);
3747 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3748 data_size = 4 + len;
3749 SIVAL(pdata,0,len);
3750 break;
3753 case SMB_QUERY_FILE_NAME_INFO:
3755 this must be *exactly* right for ACLs on mapped drives to work
3757 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3758 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3759 data_size = 4 + len;
3760 SIVAL(pdata,0,len);
3761 break;
3763 case SMB_FILE_ALLOCATION_INFORMATION:
3764 case SMB_QUERY_FILE_ALLOCATION_INFO:
3765 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3766 data_size = 8;
3767 SOFF_T(pdata,0,allocation_size);
3768 break;
3770 case SMB_FILE_END_OF_FILE_INFORMATION:
3771 case SMB_QUERY_FILE_END_OF_FILEINFO:
3772 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3773 data_size = 8;
3774 SOFF_T(pdata,0,file_size);
3775 break;
3777 case SMB_QUERY_FILE_ALL_INFO:
3778 case SMB_FILE_ALL_INFORMATION:
3780 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3781 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3782 put_long_date_timespec(pdata,create_time_ts);
3783 put_long_date_timespec(pdata+8,atime_ts);
3784 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3785 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3786 SIVAL(pdata,32,mode);
3787 SIVAL(pdata,36,0); /* padding. */
3788 pdata += 40;
3789 SOFF_T(pdata,0,allocation_size);
3790 SOFF_T(pdata,8,file_size);
3791 SIVAL(pdata,16,nlink);
3792 SCVAL(pdata,20,delete_pending);
3793 SCVAL(pdata,21,(mode&aDIR)?1:0);
3794 SSVAL(pdata,22,0);
3795 pdata += 24;
3796 SIVAL(pdata,0,ea_size);
3797 pdata += 4; /* EA info */
3798 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3799 SIVAL(pdata,0,len);
3800 pdata += 4 + len;
3801 data_size = PTR_DIFF(pdata,(*ppdata));
3802 break;
3804 case SMB_FILE_INTERNAL_INFORMATION:
3805 /* This should be an index number - looks like
3806 dev/ino to me :-)
3808 I think this causes us to fail the IFSKIT
3809 BasicFileInformationTest. -tpot */
3811 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3812 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3813 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3814 data_size = 8;
3815 break;
3817 case SMB_FILE_ACCESS_INFORMATION:
3818 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3819 SIVAL(pdata,0,access_mask);
3820 data_size = 4;
3821 break;
3823 case SMB_FILE_NAME_INFORMATION:
3824 /* Pathname with leading '\'. */
3826 size_t byte_len;
3827 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3828 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3829 SIVAL(pdata,0,byte_len);
3830 data_size = 4 + byte_len;
3831 break;
3834 case SMB_FILE_DISPOSITION_INFORMATION:
3835 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3836 data_size = 1;
3837 SCVAL(pdata,0,delete_pending);
3838 break;
3840 case SMB_FILE_POSITION_INFORMATION:
3841 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3842 data_size = 8;
3843 SOFF_T(pdata,0,pos);
3844 break;
3846 case SMB_FILE_MODE_INFORMATION:
3847 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3848 SIVAL(pdata,0,mode);
3849 data_size = 4;
3850 break;
3852 case SMB_FILE_ALIGNMENT_INFORMATION:
3853 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3854 SIVAL(pdata,0,0); /* No alignment needed. */
3855 data_size = 4;
3856 break;
3858 #if 0
3860 * NT4 server just returns "invalid query" to this - if we try to answer
3861 * it then NTws gets a BSOD! (tridge).
3862 * W2K seems to want this. JRA.
3864 case SMB_QUERY_FILE_STREAM_INFO:
3865 #endif
3866 case SMB_FILE_STREAM_INFORMATION:
3867 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3868 if (mode & aDIR) {
3869 data_size = 0;
3870 } else {
3871 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3872 SIVAL(pdata,0,0); /* ??? */
3873 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3874 SOFF_T(pdata,8,file_size);
3875 SOFF_T(pdata,16,allocation_size);
3876 data_size = 24 + byte_len;
3878 break;
3880 case SMB_QUERY_COMPRESSION_INFO:
3881 case SMB_FILE_COMPRESSION_INFORMATION:
3882 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3883 SOFF_T(pdata,0,file_size);
3884 SIVAL(pdata,8,0); /* ??? */
3885 SIVAL(pdata,12,0); /* ??? */
3886 data_size = 16;
3887 break;
3889 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3890 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3891 put_long_date_timespec(pdata,create_time_ts);
3892 put_long_date_timespec(pdata+8,atime_ts);
3893 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3894 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3895 SOFF_T(pdata,32,allocation_size);
3896 SOFF_T(pdata,40,file_size);
3897 SIVAL(pdata,48,mode);
3898 SIVAL(pdata,52,0); /* ??? */
3899 data_size = 56;
3900 break;
3902 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3903 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3904 SIVAL(pdata,0,mode);
3905 SIVAL(pdata,4,0);
3906 data_size = 8;
3907 break;
3910 * CIFS UNIX Extensions.
3913 case SMB_QUERY_FILE_UNIX_BASIC:
3915 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3916 data_size = PTR_DIFF(pdata,(*ppdata));
3919 int i;
3920 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3922 for (i=0; i<100; i++)
3923 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3924 DEBUG(4,("\n"));
3927 break;
3929 case SMB_QUERY_FILE_UNIX_INFO2:
3931 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3932 data_size = PTR_DIFF(pdata,(*ppdata));
3935 int i;
3936 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3938 for (i=0; i<100; i++)
3939 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3940 DEBUG(4,("\n"));
3943 break;
3945 case SMB_QUERY_FILE_UNIX_LINK:
3947 pstring buffer;
3949 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3950 #ifdef S_ISLNK
3951 if(!S_ISLNK(sbuf.st_mode))
3952 return(UNIXERROR(ERRSRV,ERRbadlink));
3953 #else
3954 return(UNIXERROR(ERRDOS,ERRbadlink));
3955 #endif
3956 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3957 if (len == -1)
3958 return(UNIXERROR(ERRDOS,ERRnoaccess));
3959 buffer[len] = 0;
3960 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3961 pdata += len;
3962 data_size = PTR_DIFF(pdata,(*ppdata));
3964 break;
3967 #if defined(HAVE_POSIX_ACLS)
3968 case SMB_QUERY_POSIX_ACL:
3970 SMB_ACL_T file_acl = NULL;
3971 SMB_ACL_T def_acl = NULL;
3972 uint16 num_file_acls = 0;
3973 uint16 num_def_acls = 0;
3975 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3976 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3977 } else {
3978 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3981 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3982 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3983 fname ));
3984 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3987 if (S_ISDIR(sbuf.st_mode)) {
3988 if (fsp && fsp->is_directory) {
3989 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3990 } else {
3991 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3993 def_acl = free_empty_sys_acl(conn, def_acl);
3996 num_file_acls = count_acl_entries(conn, file_acl);
3997 num_def_acls = count_acl_entries(conn, def_acl);
3999 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4000 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4001 data_size,
4002 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4003 SMB_POSIX_ACL_HEADER_SIZE) ));
4004 if (file_acl) {
4005 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4007 if (def_acl) {
4008 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4010 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4013 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4014 SSVAL(pdata,2,num_file_acls);
4015 SSVAL(pdata,4,num_def_acls);
4016 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4017 if (file_acl) {
4018 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4020 if (def_acl) {
4021 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4023 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4025 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4026 if (file_acl) {
4027 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4029 if (def_acl) {
4030 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4032 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4035 if (file_acl) {
4036 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4038 if (def_acl) {
4039 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4041 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4042 break;
4044 #endif
4047 case SMB_QUERY_POSIX_LOCK:
4049 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4050 SMB_BIG_UINT count;
4051 SMB_BIG_UINT offset;
4052 uint32 lock_pid;
4053 enum brl_type lock_type;
4055 if (total_data != POSIX_LOCK_DATA_SIZE) {
4056 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4059 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4060 case POSIX_LOCK_TYPE_READ:
4061 lock_type = READ_LOCK;
4062 break;
4063 case POSIX_LOCK_TYPE_WRITE:
4064 lock_type = WRITE_LOCK;
4065 break;
4066 case POSIX_LOCK_TYPE_UNLOCK:
4067 default:
4068 /* There's no point in asking for an unlock... */
4069 talloc_destroy(data_ctx);
4070 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4073 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4074 #if defined(HAVE_LONGLONG)
4075 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4076 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4077 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4078 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4079 #else /* HAVE_LONGLONG */
4080 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4081 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4082 #endif /* HAVE_LONGLONG */
4084 status = query_lock(fsp,
4085 &lock_pid,
4086 &count,
4087 &offset,
4088 &lock_type,
4089 POSIX_LOCK);
4091 if (ERROR_WAS_LOCK_DENIED(status)) {
4092 /* Here we need to report who has it locked... */
4093 data_size = POSIX_LOCK_DATA_SIZE;
4095 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4096 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4097 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4098 #if defined(HAVE_LONGLONG)
4099 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4100 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4101 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4102 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4103 #else /* HAVE_LONGLONG */
4104 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4105 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4106 #endif /* HAVE_LONGLONG */
4108 } else if (NT_STATUS_IS_OK(status)) {
4109 /* For success we just return a copy of what we sent
4110 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4111 data_size = POSIX_LOCK_DATA_SIZE;
4112 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4113 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4114 } else {
4115 return ERROR_NT(status);
4117 break;
4120 default:
4121 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4124 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4126 return(-1);
4129 /****************************************************************************
4130 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4131 code.
4132 ****************************************************************************/
4134 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4136 SMB_STRUCT_STAT sbuf1, sbuf2;
4137 pstring last_component_oldname;
4138 pstring last_component_newname;
4139 NTSTATUS status = NT_STATUS_OK;
4141 ZERO_STRUCT(sbuf1);
4142 ZERO_STRUCT(sbuf2);
4144 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4145 if (!NT_STATUS_IS_OK(status)) {
4146 return status;
4149 status = check_name(conn, oldname);
4150 if (!NT_STATUS_IS_OK(status)) {
4151 return status;
4154 /* source must already exist. */
4155 if (!VALID_STAT(sbuf1)) {
4156 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4159 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4160 if (!NT_STATUS_IS_OK(status)) {
4161 return status;
4164 status = check_name(conn, newname);
4165 if (!NT_STATUS_IS_OK(status)) {
4166 return status;
4169 /* Disallow if newname already exists. */
4170 if (VALID_STAT(sbuf2)) {
4171 return NT_STATUS_OBJECT_NAME_COLLISION;
4174 /* No links from a directory. */
4175 if (S_ISDIR(sbuf1.st_mode)) {
4176 return NT_STATUS_FILE_IS_A_DIRECTORY;
4179 /* Ensure this is within the share. */
4180 status = reduce_name(conn, oldname);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 return status;
4185 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4187 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4188 status = map_nt_error_from_unix(errno);
4189 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4190 nt_errstr(status), newname, oldname));
4193 return status;
4196 /****************************************************************************
4197 Deal with setting the time from any of the setfilepathinfo functions.
4198 ****************************************************************************/
4200 static NTSTATUS smb_set_file_time(connection_struct *conn,
4201 files_struct *fsp,
4202 const char *fname,
4203 const SMB_STRUCT_STAT *psbuf,
4204 struct timespec ts[2])
4206 uint32 action =
4207 FILE_NOTIFY_CHANGE_LAST_ACCESS
4208 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4211 if (!VALID_STAT(*psbuf)) {
4212 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4215 /* get some defaults (no modifications) if any info is zero or -1. */
4216 if (null_timespec(ts[0])) {
4217 ts[0] = get_atimespec(psbuf);
4218 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4221 if (null_timespec(ts[1])) {
4222 ts[1] = get_mtimespec(psbuf);
4223 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4226 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4227 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4230 * Try and set the times of this file if
4231 * they are different from the current values.
4235 struct timespec mts = get_mtimespec(psbuf);
4236 struct timespec ats = get_atimespec(psbuf);
4237 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4238 return NT_STATUS_OK;
4242 if(fsp != NULL) {
4244 * This was a setfileinfo on an open file.
4245 * NT does this a lot. We also need to
4246 * set the time here, as it can be read by
4247 * FindFirst/FindNext and with the patch for bug #2045
4248 * in smbd/fileio.c it ensures that this timestamp is
4249 * kept sticky even after a write. We save the request
4250 * away and will set it on file close and after a write. JRA.
4253 if (!null_timespec(ts[1])) {
4254 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4255 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4256 fsp_set_pending_modtime(fsp, ts[1]);
4260 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4262 if(file_ntimes(conn, fname, ts)!=0) {
4263 return map_nt_error_from_unix(errno);
4265 if (action != 0) {
4266 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4268 return NT_STATUS_OK;
4271 /****************************************************************************
4272 Deal with setting the dosmode from any of the setfilepathinfo functions.
4273 ****************************************************************************/
4275 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4276 const char *fname,
4277 SMB_STRUCT_STAT *psbuf,
4278 uint32 dosmode)
4280 if (!VALID_STAT(*psbuf)) {
4281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4284 if (dosmode) {
4285 if (S_ISDIR(psbuf->st_mode)) {
4286 dosmode |= aDIR;
4287 } else {
4288 dosmode &= ~aDIR;
4292 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4294 /* check the mode isn't different, before changing it */
4295 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4297 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4298 fname, (unsigned int)dosmode ));
4300 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4301 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4302 fname, strerror(errno)));
4303 return map_nt_error_from_unix(errno);
4306 return NT_STATUS_OK;
4309 /****************************************************************************
4310 Deal with setting the size from any of the setfilepathinfo functions.
4311 ****************************************************************************/
4313 static NTSTATUS smb_set_file_size(connection_struct *conn,
4314 struct smb_request *req,
4315 files_struct *fsp,
4316 const char *fname,
4317 SMB_STRUCT_STAT *psbuf,
4318 SMB_OFF_T size)
4320 NTSTATUS status = NT_STATUS_OK;
4321 files_struct *new_fsp = NULL;
4323 if (!VALID_STAT(*psbuf)) {
4324 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4327 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4329 if (size == get_file_size(*psbuf)) {
4330 return NT_STATUS_OK;
4333 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4334 fname, (double)size ));
4336 if (fsp && fsp->fh->fd != -1) {
4337 /* Handle based call. */
4338 if (vfs_set_filelen(fsp, size) == -1) {
4339 return map_nt_error_from_unix(errno);
4341 return NT_STATUS_OK;
4344 status = open_file_ntcreate(conn, req, fname, psbuf,
4345 FILE_WRITE_DATA,
4346 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4347 FILE_OPEN,
4349 FILE_ATTRIBUTE_NORMAL,
4350 FORCE_OPLOCK_BREAK_TO_NONE,
4351 NULL, &new_fsp);
4353 if (!NT_STATUS_IS_OK(status)) {
4354 /* NB. We check for open_was_deferred in the caller. */
4355 return status;
4358 if (vfs_set_filelen(new_fsp, size) == -1) {
4359 status = map_nt_error_from_unix(errno);
4360 close_file(new_fsp,NORMAL_CLOSE);
4361 return status;
4364 close_file(new_fsp,NORMAL_CLOSE);
4365 return NT_STATUS_OK;
4368 /****************************************************************************
4369 Deal with SMB_INFO_SET_EA.
4370 ****************************************************************************/
4372 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4373 const char *pdata,
4374 int total_data,
4375 files_struct *fsp,
4376 const char *fname)
4378 struct ea_list *ea_list = NULL;
4379 TALLOC_CTX *ctx = NULL;
4380 NTSTATUS status = NT_STATUS_OK;
4382 if (total_data < 10) {
4384 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4385 length. They seem to have no effect. Bug #3212. JRA */
4387 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4388 /* We're done. We only get EA info in this call. */
4389 return NT_STATUS_OK;
4392 return NT_STATUS_INVALID_PARAMETER;
4395 if (IVAL(pdata,0) > total_data) {
4396 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4397 IVAL(pdata,0), (unsigned int)total_data));
4398 return NT_STATUS_INVALID_PARAMETER;
4401 ctx = talloc_init("SMB_INFO_SET_EA");
4402 if (!ctx) {
4403 return NT_STATUS_NO_MEMORY;
4405 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4406 if (!ea_list) {
4407 talloc_destroy(ctx);
4408 return NT_STATUS_INVALID_PARAMETER;
4410 status = set_ea(conn, fsp, fname, ea_list);
4411 talloc_destroy(ctx);
4413 return status;
4416 /****************************************************************************
4417 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4418 ****************************************************************************/
4420 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4421 const char *pdata,
4422 int total_data,
4423 files_struct *fsp,
4424 const char *fname,
4425 SMB_STRUCT_STAT *psbuf)
4427 NTSTATUS status = NT_STATUS_OK;
4428 BOOL delete_on_close;
4429 uint32 dosmode = 0;
4431 if (total_data < 1) {
4432 return NT_STATUS_INVALID_PARAMETER;
4435 if (fsp == NULL) {
4436 return NT_STATUS_INVALID_HANDLE;
4439 delete_on_close = (CVAL(pdata,0) ? True : False);
4440 dosmode = dos_mode(conn, fname, psbuf);
4442 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4443 "delete_on_close = %u\n",
4444 fsp->fsp_name,
4445 (unsigned int)dosmode,
4446 (unsigned int)delete_on_close ));
4448 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 return status;
4454 /* The set is across all open files on this dev/inode pair. */
4455 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4456 return NT_STATUS_ACCESS_DENIED;
4458 return NT_STATUS_OK;
4461 /****************************************************************************
4462 Deal with SMB_FILE_POSITION_INFORMATION.
4463 ****************************************************************************/
4465 static NTSTATUS smb_file_position_information(connection_struct *conn,
4466 const char *pdata,
4467 int total_data,
4468 files_struct *fsp)
4470 SMB_BIG_UINT position_information;
4472 if (total_data < 8) {
4473 return NT_STATUS_INVALID_PARAMETER;
4476 if (fsp == NULL) {
4477 /* Ignore on pathname based set. */
4478 return NT_STATUS_OK;
4481 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4482 #ifdef LARGE_SMB_OFF_T
4483 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4484 #else /* LARGE_SMB_OFF_T */
4485 if (IVAL(pdata,4) != 0) {
4486 /* more than 32 bits? */
4487 return NT_STATUS_INVALID_PARAMETER;
4489 #endif /* LARGE_SMB_OFF_T */
4491 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4492 fsp->fsp_name, (double)position_information ));
4493 fsp->fh->position_information = position_information;
4494 return NT_STATUS_OK;
4497 /****************************************************************************
4498 Deal with SMB_FILE_MODE_INFORMATION.
4499 ****************************************************************************/
4501 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4502 const char *pdata,
4503 int total_data)
4505 uint32 mode;
4507 if (total_data < 4) {
4508 return NT_STATUS_INVALID_PARAMETER;
4510 mode = IVAL(pdata,0);
4511 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4512 return NT_STATUS_INVALID_PARAMETER;
4514 return NT_STATUS_OK;
4517 /****************************************************************************
4518 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4519 ****************************************************************************/
4521 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4522 char *inbuf,
4523 const char *pdata,
4524 int total_data,
4525 const char *fname)
4527 pstring link_target;
4528 const char *newname = fname;
4529 NTSTATUS status = NT_STATUS_OK;
4531 /* Set a symbolic link. */
4532 /* Don't allow this if follow links is false. */
4534 if (total_data == 0) {
4535 return NT_STATUS_INVALID_PARAMETER;
4538 if (!lp_symlinks(SNUM(conn))) {
4539 return NT_STATUS_ACCESS_DENIED;
4542 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4543 sizeof(link_target), total_data, STR_TERMINATE);
4545 /* !widelinks forces the target path to be within the share. */
4546 /* This means we can interpret the target as a pathname. */
4547 if (!lp_widelinks(SNUM(conn))) {
4548 pstring rel_name;
4549 char *last_dirp = NULL;
4551 if (*link_target == '/') {
4552 /* No absolute paths allowed. */
4553 return NT_STATUS_ACCESS_DENIED;
4555 pstrcpy(rel_name, newname);
4556 last_dirp = strrchr_m(rel_name, '/');
4557 if (last_dirp) {
4558 last_dirp[1] = '\0';
4559 } else {
4560 pstrcpy(rel_name, "./");
4562 pstrcat(rel_name, link_target);
4564 status = check_name(conn, rel_name);
4565 if (!NT_STATUS_IS_OK(status)) {
4566 return status;
4570 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4571 newname, link_target ));
4573 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4574 return map_nt_error_from_unix(errno);
4577 return NT_STATUS_OK;
4580 /****************************************************************************
4581 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4582 ****************************************************************************/
4584 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4585 char *inbuf,
4586 char *outbuf,
4587 const char *pdata,
4588 int total_data,
4589 pstring fname)
4591 pstring oldname;
4592 NTSTATUS status = NT_STATUS_OK;
4594 /* Set a hard link. */
4595 if (total_data == 0) {
4596 return NT_STATUS_INVALID_PARAMETER;
4599 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4600 sizeof(oldname), total_data, STR_TERMINATE, &status);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 return status;
4605 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 return status;
4610 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4611 fname, oldname));
4613 return hardlink_internals(conn, oldname, fname);
4616 /****************************************************************************
4617 Deal with SMB_FILE_RENAME_INFORMATION.
4618 ****************************************************************************/
4620 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4621 struct smb_request *req,
4622 char *inbuf,
4623 char *outbuf,
4624 const char *pdata,
4625 int total_data,
4626 files_struct *fsp,
4627 pstring fname)
4629 BOOL overwrite;
4630 uint32 root_fid;
4631 uint32 len;
4632 pstring newname;
4633 pstring base_name;
4634 BOOL dest_has_wcard = False;
4635 NTSTATUS status = NT_STATUS_OK;
4636 char *p;
4638 if (total_data < 13) {
4639 return NT_STATUS_INVALID_PARAMETER;
4642 overwrite = (CVAL(pdata,0) ? True : False);
4643 root_fid = IVAL(pdata,4);
4644 len = IVAL(pdata,8);
4646 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4647 return NT_STATUS_INVALID_PARAMETER;
4650 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4651 sizeof(newname), len, 0, &status,
4652 &dest_has_wcard);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 return status;
4657 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 return status;
4662 /* Check the new name has no '/' characters. */
4663 if (strchr_m(newname, '/')) {
4664 return NT_STATUS_NOT_SUPPORTED;
4667 /* Create the base directory. */
4668 pstrcpy(base_name, fname);
4669 p = strrchr_m(base_name, '/');
4670 if (p) {
4671 p[1] = '\0';
4672 } else {
4673 pstrcpy(base_name, "./");
4675 /* Append the new name. */
4676 pstrcat(base_name, newname);
4678 if (fsp) {
4679 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4680 fsp->fnum, fsp->fsp_name, base_name ));
4681 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4682 } else {
4683 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4684 fname, newname ));
4685 status = rename_internals(conn, req, fname, base_name, 0,
4686 overwrite, False, dest_has_wcard);
4689 return status;
4692 /****************************************************************************
4693 Deal with SMB_SET_POSIX_ACL.
4694 ****************************************************************************/
4696 #if defined(HAVE_POSIX_ACLS)
4697 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4698 const char *pdata,
4699 int total_data,
4700 files_struct *fsp,
4701 const char *fname,
4702 SMB_STRUCT_STAT *psbuf)
4704 uint16 posix_acl_version;
4705 uint16 num_file_acls;
4706 uint16 num_def_acls;
4707 BOOL valid_file_acls = True;
4708 BOOL valid_def_acls = True;
4710 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4711 return NT_STATUS_INVALID_PARAMETER;
4713 posix_acl_version = SVAL(pdata,0);
4714 num_file_acls = SVAL(pdata,2);
4715 num_def_acls = SVAL(pdata,4);
4717 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4718 valid_file_acls = False;
4719 num_file_acls = 0;
4722 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4723 valid_def_acls = False;
4724 num_def_acls = 0;
4727 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4728 return NT_STATUS_INVALID_PARAMETER;
4731 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4732 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4733 return NT_STATUS_INVALID_PARAMETER;
4736 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4737 fname ? fname : fsp->fsp_name,
4738 (unsigned int)num_file_acls,
4739 (unsigned int)num_def_acls));
4741 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4742 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4743 return map_nt_error_from_unix(errno);
4746 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4747 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4748 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4749 return map_nt_error_from_unix(errno);
4751 return NT_STATUS_OK;
4753 #endif
4755 /****************************************************************************
4756 Deal with SMB_SET_POSIX_LOCK.
4757 ****************************************************************************/
4759 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4760 char *inbuf,
4761 int length,
4762 const char *pdata,
4763 int total_data,
4764 files_struct *fsp)
4766 SMB_BIG_UINT count;
4767 SMB_BIG_UINT offset;
4768 uint32 lock_pid;
4769 BOOL blocking_lock = False;
4770 enum brl_type lock_type;
4771 NTSTATUS status = NT_STATUS_OK;
4773 if (fsp == NULL || fsp->fh->fd == -1) {
4774 return NT_STATUS_INVALID_HANDLE;
4777 if (total_data != POSIX_LOCK_DATA_SIZE) {
4778 return NT_STATUS_INVALID_PARAMETER;
4781 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4782 case POSIX_LOCK_TYPE_READ:
4783 lock_type = READ_LOCK;
4784 break;
4785 case POSIX_LOCK_TYPE_WRITE:
4786 /* Return the right POSIX-mappable error code for files opened read-only. */
4787 if (!fsp->can_write) {
4788 return NT_STATUS_INVALID_HANDLE;
4790 lock_type = WRITE_LOCK;
4791 break;
4792 case POSIX_LOCK_TYPE_UNLOCK:
4793 lock_type = UNLOCK_LOCK;
4794 break;
4795 default:
4796 return NT_STATUS_INVALID_PARAMETER;
4799 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4800 blocking_lock = False;
4801 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4802 blocking_lock = True;
4803 } else {
4804 return NT_STATUS_INVALID_PARAMETER;
4807 if (!lp_blocking_locks(SNUM(conn))) {
4808 blocking_lock = False;
4811 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4812 #if defined(HAVE_LONGLONG)
4813 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4814 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4815 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4816 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4817 #else /* HAVE_LONGLONG */
4818 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4819 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4820 #endif /* HAVE_LONGLONG */
4822 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4823 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4824 fsp->fsp_name,
4825 (unsigned int)lock_type,
4826 (unsigned int)lock_pid,
4827 (double)count,
4828 (double)offset ));
4830 if (lock_type == UNLOCK_LOCK) {
4831 status = do_unlock(smbd_messaging_context(),
4832 fsp,
4833 lock_pid,
4834 count,
4835 offset,
4836 POSIX_LOCK);
4837 } else {
4838 uint32 block_smbpid;
4840 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4841 fsp,
4842 lock_pid,
4843 count,
4844 offset,
4845 lock_type,
4846 POSIX_LOCK,
4847 blocking_lock,
4848 &status,
4849 &block_smbpid);
4851 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4853 * A blocking lock was requested. Package up
4854 * this smb into a queued request and push it
4855 * onto the blocking lock queue.
4857 if(push_blocking_lock_request(br_lck,
4858 inbuf, length,
4859 fsp,
4860 -1, /* infinite timeout. */
4862 lock_pid,
4863 lock_type,
4864 POSIX_LOCK,
4865 offset,
4866 count,
4867 block_smbpid)) {
4868 TALLOC_FREE(br_lck);
4869 return status;
4872 TALLOC_FREE(br_lck);
4875 return status;
4878 /****************************************************************************
4879 Deal with SMB_INFO_STANDARD.
4880 ****************************************************************************/
4882 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4883 const char *pdata,
4884 int total_data,
4885 files_struct *fsp,
4886 const char *fname,
4887 const SMB_STRUCT_STAT *psbuf)
4889 struct timespec ts[2];
4891 if (total_data < 12) {
4892 return NT_STATUS_INVALID_PARAMETER;
4895 /* access time */
4896 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4897 /* write time */
4898 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4900 DEBUG(10,("smb_set_info_standard: file %s\n",
4901 fname ? fname : fsp->fsp_name ));
4903 return smb_set_file_time(conn,
4904 fsp,
4905 fname,
4906 psbuf,
4907 ts);
4910 /****************************************************************************
4911 Deal with SMB_SET_FILE_BASIC_INFO.
4912 ****************************************************************************/
4914 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4915 const char *pdata,
4916 int total_data,
4917 files_struct *fsp,
4918 const char *fname,
4919 SMB_STRUCT_STAT *psbuf)
4921 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4922 struct timespec write_time;
4923 struct timespec changed_time;
4924 uint32 dosmode = 0;
4925 struct timespec ts[2];
4926 NTSTATUS status = NT_STATUS_OK;
4928 if (total_data < 36) {
4929 return NT_STATUS_INVALID_PARAMETER;
4932 /* Set the attributes */
4933 dosmode = IVAL(pdata,32);
4934 status = smb_set_file_dosmode(conn,
4935 fname,
4936 psbuf,
4937 dosmode);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 return status;
4942 /* Ignore create time at offset pdata. */
4944 /* access time */
4945 ts[0] = interpret_long_date(pdata+8);
4947 write_time = interpret_long_date(pdata+16);
4948 changed_time = interpret_long_date(pdata+24);
4950 /* mtime */
4951 ts[1] = timespec_min(&write_time, &changed_time);
4953 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4954 ts[1] = write_time;
4957 /* Prefer a defined time to an undefined one. */
4958 if (null_timespec(ts[1])) {
4959 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4962 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4963 fname ? fname : fsp->fsp_name ));
4965 return smb_set_file_time(conn,
4966 fsp,
4967 fname,
4968 psbuf,
4969 ts);
4972 /****************************************************************************
4973 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4974 ****************************************************************************/
4976 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4977 struct smb_request *req,
4978 const char *pdata,
4979 int total_data,
4980 files_struct *fsp,
4981 const char *fname,
4982 SMB_STRUCT_STAT *psbuf)
4984 SMB_BIG_UINT allocation_size = 0;
4985 NTSTATUS status = NT_STATUS_OK;
4986 files_struct *new_fsp = NULL;
4988 if (!VALID_STAT(*psbuf)) {
4989 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4992 if (total_data < 8) {
4993 return NT_STATUS_INVALID_PARAMETER;
4996 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4997 #ifdef LARGE_SMB_OFF_T
4998 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4999 #else /* LARGE_SMB_OFF_T */
5000 if (IVAL(pdata,4) != 0) {
5001 /* more than 32 bits? */
5002 return NT_STATUS_INVALID_PARAMETER;
5004 #endif /* LARGE_SMB_OFF_T */
5006 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5007 fname, (double)allocation_size ));
5009 if (allocation_size) {
5010 allocation_size = smb_roundup(conn, allocation_size);
5013 if(allocation_size == get_file_size(*psbuf)) {
5014 return NT_STATUS_OK;
5017 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5018 fname, (double)allocation_size ));
5020 if (fsp && fsp->fh->fd != -1) {
5021 /* Open file handle. */
5022 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5023 return map_nt_error_from_unix(errno);
5025 return NT_STATUS_OK;
5028 /* Pathname or stat or directory file. */
5030 status = open_file_ntcreate(conn, req, fname, psbuf,
5031 FILE_WRITE_DATA,
5032 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5033 FILE_OPEN,
5035 FILE_ATTRIBUTE_NORMAL,
5036 FORCE_OPLOCK_BREAK_TO_NONE,
5037 NULL, &new_fsp);
5039 if (!NT_STATUS_IS_OK(status)) {
5040 /* NB. We check for open_was_deferred in the caller. */
5041 return status;
5043 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5044 status = map_nt_error_from_unix(errno);
5045 close_file(new_fsp,NORMAL_CLOSE);
5046 return status;
5049 close_file(new_fsp,NORMAL_CLOSE);
5050 return NT_STATUS_OK;
5053 /****************************************************************************
5054 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5055 ****************************************************************************/
5057 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5058 struct smb_request *req,
5059 const char *pdata,
5060 int total_data,
5061 files_struct *fsp,
5062 const char *fname,
5063 SMB_STRUCT_STAT *psbuf)
5065 SMB_OFF_T size;
5067 if (total_data < 8) {
5068 return NT_STATUS_INVALID_PARAMETER;
5071 size = IVAL(pdata,0);
5072 #ifdef LARGE_SMB_OFF_T
5073 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5074 #else /* LARGE_SMB_OFF_T */
5075 if (IVAL(pdata,4) != 0) {
5076 /* more than 32 bits? */
5077 return NT_STATUS_INVALID_PARAMETER;
5079 #endif /* LARGE_SMB_OFF_T */
5080 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5081 "file %s to %.0f\n", fname, (double)size ));
5083 return smb_set_file_size(conn, req,
5084 fsp,
5085 fname,
5086 psbuf,
5087 size);
5090 /****************************************************************************
5091 Allow a UNIX info mknod.
5092 ****************************************************************************/
5094 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5095 const char *pdata,
5096 int total_data,
5097 const char *fname,
5098 SMB_STRUCT_STAT *psbuf)
5100 uint32 file_type = IVAL(pdata,56);
5101 #if defined(HAVE_MAKEDEV)
5102 uint32 dev_major = IVAL(pdata,60);
5103 uint32 dev_minor = IVAL(pdata,68);
5104 #endif
5105 SMB_DEV_T dev = (SMB_DEV_T)0;
5106 uint32 raw_unixmode = IVAL(pdata,84);
5107 NTSTATUS status;
5108 mode_t unixmode;
5110 if (total_data < 100) {
5111 return NT_STATUS_INVALID_PARAMETER;
5114 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 return status;
5119 #if defined(HAVE_MAKEDEV)
5120 dev = makedev(dev_major, dev_minor);
5121 #endif
5123 switch (file_type) {
5124 #if defined(S_IFIFO)
5125 case UNIX_TYPE_FIFO:
5126 unixmode |= S_IFIFO;
5127 break;
5128 #endif
5129 #if defined(S_IFSOCK)
5130 case UNIX_TYPE_SOCKET:
5131 unixmode |= S_IFSOCK;
5132 break;
5133 #endif
5134 #if defined(S_IFCHR)
5135 case UNIX_TYPE_CHARDEV:
5136 unixmode |= S_IFCHR;
5137 break;
5138 #endif
5139 #if defined(S_IFBLK)
5140 case UNIX_TYPE_BLKDEV:
5141 unixmode |= S_IFBLK;
5142 break;
5143 #endif
5144 default:
5145 return NT_STATUS_INVALID_PARAMETER;
5148 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5149 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5151 /* Ok - do the mknod. */
5152 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5153 return map_nt_error_from_unix(errno);
5156 /* If any of the other "set" calls fail we
5157 * don't want to end up with a half-constructed mknod.
5160 if (lp_inherit_perms(SNUM(conn))) {
5161 inherit_access_acl(
5162 conn, parent_dirname(fname),
5163 fname, unixmode);
5166 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5167 status = map_nt_error_from_unix(errno);
5168 SMB_VFS_UNLINK(conn,fname);
5169 return status;
5171 return NT_STATUS_OK;
5174 /****************************************************************************
5175 Deal with SMB_SET_FILE_UNIX_BASIC.
5176 ****************************************************************************/
5178 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5179 struct smb_request *req,
5180 const char *pdata,
5181 int total_data,
5182 files_struct *fsp,
5183 const char *fname,
5184 SMB_STRUCT_STAT *psbuf)
5186 struct timespec ts[2];
5187 uint32 raw_unixmode;
5188 mode_t unixmode;
5189 SMB_OFF_T size = 0;
5190 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5191 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5192 NTSTATUS status = NT_STATUS_OK;
5193 BOOL delete_on_fail = False;
5194 enum perm_type ptype;
5196 if (total_data < 100) {
5197 return NT_STATUS_INVALID_PARAMETER;
5200 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5201 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5202 size=IVAL(pdata,0); /* first 8 Bytes are size */
5203 #ifdef LARGE_SMB_OFF_T
5204 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5205 #else /* LARGE_SMB_OFF_T */
5206 if (IVAL(pdata,4) != 0) {
5207 /* more than 32 bits? */
5208 return NT_STATUS_INVALID_PARAMETER;
5210 #endif /* LARGE_SMB_OFF_T */
5213 ts[0] = interpret_long_date(pdata+24); /* access_time */
5214 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5215 set_owner = (uid_t)IVAL(pdata,40);
5216 set_grp = (gid_t)IVAL(pdata,48);
5217 raw_unixmode = IVAL(pdata,84);
5219 if (VALID_STAT(*psbuf)) {
5220 if (S_ISDIR(psbuf->st_mode)) {
5221 ptype = PERM_EXISTING_DIR;
5222 } else {
5223 ptype = PERM_EXISTING_FILE;
5225 } else {
5226 ptype = PERM_NEW_FILE;
5229 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 return status;
5234 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5235 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5236 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5238 if (!VALID_STAT(*psbuf)) {
5240 * The only valid use of this is to create character and block
5241 * devices, and named pipes. This is deprecated (IMHO) and
5242 * a new info level should be used for mknod. JRA.
5245 status = smb_unix_mknod(conn,
5246 pdata,
5247 total_data,
5248 fname,
5249 psbuf);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 return status;
5254 /* Ensure we don't try and change anything else. */
5255 raw_unixmode = SMB_MODE_NO_CHANGE;
5256 size = get_file_size(*psbuf);
5257 ts[0] = get_atimespec(psbuf);
5258 ts[1] = get_mtimespec(psbuf);
5260 * We continue here as we might want to change the
5261 * owner uid/gid.
5263 delete_on_fail = True;
5266 #if 1
5267 /* Horrible backwards compatibility hack as an old server bug
5268 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5269 * */
5271 if (!size) {
5272 size = get_file_size(*psbuf);
5274 #endif
5277 * Deal with the UNIX specific mode set.
5280 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5281 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5282 (unsigned int)unixmode, fname ));
5283 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5284 return map_nt_error_from_unix(errno);
5289 * Deal with the UNIX specific uid set.
5292 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5293 int ret;
5295 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5296 (unsigned int)set_owner, fname ));
5298 if (S_ISLNK(psbuf->st_mode)) {
5299 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5300 } else {
5301 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5304 if (ret != 0) {
5305 status = map_nt_error_from_unix(errno);
5306 if (delete_on_fail) {
5307 SMB_VFS_UNLINK(conn,fname);
5309 return status;
5314 * Deal with the UNIX specific gid set.
5317 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5318 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5319 (unsigned int)set_owner, fname ));
5320 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5321 status = map_nt_error_from_unix(errno);
5322 if (delete_on_fail) {
5323 SMB_VFS_UNLINK(conn,fname);
5325 return status;
5329 /* Deal with any size changes. */
5331 status = smb_set_file_size(conn, req,
5332 fsp,
5333 fname,
5334 psbuf,
5335 size);
5336 if (!NT_STATUS_IS_OK(status)) {
5337 return status;
5340 /* Deal with any time changes. */
5342 return smb_set_file_time(conn,
5343 fsp,
5344 fname,
5345 psbuf,
5346 ts);
5349 /****************************************************************************
5350 Deal with SMB_SET_FILE_UNIX_INFO2.
5351 ****************************************************************************/
5353 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5354 struct smb_request *req,
5355 const char *pdata,
5356 int total_data,
5357 files_struct *fsp,
5358 const char *fname,
5359 SMB_STRUCT_STAT *psbuf)
5361 NTSTATUS status;
5362 uint32 smb_fflags;
5363 uint32 smb_fmask;
5365 if (total_data < 116) {
5366 return NT_STATUS_INVALID_PARAMETER;
5369 /* Start by setting all the fields that are common between UNIX_BASIC
5370 * and UNIX_INFO2.
5372 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5373 fsp, fname, psbuf);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 return status;
5378 smb_fflags = IVAL(pdata, 108);
5379 smb_fmask = IVAL(pdata, 112);
5381 /* NB: We should only attempt to alter the file flags if the client
5382 * sends a non-zero mask.
5384 if (smb_fmask != 0) {
5385 int stat_fflags = 0;
5387 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5388 &stat_fflags)) {
5389 /* Client asked to alter a flag we don't understand. */
5390 return NT_STATUS_INVALID_PARAMETER;
5393 if (fsp && fsp->fh->fd != -1) {
5394 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5395 return NT_STATUS_NOT_SUPPORTED;
5396 } else {
5397 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5398 return map_nt_error_from_unix(errno);
5403 /* XXX: need to add support for changing the create_time here. You
5404 * can do this for paths on Darwin with setattrlist(2). The right way
5405 * to hook this up is probably by extending the VFS utimes interface.
5408 return NT_STATUS_OK;
5411 /****************************************************************************
5412 Create a directory with POSIX semantics.
5413 ****************************************************************************/
5415 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5416 struct smb_request *req,
5417 char **ppdata,
5418 int total_data,
5419 const char *fname,
5420 SMB_STRUCT_STAT *psbuf,
5421 int *pdata_return_size)
5423 NTSTATUS status = NT_STATUS_OK;
5424 uint32 raw_unixmode = 0;
5425 uint32 mod_unixmode = 0;
5426 mode_t unixmode = (mode_t)0;
5427 files_struct *fsp = NULL;
5428 uint16 info_level_return = 0;
5429 int info;
5430 char *pdata = *ppdata;
5432 if (total_data < 18) {
5433 return NT_STATUS_INVALID_PARAMETER;
5436 raw_unixmode = IVAL(pdata,8);
5437 /* Next 4 bytes are not yet defined. */
5439 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5440 if (!NT_STATUS_IS_OK(status)) {
5441 return status;
5444 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5446 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5447 fname, (unsigned int)unixmode ));
5449 status = open_directory(conn, req,
5450 fname,
5451 psbuf,
5452 FILE_READ_ATTRIBUTES, /* Just a stat open */
5453 FILE_SHARE_NONE, /* Ignored for stat opens */
5454 FILE_CREATE,
5456 mod_unixmode,
5457 &info,
5458 &fsp);
5460 if (NT_STATUS_IS_OK(status)) {
5461 close_file(fsp, NORMAL_CLOSE);
5464 info_level_return = SVAL(pdata,16);
5466 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5467 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5468 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5469 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5470 } else {
5471 *pdata_return_size = 12;
5474 /* Realloc the data size */
5475 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5476 if (*ppdata == NULL) {
5477 *pdata_return_size = 0;
5478 return NT_STATUS_NO_MEMORY;
5480 pdata = *ppdata;
5482 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5483 SSVAL(pdata,2,0); /* No fnum. */
5484 SIVAL(pdata,4,info); /* Was directory created. */
5486 switch (info_level_return) {
5487 case SMB_QUERY_FILE_UNIX_BASIC:
5488 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5489 SSVAL(pdata,10,0); /* Padding. */
5490 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5491 break;
5492 case SMB_QUERY_FILE_UNIX_INFO2:
5493 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5494 SSVAL(pdata,10,0); /* Padding. */
5495 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5496 break;
5497 default:
5498 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5499 SSVAL(pdata,10,0); /* Padding. */
5500 break;
5503 return status;
5506 /****************************************************************************
5507 Open/Create a file with POSIX semantics.
5508 ****************************************************************************/
5510 static NTSTATUS smb_posix_open(connection_struct *conn,
5511 struct smb_request *req,
5512 char **ppdata,
5513 int total_data,
5514 const char *fname,
5515 SMB_STRUCT_STAT *psbuf,
5516 int *pdata_return_size)
5518 BOOL extended_oplock_granted = False;
5519 char *pdata = *ppdata;
5520 uint32 flags = 0;
5521 uint32 wire_open_mode = 0;
5522 uint32 raw_unixmode = 0;
5523 uint32 mod_unixmode = 0;
5524 uint32 create_disp = 0;
5525 uint32 access_mask = 0;
5526 uint32 create_options = 0;
5527 NTSTATUS status = NT_STATUS_OK;
5528 mode_t unixmode = (mode_t)0;
5529 files_struct *fsp = NULL;
5530 int oplock_request = 0;
5531 int info = 0;
5532 uint16 info_level_return = 0;
5534 if (total_data < 18) {
5535 return NT_STATUS_INVALID_PARAMETER;
5538 flags = IVAL(pdata,0);
5539 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5540 if (oplock_request) {
5541 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5544 wire_open_mode = IVAL(pdata,4);
5546 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5547 return smb_posix_mkdir(conn, req,
5548 ppdata,
5549 total_data,
5550 fname,
5551 psbuf,
5552 pdata_return_size);
5555 switch (wire_open_mode & SMB_ACCMODE) {
5556 case SMB_O_RDONLY:
5557 access_mask = FILE_READ_DATA;
5558 break;
5559 case SMB_O_WRONLY:
5560 access_mask = FILE_WRITE_DATA;
5561 break;
5562 case SMB_O_RDWR:
5563 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5564 break;
5565 default:
5566 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5567 (unsigned int)wire_open_mode ));
5568 return NT_STATUS_INVALID_PARAMETER;
5571 wire_open_mode &= ~SMB_ACCMODE;
5573 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5574 create_disp = FILE_CREATE;
5575 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5576 create_disp = FILE_OVERWRITE_IF;
5577 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5578 create_disp = FILE_OPEN_IF;
5579 } else {
5580 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5581 (unsigned int)wire_open_mode ));
5582 return NT_STATUS_INVALID_PARAMETER;
5585 raw_unixmode = IVAL(pdata,8);
5586 /* Next 4 bytes are not yet defined. */
5588 status = unix_perms_from_wire(conn,
5589 psbuf,
5590 raw_unixmode,
5591 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5592 &unixmode);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 return status;
5598 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5600 if (wire_open_mode & SMB_O_SYNC) {
5601 create_options |= FILE_WRITE_THROUGH;
5603 if (wire_open_mode & SMB_O_APPEND) {
5604 access_mask |= FILE_APPEND_DATA;
5606 if (wire_open_mode & SMB_O_DIRECT) {
5607 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5610 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5611 fname,
5612 (unsigned int)wire_open_mode,
5613 (unsigned int)unixmode ));
5615 status = open_file_ntcreate(conn, req,
5616 fname,
5617 psbuf,
5618 access_mask,
5619 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5620 create_disp,
5621 0, /* no create options yet. */
5622 mod_unixmode,
5623 oplock_request,
5624 &info,
5625 &fsp);
5627 if (!NT_STATUS_IS_OK(status)) {
5628 return status;
5631 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5632 extended_oplock_granted = True;
5635 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5636 extended_oplock_granted = True;
5639 info_level_return = SVAL(pdata,16);
5641 /* Allocate the correct return size. */
5643 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5644 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5645 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5646 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5647 } else {
5648 *pdata_return_size = 12;
5651 /* Realloc the data size */
5652 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5653 if (*ppdata == NULL) {
5654 close_file(fsp,ERROR_CLOSE);
5655 *pdata_return_size = 0;
5656 return NT_STATUS_NO_MEMORY;
5658 pdata = *ppdata;
5660 if (extended_oplock_granted) {
5661 if (flags & REQUEST_BATCH_OPLOCK) {
5662 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5663 } else {
5664 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5666 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5667 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5668 } else {
5669 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5672 SSVAL(pdata,2,fsp->fnum);
5673 SIVAL(pdata,4,info); /* Was file created etc. */
5675 switch (info_level_return) {
5676 case SMB_QUERY_FILE_UNIX_BASIC:
5677 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5678 SSVAL(pdata,10,0); /* padding. */
5679 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5680 break;
5681 case SMB_QUERY_FILE_UNIX_INFO2:
5682 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5683 SSVAL(pdata,10,0); /* padding. */
5684 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5685 break;
5686 default:
5687 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5688 SSVAL(pdata,10,0); /* padding. */
5689 break;
5691 return NT_STATUS_OK;
5694 /****************************************************************************
5695 Delete a file with POSIX semantics.
5696 ****************************************************************************/
5698 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5699 struct smb_request *req,
5700 const char *pdata,
5701 int total_data,
5702 const char *fname,
5703 SMB_STRUCT_STAT *psbuf)
5705 NTSTATUS status = NT_STATUS_OK;
5706 files_struct *fsp = NULL;
5707 uint16 flags = 0;
5708 int info = 0;
5710 if (total_data < 2) {
5711 return NT_STATUS_INVALID_PARAMETER;
5714 flags = SVAL(pdata,0);
5716 if (!VALID_STAT(*psbuf)) {
5717 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5720 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5721 !VALID_STAT_OF_DIR(*psbuf)) {
5722 return NT_STATUS_NOT_A_DIRECTORY;
5725 DEBUG(10,("smb_posix_unlink: %s %s\n",
5726 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5727 fname));
5729 if (VALID_STAT_OF_DIR(*psbuf)) {
5730 status = open_directory(conn, req,
5731 fname,
5732 psbuf,
5733 DELETE_ACCESS,
5734 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5735 FILE_OPEN,
5736 FILE_DELETE_ON_CLOSE,
5737 FILE_FLAG_POSIX_SEMANTICS|0777,
5738 &info,
5739 &fsp);
5740 } else {
5741 char del = 1;
5743 status = open_file_ntcreate(conn, req,
5744 fname,
5745 psbuf,
5746 DELETE_ACCESS,
5747 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5748 FILE_OPEN,
5750 FILE_FLAG_POSIX_SEMANTICS|0777,
5751 0, /* No oplock, but break existing ones. */
5752 &info,
5753 &fsp);
5755 * For file opens we must set the delete on close
5756 * after the open.
5759 if (!NT_STATUS_IS_OK(status)) {
5760 return status;
5763 status = smb_set_file_disposition_info(conn,
5764 &del,
5766 fsp,
5767 fname,
5768 psbuf);
5771 if (!NT_STATUS_IS_OK(status)) {
5772 return status;
5774 return close_file(fsp, NORMAL_CLOSE);
5777 /****************************************************************************
5778 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5779 ****************************************************************************/
5781 static int call_trans2setfilepathinfo(connection_struct *conn,
5782 struct smb_request *req,
5783 char *inbuf, char *outbuf, int length,
5784 int bufsize,
5785 unsigned int tran_call,
5786 char **pparams, int total_params, char **ppdata, int total_data,
5787 unsigned int max_data_bytes)
5789 char *params = *pparams;
5790 char *pdata = *ppdata;
5791 uint16 info_level;
5792 SMB_STRUCT_STAT sbuf;
5793 pstring fname;
5794 files_struct *fsp = NULL;
5795 NTSTATUS status = NT_STATUS_OK;
5796 int data_return_size = 0;
5798 if (!params) {
5799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5802 ZERO_STRUCT(sbuf);
5804 if (tran_call == TRANSACT2_SETFILEINFO) {
5805 if (total_params < 4) {
5806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5809 fsp = file_fsp(params,0);
5810 info_level = SVAL(params,2);
5812 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5814 * This is actually a SETFILEINFO on a directory
5815 * handle (returned from an NT SMB). NT5.0 seems
5816 * to do this call. JRA.
5818 pstrcpy(fname, fsp->fsp_name);
5819 if (INFO_LEVEL_IS_UNIX(info_level)) {
5820 /* Always do lstat for UNIX calls. */
5821 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5822 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5823 return UNIXERROR(ERRDOS,ERRbadpath);
5825 } else {
5826 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5827 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5828 return UNIXERROR(ERRDOS,ERRbadpath);
5831 } else if (fsp && fsp->print_file) {
5833 * Doing a DELETE_ON_CLOSE should cancel a print job.
5835 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5836 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5838 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5840 SSVAL(params,0,0);
5841 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5842 return(-1);
5843 } else
5844 return (UNIXERROR(ERRDOS,ERRbadpath));
5845 } else {
5847 * Original code - this is an open file.
5849 CHECK_FSP(fsp,conn);
5851 pstrcpy(fname, fsp->fsp_name);
5853 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5854 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5855 return(UNIXERROR(ERRDOS,ERRbadfid));
5858 } else {
5859 /* set path info */
5860 if (total_params < 7) {
5861 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5864 info_level = SVAL(params,0);
5865 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
5866 sizeof(fname), total_params - 6, STR_TERMINATE,
5867 &status);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 return ERROR_NT(status);
5872 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5873 if (!NT_STATUS_IS_OK(status)) {
5874 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5875 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5877 return ERROR_NT(status);
5880 status = unix_convert(conn, fname, False, NULL, &sbuf);
5881 if (!NT_STATUS_IS_OK(status)) {
5882 return ERROR_NT(status);
5885 status = check_name(conn, fname);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 return ERROR_NT(status);
5890 if (INFO_LEVEL_IS_UNIX(info_level)) {
5892 * For CIFS UNIX extensions the target name may not exist.
5895 /* Always do lstat for UNIX calls. */
5896 SMB_VFS_LSTAT(conn,fname,&sbuf);
5898 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5899 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5900 return UNIXERROR(ERRDOS,ERRbadpath);
5904 if (!CAN_WRITE(conn)) {
5905 return ERROR_DOS(ERRSRV,ERRaccess);
5908 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5909 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5912 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5913 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5915 /* Realloc the parameter size */
5916 *pparams = (char *)SMB_REALLOC(*pparams,2);
5917 if (*pparams == NULL) {
5918 return ERROR_NT(NT_STATUS_NO_MEMORY);
5920 params = *pparams;
5922 SSVAL(params,0,0);
5924 if (fsp && !null_timespec(fsp->pending_modtime)) {
5925 /* the pending modtime overrides the current modtime */
5926 set_mtimespec(&sbuf, fsp->pending_modtime);
5929 switch (info_level) {
5931 case SMB_INFO_STANDARD:
5933 status = smb_set_info_standard(conn,
5934 pdata,
5935 total_data,
5936 fsp,
5937 fname,
5938 &sbuf);
5939 break;
5942 case SMB_INFO_SET_EA:
5944 status = smb_info_set_ea(conn,
5945 pdata,
5946 total_data,
5947 fsp,
5948 fname);
5949 break;
5952 case SMB_SET_FILE_BASIC_INFO:
5953 case SMB_FILE_BASIC_INFORMATION:
5955 status = smb_set_file_basic_info(conn,
5956 pdata,
5957 total_data,
5958 fsp,
5959 fname,
5960 &sbuf);
5961 break;
5964 case SMB_FILE_ALLOCATION_INFORMATION:
5965 case SMB_SET_FILE_ALLOCATION_INFO:
5967 status = smb_set_file_allocation_info(conn, req,
5968 pdata,
5969 total_data,
5970 fsp,
5971 fname,
5972 &sbuf);
5973 break;
5976 case SMB_FILE_END_OF_FILE_INFORMATION:
5977 case SMB_SET_FILE_END_OF_FILE_INFO:
5979 status = smb_set_file_end_of_file_info(conn, req,
5980 pdata,
5981 total_data,
5982 fsp,
5983 fname,
5984 &sbuf);
5985 break;
5988 case SMB_FILE_DISPOSITION_INFORMATION:
5989 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5991 #if 0
5992 /* JRA - We used to just ignore this on a path ?
5993 * Shouldn't this be invalid level on a pathname
5994 * based call ?
5996 if (tran_call != TRANSACT2_SETFILEINFO) {
5997 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5999 #endif
6000 status = smb_set_file_disposition_info(conn,
6001 pdata,
6002 total_data,
6003 fsp,
6004 fname,
6005 &sbuf);
6006 break;
6009 case SMB_FILE_POSITION_INFORMATION:
6011 status = smb_file_position_information(conn,
6012 pdata,
6013 total_data,
6014 fsp);
6015 break;
6018 /* From tridge Samba4 :
6019 * MODE_INFORMATION in setfileinfo (I have no
6020 * idea what "mode information" on a file is - it takes a value of 0,
6021 * 2, 4 or 6. What could it be?).
6024 case SMB_FILE_MODE_INFORMATION:
6026 status = smb_file_mode_information(conn,
6027 pdata,
6028 total_data);
6029 break;
6033 * CIFS UNIX extensions.
6036 case SMB_SET_FILE_UNIX_BASIC:
6038 status = smb_set_file_unix_basic(conn, req,
6039 pdata,
6040 total_data,
6041 fsp,
6042 fname,
6043 &sbuf);
6044 break;
6047 case SMB_SET_FILE_UNIX_INFO2:
6049 status = smb_set_file_unix_info2(conn, req,
6050 pdata,
6051 total_data,
6052 fsp,
6053 fname,
6054 &sbuf);
6055 break;
6058 case SMB_SET_FILE_UNIX_LINK:
6060 if (tran_call != TRANSACT2_SETPATHINFO) {
6061 /* We must have a pathname for this. */
6062 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6064 status = smb_set_file_unix_link(conn,
6065 inbuf,
6066 pdata,
6067 total_data,
6068 fname);
6069 break;
6072 case SMB_SET_FILE_UNIX_HLINK:
6074 if (tran_call != TRANSACT2_SETPATHINFO) {
6075 /* We must have a pathname for this. */
6076 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6078 status = smb_set_file_unix_hlink(conn,
6079 inbuf,
6080 outbuf,
6081 pdata,
6082 total_data,
6083 fname);
6084 break;
6087 case SMB_FILE_RENAME_INFORMATION:
6089 status = smb_file_rename_information(conn, req,
6090 inbuf,
6091 outbuf,
6092 pdata,
6093 total_data,
6094 fsp,
6095 fname);
6096 break;
6099 #if defined(HAVE_POSIX_ACLS)
6100 case SMB_SET_POSIX_ACL:
6102 status = smb_set_posix_acl(conn,
6103 pdata,
6104 total_data,
6105 fsp,
6106 fname,
6107 &sbuf);
6108 break;
6110 #endif
6112 case SMB_SET_POSIX_LOCK:
6114 if (tran_call != TRANSACT2_SETFILEINFO) {
6115 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6117 status = smb_set_posix_lock(conn,
6118 inbuf,
6119 length,
6120 pdata,
6121 total_data,
6122 fsp);
6123 break;
6126 case SMB_POSIX_PATH_OPEN:
6128 if (tran_call != TRANSACT2_SETPATHINFO) {
6129 /* We must have a pathname for this. */
6130 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6133 status = smb_posix_open(conn, req,
6134 ppdata,
6135 total_data,
6136 fname,
6137 &sbuf,
6138 &data_return_size);
6139 break;
6142 case SMB_POSIX_PATH_UNLINK:
6144 if (tran_call != TRANSACT2_SETPATHINFO) {
6145 /* We must have a pathname for this. */
6146 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6149 status = smb_posix_unlink(conn, req,
6150 pdata,
6151 total_data,
6152 fname,
6153 &sbuf);
6154 break;
6157 default:
6158 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6162 if (!NT_STATUS_IS_OK(status)) {
6163 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6164 /* We have re-scheduled this call. */
6165 return -1;
6167 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6168 /* We have re-scheduled this call. */
6169 return -1;
6171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6172 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6174 return ERROR_NT(status);
6177 SSVAL(params,0,0);
6178 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6180 return -1;
6183 /****************************************************************************
6184 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6185 ****************************************************************************/
6187 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6188 char **pparams, int total_params, char **ppdata, int total_data,
6189 unsigned int max_data_bytes)
6191 char *params = *pparams;
6192 char *pdata = *ppdata;
6193 pstring directory;
6194 SMB_STRUCT_STAT sbuf;
6195 NTSTATUS status = NT_STATUS_OK;
6196 struct ea_list *ea_list = NULL;
6198 if (!CAN_WRITE(conn))
6199 return ERROR_DOS(ERRSRV,ERRaccess);
6201 if (total_params < 5) {
6202 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6205 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, &params[4],
6206 sizeof(directory), total_params - 4, STR_TERMINATE,
6207 &status);
6208 if (!NT_STATUS_IS_OK(status)) {
6209 return ERROR_NT(status);
6212 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6214 status = unix_convert(conn, directory, False, NULL, &sbuf);
6215 if (!NT_STATUS_IS_OK(status)) {
6216 return ERROR_NT(status);
6219 status = check_name(conn, directory);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6222 return ERROR_NT(status);
6225 /* Any data in this call is an EA list. */
6226 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6227 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6231 * OS/2 workplace shell seems to send SET_EA requests of "null"
6232 * length (4 bytes containing IVAL 4).
6233 * They seem to have no effect. Bug #3212. JRA.
6236 if (total_data != 4) {
6237 if (total_data < 10) {
6238 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6241 if (IVAL(pdata,0) > total_data) {
6242 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6243 IVAL(pdata,0), (unsigned int)total_data));
6244 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6247 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6248 total_data - 4);
6249 if (!ea_list) {
6250 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6252 } else if (IVAL(pdata,0) != 4) {
6253 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6256 status = create_directory(conn, directory);
6258 if (!NT_STATUS_IS_OK(status)) {
6259 return ERROR_NT(status);
6262 /* Try and set any given EA. */
6263 if (ea_list) {
6264 status = set_ea(conn, NULL, directory, ea_list);
6265 if (!NT_STATUS_IS_OK(status)) {
6266 return ERROR_NT(status);
6270 /* Realloc the parameter and data sizes */
6271 *pparams = (char *)SMB_REALLOC(*pparams,2);
6272 if(*pparams == NULL) {
6273 return ERROR_NT(NT_STATUS_NO_MEMORY);
6275 params = *pparams;
6277 SSVAL(params,0,0);
6279 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6281 return(-1);
6284 /****************************************************************************
6285 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6286 We don't actually do this - we just send a null response.
6287 ****************************************************************************/
6289 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6290 char **pparams, int total_params, char **ppdata, int total_data,
6291 unsigned int max_data_bytes)
6293 static uint16 fnf_handle = 257;
6294 char *params = *pparams;
6295 uint16 info_level;
6297 if (total_params < 6) {
6298 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6301 info_level = SVAL(params,4);
6302 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6304 switch (info_level) {
6305 case 1:
6306 case 2:
6307 break;
6308 default:
6309 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6312 /* Realloc the parameter and data sizes */
6313 *pparams = (char *)SMB_REALLOC(*pparams,6);
6314 if (*pparams == NULL) {
6315 return ERROR_NT(NT_STATUS_NO_MEMORY);
6317 params = *pparams;
6319 SSVAL(params,0,fnf_handle);
6320 SSVAL(params,2,0); /* No changes */
6321 SSVAL(params,4,0); /* No EA errors */
6323 fnf_handle++;
6325 if(fnf_handle == 0)
6326 fnf_handle = 257;
6328 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6330 return(-1);
6333 /****************************************************************************
6334 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6335 changes). Currently this does nothing.
6336 ****************************************************************************/
6338 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6339 char **pparams, int total_params, char **ppdata, int total_data,
6340 unsigned int max_data_bytes)
6342 char *params = *pparams;
6344 DEBUG(3,("call_trans2findnotifynext\n"));
6346 /* Realloc the parameter and data sizes */
6347 *pparams = (char *)SMB_REALLOC(*pparams,4);
6348 if (*pparams == NULL) {
6349 return ERROR_NT(NT_STATUS_NO_MEMORY);
6351 params = *pparams;
6353 SSVAL(params,0,0); /* No changes */
6354 SSVAL(params,2,0); /* No EA errors */
6356 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6358 return(-1);
6361 /****************************************************************************
6362 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6363 ****************************************************************************/
6365 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6366 char **pparams, int total_params, char **ppdata, int total_data,
6367 unsigned int max_data_bytes)
6369 char *params = *pparams;
6370 pstring pathname;
6371 int reply_size = 0;
6372 int max_referral_level;
6373 NTSTATUS status = NT_STATUS_OK;
6375 DEBUG(10,("call_trans2getdfsreferral\n"));
6377 if (total_params < 3) {
6378 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6381 max_referral_level = SVAL(params,0);
6383 if(!lp_host_msdfs())
6384 return ERROR_DOS(ERRDOS,ERRbadfunc);
6386 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, &params[2],
6387 sizeof(pathname), total_params - 2, STR_TERMINATE);
6388 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6389 return ERROR_NT(status);
6391 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6392 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6394 return(-1);
6397 #define LMCAT_SPL 0x53
6398 #define LMFUNC_GETJOBID 0x60
6400 /****************************************************************************
6401 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6402 ****************************************************************************/
6404 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6405 char **pparams, int total_params, char **ppdata, int total_data,
6406 unsigned int max_data_bytes)
6408 char *pdata = *ppdata;
6409 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6411 /* check for an invalid fid before proceeding */
6413 if (!fsp)
6414 return(ERROR_DOS(ERRDOS,ERRbadfid));
6416 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6417 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6418 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6419 if (*ppdata == NULL) {
6420 return ERROR_NT(NT_STATUS_NO_MEMORY);
6422 pdata = *ppdata;
6424 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6425 CAN ACCEPT THIS IN UNICODE. JRA. */
6427 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6428 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6429 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6430 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6431 return(-1);
6432 } else {
6433 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6434 return ERROR_DOS(ERRSRV,ERRerror);
6438 /****************************************************************************
6439 Reply to a SMBfindclose (stop trans2 directory search).
6440 ****************************************************************************/
6442 int reply_findclose(connection_struct *conn,
6443 char *inbuf,char *outbuf,int length,int bufsize)
6445 int outsize = 0;
6446 int dptr_num=SVALS(inbuf,smb_vwv0);
6447 START_PROFILE(SMBfindclose);
6449 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6451 dptr_close(&dptr_num);
6453 outsize = set_message(inbuf, outbuf,0,0,False);
6455 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6457 END_PROFILE(SMBfindclose);
6458 return(outsize);
6461 /****************************************************************************
6462 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6463 ****************************************************************************/
6465 int reply_findnclose(connection_struct *conn,
6466 char *inbuf,char *outbuf,int length,int bufsize)
6468 int outsize = 0;
6469 int dptr_num= -1;
6470 START_PROFILE(SMBfindnclose);
6472 dptr_num = SVAL(inbuf,smb_vwv0);
6474 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6476 /* We never give out valid handles for a
6477 findnotifyfirst - so any dptr_num is ok here.
6478 Just ignore it. */
6480 outsize = set_message(inbuf, outbuf,0,0,False);
6482 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6484 END_PROFILE(SMBfindnclose);
6485 return(outsize);
6488 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6489 struct trans_state *state,
6490 char *inbuf, char *outbuf, int size, int bufsize)
6492 int outsize;
6494 if (Protocol >= PROTOCOL_NT1) {
6495 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6498 /* Now we must call the relevant TRANS2 function */
6499 switch(state->call) {
6500 case TRANSACT2_OPEN:
6502 START_PROFILE(Trans2_open);
6503 outsize = call_trans2open(
6504 conn, req, inbuf, outbuf, bufsize,
6505 &state->param, state->total_param,
6506 &state->data, state->total_data,
6507 state->max_data_return);
6508 END_PROFILE(Trans2_open);
6509 break;
6512 case TRANSACT2_FINDFIRST:
6514 START_PROFILE(Trans2_findfirst);
6515 outsize = call_trans2findfirst(
6516 conn, inbuf, outbuf, bufsize,
6517 &state->param, state->total_param,
6518 &state->data, state->total_data,
6519 state->max_data_return);
6520 END_PROFILE(Trans2_findfirst);
6521 break;
6524 case TRANSACT2_FINDNEXT:
6526 START_PROFILE(Trans2_findnext);
6527 outsize = call_trans2findnext(
6528 conn, inbuf, outbuf, size, bufsize,
6529 &state->param, state->total_param,
6530 &state->data, state->total_data,
6531 state->max_data_return);
6532 END_PROFILE(Trans2_findnext);
6533 break;
6536 case TRANSACT2_QFSINFO:
6538 START_PROFILE(Trans2_qfsinfo);
6539 outsize = call_trans2qfsinfo(
6540 conn, inbuf, outbuf, size, bufsize,
6541 &state->param, state->total_param,
6542 &state->data, state->total_data,
6543 state->max_data_return);
6544 END_PROFILE(Trans2_qfsinfo);
6545 break;
6548 case TRANSACT2_SETFSINFO:
6550 START_PROFILE(Trans2_setfsinfo);
6551 outsize = call_trans2setfsinfo(
6552 conn, inbuf, outbuf, size, bufsize,
6553 &state->param, state->total_param,
6554 &state->data, state->total_data,
6555 state->max_data_return);
6556 END_PROFILE(Trans2_setfsinfo);
6557 break;
6560 case TRANSACT2_QPATHINFO:
6561 case TRANSACT2_QFILEINFO:
6563 START_PROFILE(Trans2_qpathinfo);
6564 outsize = call_trans2qfilepathinfo(
6565 conn, inbuf, outbuf, size, bufsize, state->call,
6566 &state->param, state->total_param,
6567 &state->data, state->total_data,
6568 state->max_data_return);
6569 END_PROFILE(Trans2_qpathinfo);
6570 break;
6573 case TRANSACT2_SETPATHINFO:
6574 case TRANSACT2_SETFILEINFO:
6576 START_PROFILE(Trans2_setpathinfo);
6577 outsize = call_trans2setfilepathinfo(
6578 conn, req, inbuf, outbuf, size, bufsize, state->call,
6579 &state->param, state->total_param,
6580 &state->data, state->total_data,
6581 state->max_data_return);
6582 END_PROFILE(Trans2_setpathinfo);
6583 break;
6586 case TRANSACT2_FINDNOTIFYFIRST:
6588 START_PROFILE(Trans2_findnotifyfirst);
6589 outsize = call_trans2findnotifyfirst(
6590 conn, inbuf, outbuf, size, bufsize,
6591 &state->param, state->total_param,
6592 &state->data, state->total_data,
6593 state->max_data_return);
6594 END_PROFILE(Trans2_findnotifyfirst);
6595 break;
6598 case TRANSACT2_FINDNOTIFYNEXT:
6600 START_PROFILE(Trans2_findnotifynext);
6601 outsize = call_trans2findnotifynext(
6602 conn, inbuf, outbuf, size, bufsize,
6603 &state->param, state->total_param,
6604 &state->data, state->total_data,
6605 state->max_data_return);
6606 END_PROFILE(Trans2_findnotifynext);
6607 break;
6610 case TRANSACT2_MKDIR:
6612 START_PROFILE(Trans2_mkdir);
6613 outsize = call_trans2mkdir(
6614 conn, inbuf, outbuf, size, bufsize,
6615 &state->param, state->total_param,
6616 &state->data, state->total_data,
6617 state->max_data_return);
6618 END_PROFILE(Trans2_mkdir);
6619 break;
6622 case TRANSACT2_GET_DFS_REFERRAL:
6624 START_PROFILE(Trans2_get_dfs_referral);
6625 outsize = call_trans2getdfsreferral(
6626 conn, inbuf, outbuf, size, bufsize,
6627 &state->param, state->total_param,
6628 &state->data, state->total_data,
6629 state->max_data_return);
6630 END_PROFILE(Trans2_get_dfs_referral);
6631 break;
6634 case TRANSACT2_IOCTL:
6636 START_PROFILE(Trans2_ioctl);
6637 outsize = call_trans2ioctl(
6638 conn, inbuf, outbuf, size, bufsize,
6639 &state->param, state->total_param,
6640 &state->data, state->total_data,
6641 state->max_data_return);
6642 END_PROFILE(Trans2_ioctl);
6643 break;
6646 default:
6647 /* Error in request */
6648 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6649 outsize = ERROR_DOS(ERRSRV,ERRerror);
6652 return outsize;
6655 /****************************************************************************
6656 Reply to a SMBtrans2.
6657 ****************************************************************************/
6659 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6660 int size, int bufsize)
6662 int outsize = 0;
6663 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6664 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6665 unsigned int psoff = SVAL(inbuf, smb_psoff);
6666 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6667 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6668 struct trans_state *state;
6669 NTSTATUS result;
6671 START_PROFILE(SMBtrans2);
6673 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6674 if (!NT_STATUS_IS_OK(result)) {
6675 DEBUG(2, ("Got invalid trans2 request: %s\n",
6676 nt_errstr(result)));
6677 END_PROFILE(SMBtrans2);
6678 return ERROR_NT(result);
6681 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6682 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6683 && (tran_call != TRANSACT2_QFILEINFO)) {
6684 END_PROFILE(SMBtrans2);
6685 return ERROR_DOS(ERRSRV,ERRaccess);
6688 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6689 DEBUG(0, ("talloc failed\n"));
6690 END_PROFILE(SMBtrans2);
6691 return ERROR_NT(NT_STATUS_NO_MEMORY);
6694 state->cmd = SMBtrans2;
6696 state->mid = SVAL(inbuf, smb_mid);
6697 state->vuid = SVAL(inbuf, smb_uid);
6698 state->setup_count = SVAL(inbuf, smb_suwcnt);
6699 state->setup = NULL;
6700 state->total_param = SVAL(inbuf, smb_tpscnt);
6701 state->param = NULL;
6702 state->total_data = SVAL(inbuf, smb_tdscnt);
6703 state->data = NULL;
6704 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6705 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6706 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6707 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6708 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6710 state->call = tran_call;
6712 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6713 is so as a sanity check */
6714 if (state->setup_count != 1) {
6716 * Need to have rc=0 for ioctl to get job id for OS/2.
6717 * Network printing will fail if function is not successful.
6718 * Similar function in reply.c will be used if protocol
6719 * is LANMAN1.0 instead of LM1.2X002.
6720 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6721 * outbuf doesn't have to be set(only job id is used).
6723 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6724 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6725 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6726 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6727 } else {
6728 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6729 DEBUG(2,("Transaction is %d\n",tran_call));
6730 TALLOC_FREE(state);
6731 END_PROFILE(SMBtrans2);
6732 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6736 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6737 goto bad_param;
6739 if (state->total_data) {
6740 /* Can't use talloc here, the core routines do realloc on the
6741 * params and data. */
6742 state->data = (char *)SMB_MALLOC(state->total_data);
6743 if (state->data == NULL) {
6744 DEBUG(0,("reply_trans2: data malloc fail for %u "
6745 "bytes !\n", (unsigned int)state->total_data));
6746 TALLOC_FREE(state);
6747 END_PROFILE(SMBtrans2);
6748 return(ERROR_DOS(ERRDOS,ERRnomem));
6750 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6751 goto bad_param;
6752 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6753 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6754 goto bad_param;
6756 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6759 if (state->total_param) {
6760 /* Can't use talloc here, the core routines do realloc on the
6761 * params and data. */
6762 state->param = (char *)SMB_MALLOC(state->total_param);
6763 if (state->param == NULL) {
6764 DEBUG(0,("reply_trans: param malloc fail for %u "
6765 "bytes !\n", (unsigned int)state->total_param));
6766 SAFE_FREE(state->data);
6767 TALLOC_FREE(state);
6768 END_PROFILE(SMBtrans2);
6769 return(ERROR_DOS(ERRDOS,ERRnomem));
6771 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6772 goto bad_param;
6773 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6774 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6775 goto bad_param;
6777 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6780 state->received_data = dscnt;
6781 state->received_param = pscnt;
6783 if ((state->received_param == state->total_param) &&
6784 (state->received_data == state->total_data)) {
6786 struct smb_request req;
6787 init_smb_request(&req, (uint8 *)inbuf);
6789 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6790 size, bufsize);
6791 SAFE_FREE(state->data);
6792 SAFE_FREE(state->param);
6793 TALLOC_FREE(state);
6794 END_PROFILE(SMBtrans2);
6795 return outsize;
6798 DLIST_ADD(conn->pending_trans, state);
6800 /* We need to send an interim response then receive the rest
6801 of the parameter/data bytes */
6802 outsize = set_message(inbuf, outbuf,0,0,False);
6803 show_msg(outbuf);
6804 END_PROFILE(SMBtrans2);
6805 return outsize;
6807 bad_param:
6809 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6810 SAFE_FREE(state->data);
6811 SAFE_FREE(state->param);
6812 TALLOC_FREE(state);
6813 END_PROFILE(SMBtrans2);
6814 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6818 /****************************************************************************
6819 Reply to a SMBtranss2
6820 ****************************************************************************/
6822 int reply_transs2(connection_struct *conn,
6823 char *inbuf,char *outbuf,int size,int bufsize)
6825 int outsize = 0;
6826 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6827 struct trans_state *state;
6828 struct smb_request req;
6830 START_PROFILE(SMBtranss2);
6832 show_msg(inbuf);
6834 for (state = conn->pending_trans; state != NULL;
6835 state = state->next) {
6836 if (state->mid == SVAL(inbuf,smb_mid)) {
6837 break;
6841 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6842 END_PROFILE(SMBtranss2);
6843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6846 /* Revise state->total_param and state->total_data in case they have
6847 changed downwards */
6849 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6850 state->total_param = SVAL(inbuf, smb_tpscnt);
6851 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6852 state->total_data = SVAL(inbuf, smb_tdscnt);
6854 pcnt = SVAL(inbuf, smb_spscnt);
6855 poff = SVAL(inbuf, smb_spsoff);
6856 pdisp = SVAL(inbuf, smb_spsdisp);
6858 dcnt = SVAL(inbuf, smb_sdscnt);
6859 doff = SVAL(inbuf, smb_sdsoff);
6860 ddisp = SVAL(inbuf, smb_sdsdisp);
6862 state->received_param += pcnt;
6863 state->received_data += dcnt;
6865 if ((state->received_data > state->total_data) ||
6866 (state->received_param > state->total_param))
6867 goto bad_param;
6869 if (pcnt) {
6870 if (pdisp+pcnt > state->total_param)
6871 goto bad_param;
6872 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6873 goto bad_param;
6874 if (pdisp > state->total_param)
6875 goto bad_param;
6876 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6877 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6878 goto bad_param;
6879 if (state->param + pdisp < state->param)
6880 goto bad_param;
6882 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6883 pcnt);
6886 if (dcnt) {
6887 if (ddisp+dcnt > state->total_data)
6888 goto bad_param;
6889 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6890 goto bad_param;
6891 if (ddisp > state->total_data)
6892 goto bad_param;
6893 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6894 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6895 goto bad_param;
6896 if (state->data + ddisp < state->data)
6897 goto bad_param;
6899 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6900 dcnt);
6903 if ((state->received_param < state->total_param) ||
6904 (state->received_data < state->total_data)) {
6905 END_PROFILE(SMBtranss2);
6906 return -1;
6909 /* construct_reply_common has done us the favor to pre-fill the
6910 * command field with SMBtranss2 which is wrong :-)
6912 SCVAL(outbuf,smb_com,SMBtrans2);
6914 init_smb_request(&req, (uint8 *)inbuf);
6916 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6917 bufsize);
6919 DLIST_REMOVE(conn->pending_trans, state);
6920 SAFE_FREE(state->data);
6921 SAFE_FREE(state->param);
6922 TALLOC_FREE(state);
6924 if (outsize == 0) {
6925 END_PROFILE(SMBtranss2);
6926 return(ERROR_DOS(ERRSRV,ERRnosupport));
6929 END_PROFILE(SMBtranss2);
6930 return(outsize);
6932 bad_param:
6934 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6935 DLIST_REMOVE(conn->pending_trans, state);
6936 SAFE_FREE(state->data);
6937 SAFE_FREE(state->param);
6938 TALLOC_FREE(state);
6939 END_PROFILE(SMBtranss2);
6940 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);