r23106: Use lchown for symlinks.
[Samba.git] / source / smbd / trans2.c
blob835fd0cedba87821b765f9f234b86b3230a87e93
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, char *inbuf, char *outbuf, int bufsize,
744 char **pparams, int total_params, char **ppdata, int total_data,
745 unsigned int max_data_bytes)
747 char *params = *pparams;
748 char *pdata = *ppdata;
749 int deny_mode;
750 int32 open_attr;
751 BOOL oplock_request;
752 #if 0
753 BOOL return_additional_info;
754 int16 open_sattr;
755 time_t open_time;
756 #endif
757 int open_ofun;
758 uint32 open_size;
759 char *pname;
760 pstring fname;
761 SMB_OFF_T size=0;
762 int fattr=0,mtime=0;
763 SMB_INO_T inode = 0;
764 SMB_STRUCT_STAT sbuf;
765 int smb_action = 0;
766 files_struct *fsp;
767 struct ea_list *ea_list = NULL;
768 uint16 flags = 0;
769 NTSTATUS status;
770 uint32 access_mask;
771 uint32 share_mode;
772 uint32 create_disposition;
773 uint32 create_options = 0;
776 * Ensure we have enough parameters to perform the operation.
779 if (total_params < 29) {
780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
783 flags = SVAL(params, 0);
784 deny_mode = SVAL(params, 2);
785 open_attr = SVAL(params,6);
786 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
787 if (oplock_request) {
788 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
791 #if 0
792 return_additional_info = BITSETW(params,0);
793 open_sattr = SVAL(params, 4);
794 open_time = make_unix_date3(params+8);
795 #endif
796 open_ofun = SVAL(params,12);
797 open_size = IVAL(params,14);
798 pname = &params[28];
800 if (IS_IPC(conn)) {
801 return(ERROR_DOS(ERRSRV,ERRaccess));
804 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
805 if (!NT_STATUS_IS_OK(status)) {
806 return ERROR_NT(status);
809 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
810 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
811 (unsigned int)open_ofun, open_size));
813 /* XXXX we need to handle passed times, sattr and flags */
815 status = unix_convert(conn, fname, False, NULL, &sbuf);
816 if (!NT_STATUS_IS_OK(status)) {
817 return ERROR_NT(status);
820 status = check_name(conn, fname);
821 if (!NT_STATUS_IS_OK(status)) {
822 return ERROR_NT(status);
825 if (open_ofun == 0) {
826 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
829 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
830 &access_mask,
831 &share_mode,
832 &create_disposition,
833 &create_options)) {
834 return ERROR_DOS(ERRDOS, ERRbadaccess);
837 /* Any data in this call is an EA list. */
838 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
839 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
842 if (total_data != 4) {
843 if (total_data < 10) {
844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
847 if (IVAL(pdata,0) > total_data) {
848 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
849 IVAL(pdata,0), (unsigned int)total_data));
850 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
853 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
854 total_data - 4);
855 if (!ea_list) {
856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
858 } else if (IVAL(pdata,0) != 4) {
859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
862 status = open_file_ntcreate(conn,fname,&sbuf,
863 access_mask,
864 share_mode,
865 create_disposition,
866 create_options,
867 open_attr,
868 oplock_request,
869 &smb_action, &fsp);
871 if (!NT_STATUS_IS_OK(status)) {
872 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
873 /* We have re-scheduled this call. */
874 return -1;
876 return ERROR_NT(status);
879 size = get_file_size(sbuf);
880 fattr = dos_mode(conn,fname,&sbuf);
881 mtime = sbuf.st_mtime;
882 inode = sbuf.st_ino;
883 if (fattr & aDIR) {
884 close_file(fsp,ERROR_CLOSE);
885 return(ERROR_DOS(ERRDOS,ERRnoaccess));
888 /* Save the requested allocation size. */
889 /* Allocate space for the file if a size hint is supplied */
890 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
891 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
892 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
893 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
894 if (fsp->is_directory) {
895 close_file(fsp,ERROR_CLOSE);
896 /* Can't set allocation size on a directory. */
897 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
899 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
900 close_file(fsp,ERROR_CLOSE);
901 return ERROR_NT(NT_STATUS_DISK_FULL);
904 /* Adjust size here to return the right size in the reply.
905 Windows does it this way. */
906 size = fsp->initial_allocation_size;
907 } else {
908 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
912 if (ea_list && smb_action == FILE_WAS_CREATED) {
913 status = set_ea(conn, fsp, fname, ea_list);
914 if (!NT_STATUS_IS_OK(status)) {
915 close_file(fsp,ERROR_CLOSE);
916 return ERROR_NT(status);
920 /* Realloc the size of parameters and data we will return */
921 *pparams = (char *)SMB_REALLOC(*pparams, 30);
922 if(*pparams == NULL ) {
923 return ERROR_NT(NT_STATUS_NO_MEMORY);
925 params = *pparams;
927 SSVAL(params,0,fsp->fnum);
928 SSVAL(params,2,fattr);
929 srv_put_dos_date2(params,4, mtime);
930 SIVAL(params,8, (uint32)size);
931 SSVAL(params,12,deny_mode);
932 SSVAL(params,14,0); /* open_type - file or directory. */
933 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
935 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
936 smb_action |= EXTENDED_OPLOCK_GRANTED;
939 SSVAL(params,18,smb_action);
942 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
944 SIVAL(params,20,inode);
945 SSVAL(params,24,0); /* Padding. */
946 if (flags & 8) {
947 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
948 SIVAL(params, 26, ea_size);
949 } else {
950 SIVAL(params, 26, 0);
953 /* Send the required number of replies */
954 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
956 return -1;
959 /*********************************************************
960 Routine to check if a given string matches exactly.
961 as a special case a mask of "." does NOT match. That
962 is required for correct wildcard semantics
963 Case can be significant or not.
964 **********************************************************/
966 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
968 if (mask[0] == '.' && mask[1] == 0)
969 return False;
970 if (conn->case_sensitive)
971 return strcmp(str,mask)==0;
972 if (StrCaseCmp(str,mask) != 0) {
973 return False;
975 if (dptr_has_wild(conn->dirptr)) {
976 return False;
978 return True;
981 /****************************************************************************
982 Return the filetype for UNIX extensions.
983 ****************************************************************************/
985 static uint32 unix_filetype(mode_t mode)
987 if(S_ISREG(mode))
988 return UNIX_TYPE_FILE;
989 else if(S_ISDIR(mode))
990 return UNIX_TYPE_DIR;
991 #ifdef S_ISLNK
992 else if(S_ISLNK(mode))
993 return UNIX_TYPE_SYMLINK;
994 #endif
995 #ifdef S_ISCHR
996 else if(S_ISCHR(mode))
997 return UNIX_TYPE_CHARDEV;
998 #endif
999 #ifdef S_ISBLK
1000 else if(S_ISBLK(mode))
1001 return UNIX_TYPE_BLKDEV;
1002 #endif
1003 #ifdef S_ISFIFO
1004 else if(S_ISFIFO(mode))
1005 return UNIX_TYPE_FIFO;
1006 #endif
1007 #ifdef S_ISSOCK
1008 else if(S_ISSOCK(mode))
1009 return UNIX_TYPE_SOCKET;
1010 #endif
1012 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1013 return UNIX_TYPE_UNKNOWN;
1016 /****************************************************************************
1017 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1018 ****************************************************************************/
1020 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1022 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1023 SMB_STRUCT_STAT *psbuf,
1024 uint32 perms,
1025 enum perm_type ptype,
1026 mode_t *ret_perms)
1028 mode_t ret = 0;
1030 if (perms == SMB_MODE_NO_CHANGE) {
1031 if (!VALID_STAT(*psbuf)) {
1032 return NT_STATUS_INVALID_PARAMETER;
1033 } else {
1034 *ret_perms = psbuf->st_mode;
1035 return NT_STATUS_OK;
1039 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1040 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1041 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1042 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1043 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1044 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1045 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1046 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1047 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1048 #ifdef S_ISVTX
1049 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1050 #endif
1051 #ifdef S_ISGID
1052 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1053 #endif
1054 #ifdef S_ISUID
1055 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1056 #endif
1058 switch (ptype) {
1059 case PERM_NEW_FILE:
1060 /* Apply mode mask */
1061 ret &= lp_create_mask(SNUM(conn));
1062 /* Add in force bits */
1063 ret |= lp_force_create_mode(SNUM(conn));
1064 break;
1065 case PERM_NEW_DIR:
1066 ret &= lp_dir_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_dir_mode(SNUM(conn));
1069 break;
1070 case PERM_EXISTING_FILE:
1071 /* Apply mode mask */
1072 ret &= lp_security_mask(SNUM(conn));
1073 /* Add in force bits */
1074 ret |= lp_force_security_mode(SNUM(conn));
1075 break;
1076 case PERM_EXISTING_DIR:
1077 /* Apply mode mask */
1078 ret &= lp_dir_security_mask(SNUM(conn));
1079 /* Add in force bits */
1080 ret |= lp_force_dir_security_mode(SNUM(conn));
1081 break;
1084 *ret_perms = ret;
1085 return NT_STATUS_OK;
1088 /****************************************************************************
1089 Get a level dependent lanman2 dir entry.
1090 ****************************************************************************/
1092 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1093 void *inbuf, char *outbuf,
1094 char *path_mask,uint32 dirtype,int info_level,
1095 int requires_resume_key,
1096 BOOL dont_descend,char **ppdata,
1097 char *base_data, int space_remaining,
1098 BOOL *out_of_space, BOOL *got_exact_match,
1099 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1101 const char *dname;
1102 BOOL found = False;
1103 SMB_STRUCT_STAT sbuf;
1104 pstring mask;
1105 pstring pathreal;
1106 pstring fname;
1107 char *p, *q, *pdata = *ppdata;
1108 uint32 reskey=0;
1109 long prev_dirpos=0;
1110 uint32 mode=0;
1111 SMB_OFF_T file_size = 0;
1112 SMB_BIG_UINT allocation_size = 0;
1113 uint32 len;
1114 struct timespec mdate_ts, adate_ts, create_date_ts;
1115 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1116 char *nameptr;
1117 char *last_entry_ptr;
1118 BOOL was_8_3;
1119 uint32 nt_extmode; /* Used for NT connections instead of mode */
1120 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1121 BOOL check_mangled_names = lp_manglednames(conn->params);
1123 *fname = 0;
1124 *out_of_space = False;
1125 *got_exact_match = False;
1127 ZERO_STRUCT(mdate_ts);
1128 ZERO_STRUCT(adate_ts);
1129 ZERO_STRUCT(create_date_ts);
1131 if (!conn->dirptr)
1132 return(False);
1134 p = strrchr_m(path_mask,'/');
1135 if(p != NULL) {
1136 if(p[1] == '\0')
1137 pstrcpy(mask,"*.*");
1138 else
1139 pstrcpy(mask, p+1);
1140 } else
1141 pstrcpy(mask, path_mask);
1144 while (!found) {
1145 BOOL got_match;
1146 BOOL ms_dfs_link = False;
1148 /* Needed if we run out of space */
1149 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1150 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1153 * Due to bugs in NT client redirectors we are not using
1154 * resume keys any more - set them to zero.
1155 * Check out the related comments in findfirst/findnext.
1156 * JRA.
1159 reskey = 0;
1161 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1162 (long)conn->dirptr,curr_dirpos));
1164 if (!dname) {
1165 return(False);
1169 * fname may get mangled, dname is never mangled.
1170 * Whenever we're accessing the filesystem we use
1171 * pathreal which is composed from dname.
1174 pstrcpy(fname,dname);
1176 /* This will mangle fname if it's an illegal name. */
1177 mangle_map(fname,False,True,conn->params);
1179 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1180 got_match = mask_match(fname, mask, conn->case_sensitive);
1183 if(!got_match && check_mangled_names &&
1184 !mangle_is_8_3(fname, False, conn->params)) {
1185 pstring mangled_name;
1188 * It turns out that NT matches wildcards against
1189 * both long *and* short names. This may explain some
1190 * of the wildcard wierdness from old DOS clients
1191 * that some people have been seeing.... JRA.
1194 pstrcpy(mangled_name, fname);
1196 /* Force the mangling into 8.3. */
1197 mangle_map( mangled_name, True, False, conn->params);
1198 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1199 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1203 if (got_match) {
1204 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1205 if (dont_descend && !isdots) {
1206 continue;
1209 pstrcpy(pathreal,conn->dirpath);
1210 if(needslash) {
1211 pstrcat(pathreal,"/");
1213 pstrcat(pathreal,dname);
1215 if (INFO_LEVEL_IS_UNIX(info_level)) {
1216 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1217 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1218 pathreal,strerror(errno)));
1219 continue;
1221 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1222 pstring link_target;
1224 /* Needed to show the msdfs symlinks as
1225 * directories */
1227 if(lp_host_msdfs() &&
1228 lp_msdfs_root(SNUM(conn)) &&
1229 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1230 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1231 "as a directory\n",
1232 pathreal));
1233 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1235 } else {
1237 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1238 pathreal,strerror(errno)));
1239 continue;
1243 if (ms_dfs_link) {
1244 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1245 } else {
1246 mode = dos_mode(conn,pathreal,&sbuf);
1249 if (!dir_check_ftype(conn,mode,dirtype)) {
1250 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1251 continue;
1254 if (!(mode & aDIR)) {
1255 file_size = get_file_size(sbuf);
1257 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1259 mdate_ts = get_mtimespec(&sbuf);
1260 adate_ts = get_atimespec(&sbuf);
1261 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1263 if (lp_dos_filetime_resolution(SNUM(conn))) {
1264 dos_filetime_timespec(&create_date_ts);
1265 dos_filetime_timespec(&mdate_ts);
1266 dos_filetime_timespec(&adate_ts);
1269 create_date = convert_timespec_to_time_t(create_date_ts);
1270 mdate = convert_timespec_to_time_t(mdate_ts);
1271 adate = convert_timespec_to_time_t(adate_ts);
1273 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1275 found = True;
1277 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1281 p = pdata;
1282 last_entry_ptr = p;
1284 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1286 switch (info_level) {
1287 case SMB_FIND_INFO_STANDARD:
1288 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1289 if(requires_resume_key) {
1290 SIVAL(p,0,reskey);
1291 p += 4;
1293 srv_put_dos_date2(p,0,create_date);
1294 srv_put_dos_date2(p,4,adate);
1295 srv_put_dos_date2(p,8,mdate);
1296 SIVAL(p,12,(uint32)file_size);
1297 SIVAL(p,16,(uint32)allocation_size);
1298 SSVAL(p,20,mode);
1299 p += 23;
1300 nameptr = p;
1301 p += align_string(outbuf, p, 0);
1302 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1303 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1304 if (len > 2) {
1305 SCVAL(nameptr, -1, len - 2);
1306 } else {
1307 SCVAL(nameptr, -1, 0);
1309 } else {
1310 if (len > 1) {
1311 SCVAL(nameptr, -1, len - 1);
1312 } else {
1313 SCVAL(nameptr, -1, 0);
1316 p += len;
1317 break;
1319 case SMB_FIND_EA_SIZE:
1320 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1321 if(requires_resume_key) {
1322 SIVAL(p,0,reskey);
1323 p += 4;
1325 srv_put_dos_date2(p,0,create_date);
1326 srv_put_dos_date2(p,4,adate);
1327 srv_put_dos_date2(p,8,mdate);
1328 SIVAL(p,12,(uint32)file_size);
1329 SIVAL(p,16,(uint32)allocation_size);
1330 SSVAL(p,20,mode);
1332 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1333 SIVAL(p,22,ea_size); /* Extended attributes */
1335 p += 27;
1336 nameptr = p - 1;
1337 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1338 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1339 if (len > 2) {
1340 len -= 2;
1341 } else {
1342 len = 0;
1344 } else {
1345 if (len > 1) {
1346 len -= 1;
1347 } else {
1348 len = 0;
1351 SCVAL(nameptr,0,len);
1352 p += len;
1353 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1354 break;
1356 case SMB_FIND_EA_LIST:
1358 struct ea_list *file_list = NULL;
1359 size_t ea_len = 0;
1361 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1362 if (!name_list) {
1363 return False;
1365 if(requires_resume_key) {
1366 SIVAL(p,0,reskey);
1367 p += 4;
1369 srv_put_dos_date2(p,0,create_date);
1370 srv_put_dos_date2(p,4,adate);
1371 srv_put_dos_date2(p,8,mdate);
1372 SIVAL(p,12,(uint32)file_size);
1373 SIVAL(p,16,(uint32)allocation_size);
1374 SSVAL(p,20,mode);
1375 p += 22; /* p now points to the EA area. */
1377 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1378 name_list = ea_list_union(name_list, file_list, &ea_len);
1380 /* We need to determine if this entry will fit in the space available. */
1381 /* Max string size is 255 bytes. */
1382 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1383 /* Move the dirptr back to prev_dirpos */
1384 dptr_SeekDir(conn->dirptr, prev_dirpos);
1385 *out_of_space = True;
1386 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1387 return False; /* Not finished - just out of space */
1390 /* Push the ea_data followed by the name. */
1391 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1392 nameptr = p;
1393 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1394 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1395 if (len > 2) {
1396 len -= 2;
1397 } else {
1398 len = 0;
1400 } else {
1401 if (len > 1) {
1402 len -= 1;
1403 } else {
1404 len = 0;
1407 SCVAL(nameptr,0,len);
1408 p += len + 1;
1409 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1410 break;
1413 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1414 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1415 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1416 p += 4;
1417 SIVAL(p,0,reskey); p += 4;
1418 put_long_date_timespec(p,create_date_ts); p += 8;
1419 put_long_date_timespec(p,adate_ts); p += 8;
1420 put_long_date_timespec(p,mdate_ts); p += 8;
1421 put_long_date_timespec(p,mdate_ts); p += 8;
1422 SOFF_T(p,0,file_size); p += 8;
1423 SOFF_T(p,0,allocation_size); p += 8;
1424 SIVAL(p,0,nt_extmode); p += 4;
1425 q = p; p += 4; /* q is placeholder for name length. */
1427 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1428 SIVAL(p,0,ea_size); /* Extended attributes */
1429 p += 4;
1431 /* Clear the short name buffer. This is
1432 * IMPORTANT as not doing so will trigger
1433 * a Win2k client bug. JRA.
1435 if (!was_8_3 && check_mangled_names) {
1436 pstring mangled_name;
1437 pstrcpy(mangled_name, fname);
1438 mangle_map(mangled_name,True,True,
1439 conn->params);
1440 mangled_name[12] = 0;
1441 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1442 if (len < 24) {
1443 memset(p + 2 + len,'\0',24 - len);
1445 SSVAL(p, 0, len);
1446 } else {
1447 memset(p,'\0',26);
1449 p += 2 + 24;
1450 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1451 SIVAL(q,0,len);
1452 p += len;
1453 SIVAL(p,0,0); /* Ensure any padding is null. */
1454 len = PTR_DIFF(p, pdata);
1455 len = (len + 3) & ~3;
1456 SIVAL(pdata,0,len);
1457 p = pdata + len;
1458 break;
1460 case SMB_FIND_FILE_DIRECTORY_INFO:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1462 p += 4;
1463 SIVAL(p,0,reskey); p += 4;
1464 put_long_date_timespec(p,create_date_ts); p += 8;
1465 put_long_date_timespec(p,adate_ts); p += 8;
1466 put_long_date_timespec(p,mdate_ts); p += 8;
1467 put_long_date_timespec(p,mdate_ts); p += 8;
1468 SOFF_T(p,0,file_size); p += 8;
1469 SOFF_T(p,0,allocation_size); p += 8;
1470 SIVAL(p,0,nt_extmode); p += 4;
1471 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1472 SIVAL(p,0,len);
1473 p += 4 + len;
1474 SIVAL(p,0,0); /* Ensure any padding is null. */
1475 len = PTR_DIFF(p, pdata);
1476 len = (len + 3) & ~3;
1477 SIVAL(pdata,0,len);
1478 p = pdata + len;
1479 break;
1481 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1482 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1483 p += 4;
1484 SIVAL(p,0,reskey); p += 4;
1485 put_long_date_timespec(p,create_date_ts); p += 8;
1486 put_long_date_timespec(p,adate_ts); p += 8;
1487 put_long_date_timespec(p,mdate_ts); p += 8;
1488 put_long_date_timespec(p,mdate_ts); p += 8;
1489 SOFF_T(p,0,file_size); p += 8;
1490 SOFF_T(p,0,allocation_size); p += 8;
1491 SIVAL(p,0,nt_extmode); p += 4;
1492 q = p; p += 4; /* q is placeholder for name length. */
1494 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1495 SIVAL(p,0,ea_size); /* Extended attributes */
1496 p +=4;
1498 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1499 SIVAL(q, 0, len);
1500 p += len;
1502 SIVAL(p,0,0); /* Ensure any padding is null. */
1503 len = PTR_DIFF(p, pdata);
1504 len = (len + 3) & ~3;
1505 SIVAL(pdata,0,len);
1506 p = pdata + len;
1507 break;
1509 case SMB_FIND_FILE_NAMES_INFO:
1510 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1511 p += 4;
1512 SIVAL(p,0,reskey); p += 4;
1513 p += 4;
1514 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1515 acl on a dir (tridge) */
1516 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1517 SIVAL(p, -4, len);
1518 p += len;
1519 SIVAL(p,0,0); /* Ensure any padding is null. */
1520 len = PTR_DIFF(p, pdata);
1521 len = (len + 3) & ~3;
1522 SIVAL(pdata,0,len);
1523 p = pdata + len;
1524 break;
1526 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1527 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1528 p += 4;
1529 SIVAL(p,0,reskey); p += 4;
1530 put_long_date_timespec(p,create_date_ts); p += 8;
1531 put_long_date_timespec(p,adate_ts); p += 8;
1532 put_long_date_timespec(p,mdate_ts); p += 8;
1533 put_long_date_timespec(p,mdate_ts); p += 8;
1534 SOFF_T(p,0,file_size); p += 8;
1535 SOFF_T(p,0,allocation_size); p += 8;
1536 SIVAL(p,0,nt_extmode); p += 4;
1537 q = p; p += 4; /* q is placeholder for name length. */
1539 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1540 SIVAL(p,0,ea_size); /* Extended attributes */
1541 p +=4;
1543 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1544 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1545 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1546 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1547 SIVAL(q, 0, len);
1548 p += len;
1549 SIVAL(p,0,0); /* Ensure any padding is null. */
1550 len = PTR_DIFF(p, pdata);
1551 len = (len + 3) & ~3;
1552 SIVAL(pdata,0,len);
1553 p = pdata + len;
1554 break;
1556 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1557 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1558 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1559 p += 4;
1560 SIVAL(p,0,reskey); p += 4;
1561 put_long_date_timespec(p,create_date_ts); p += 8;
1562 put_long_date_timespec(p,adate_ts); p += 8;
1563 put_long_date_timespec(p,mdate_ts); p += 8;
1564 put_long_date_timespec(p,mdate_ts); p += 8;
1565 SOFF_T(p,0,file_size); p += 8;
1566 SOFF_T(p,0,allocation_size); p += 8;
1567 SIVAL(p,0,nt_extmode); p += 4;
1568 q = p; p += 4; /* q is placeholder for name length */
1570 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1571 SIVAL(p,0,ea_size); /* Extended attributes */
1572 p +=4;
1574 /* Clear the short name buffer. This is
1575 * IMPORTANT as not doing so will trigger
1576 * a Win2k client bug. JRA.
1578 if (!was_8_3 && check_mangled_names) {
1579 pstring mangled_name;
1580 pstrcpy(mangled_name, fname);
1581 mangle_map(mangled_name,True,True,
1582 conn->params);
1583 mangled_name[12] = 0;
1584 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1585 SSVAL(p, 0, len);
1586 if (len < 24) {
1587 memset(p + 2 + len,'\0',24 - len);
1589 SSVAL(p, 0, len);
1590 } else {
1591 memset(p,'\0',26);
1593 p += 26;
1594 SSVAL(p,0,0); p += 2; /* Reserved ? */
1595 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1596 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1597 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1598 SIVAL(q,0,len);
1599 p += len;
1600 SIVAL(p,0,0); /* Ensure any padding is null. */
1601 len = PTR_DIFF(p, pdata);
1602 len = (len + 3) & ~3;
1603 SIVAL(pdata,0,len);
1604 p = pdata + len;
1605 break;
1607 /* CIFS UNIX Extension. */
1609 case SMB_FIND_FILE_UNIX:
1610 case SMB_FIND_FILE_UNIX_INFO2:
1611 p+= 4;
1612 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1614 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1616 if (info_level == SMB_FIND_FILE_UNIX) {
1617 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1618 p = store_file_unix_basic(conn, p,
1619 NULL, &sbuf);
1620 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1621 } else {
1622 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1623 p = store_file_unix_basic_info2(conn, p,
1624 NULL, &sbuf);
1625 nameptr = p;
1626 p += 4;
1627 len = srvstr_push(outbuf, p, fname, -1, 0);
1628 SIVAL(nameptr, 0, len);
1631 p += len;
1632 SIVAL(p,0,0); /* Ensure any padding is null. */
1634 len = PTR_DIFF(p, pdata);
1635 len = (len + 3) & ~3;
1636 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1637 p = pdata + len;
1638 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1640 break;
1642 default:
1643 return(False);
1647 if (PTR_DIFF(p,pdata) > space_remaining) {
1648 /* Move the dirptr back to prev_dirpos */
1649 dptr_SeekDir(conn->dirptr, prev_dirpos);
1650 *out_of_space = True;
1651 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1652 return False; /* Not finished - just out of space */
1655 /* Setup the last entry pointer, as an offset from base_data */
1656 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1657 /* Advance the data pointer to the next slot */
1658 *ppdata = p;
1660 return(found);
1663 /****************************************************************************
1664 Reply to a TRANS2_FINDFIRST.
1665 ****************************************************************************/
1667 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1668 char **pparams, int total_params, char **ppdata, int total_data,
1669 unsigned int max_data_bytes)
1671 /* We must be careful here that we don't return more than the
1672 allowed number of data bytes. If this means returning fewer than
1673 maxentries then so be it. We assume that the redirector has
1674 enough room for the fixed number of parameter bytes it has
1675 requested. */
1676 char *params = *pparams;
1677 char *pdata = *ppdata;
1678 uint32 dirtype;
1679 int maxentries;
1680 uint16 findfirst_flags;
1681 BOOL close_after_first;
1682 BOOL close_if_end;
1683 BOOL requires_resume_key;
1684 int info_level;
1685 pstring directory;
1686 pstring mask;
1687 char *p;
1688 int last_entry_off=0;
1689 int dptr_num = -1;
1690 int numentries = 0;
1691 int i;
1692 BOOL finished = False;
1693 BOOL dont_descend = False;
1694 BOOL out_of_space = False;
1695 int space_remaining;
1696 BOOL mask_contains_wcard = False;
1697 SMB_STRUCT_STAT sbuf;
1698 TALLOC_CTX *ea_ctx = NULL;
1699 struct ea_list *ea_list = NULL;
1700 NTSTATUS ntstatus = NT_STATUS_OK;
1702 if (total_params < 13) {
1703 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1706 dirtype = SVAL(params,0);
1707 maxentries = SVAL(params,2);
1708 findfirst_flags = SVAL(params,4);
1709 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1710 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1711 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1712 info_level = SVAL(params,6);
1714 *directory = *mask = 0;
1716 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1717 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1718 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1719 info_level, max_data_bytes));
1721 if (!maxentries) {
1722 /* W2K3 seems to treat zero as 1. */
1723 maxentries = 1;
1726 switch (info_level) {
1727 case SMB_FIND_INFO_STANDARD:
1728 case SMB_FIND_EA_SIZE:
1729 case SMB_FIND_EA_LIST:
1730 case SMB_FIND_FILE_DIRECTORY_INFO:
1731 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1732 case SMB_FIND_FILE_NAMES_INFO:
1733 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1734 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1735 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1736 break;
1737 case SMB_FIND_FILE_UNIX:
1738 case SMB_FIND_FILE_UNIX_INFO2:
1739 if (!lp_unix_extensions()) {
1740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1742 break;
1743 default:
1744 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1747 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1748 if (!NT_STATUS_IS_OK(ntstatus)) {
1749 return ERROR_NT(ntstatus);
1752 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1753 if (!NT_STATUS_IS_OK(ntstatus)) {
1754 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1755 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1757 return ERROR_NT(ntstatus);
1760 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1761 if (!NT_STATUS_IS_OK(ntstatus)) {
1762 return ERROR_NT(ntstatus);
1764 ntstatus = check_name(conn, directory);
1765 if (!NT_STATUS_IS_OK(ntstatus)) {
1766 return ERROR_NT(ntstatus);
1769 p = strrchr_m(directory,'/');
1770 if(p == NULL) {
1771 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1772 if((directory[0] == '.') && (directory[1] == '\0')) {
1773 pstrcpy(mask,"*");
1774 mask_contains_wcard = True;
1775 } else {
1776 pstrcpy(mask,directory);
1778 pstrcpy(directory,"./");
1779 } else {
1780 pstrcpy(mask,p+1);
1781 *p = 0;
1784 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1786 if (info_level == SMB_FIND_EA_LIST) {
1787 uint32 ea_size;
1789 if (total_data < 4) {
1790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1793 ea_size = IVAL(pdata,0);
1794 if (ea_size != total_data) {
1795 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1796 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 if (!lp_ea_support(SNUM(conn))) {
1801 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1804 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1805 return ERROR_NT(NT_STATUS_NO_MEMORY);
1808 /* Pull out the list of names. */
1809 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1810 if (!ea_list) {
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1816 *ppdata = (char *)SMB_REALLOC(
1817 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1818 if(*ppdata == NULL ) {
1819 talloc_destroy(ea_ctx);
1820 return ERROR_NT(NT_STATUS_NO_MEMORY);
1822 pdata = *ppdata;
1824 /* Realloc the params space */
1825 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1826 if (*pparams == NULL) {
1827 talloc_destroy(ea_ctx);
1828 return ERROR_NT(NT_STATUS_NO_MEMORY);
1830 params = *pparams;
1832 /* Save the wildcard match and attribs we are using on this directory -
1833 needed as lanman2 assumes these are being saved between calls */
1835 ntstatus = dptr_create(conn,
1836 directory,
1837 False,
1838 True,
1839 SVAL(inbuf,smb_pid),
1840 mask,
1841 mask_contains_wcard,
1842 dirtype,
1843 &conn->dirptr);
1845 if (!NT_STATUS_IS_OK(ntstatus)) {
1846 talloc_destroy(ea_ctx);
1847 return ERROR_NT(ntstatus);
1850 dptr_num = dptr_dnum(conn->dirptr);
1851 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1853 /* We don't need to check for VOL here as this is returned by
1854 a different TRANS2 call. */
1856 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1857 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1858 dont_descend = True;
1860 p = pdata;
1861 space_remaining = max_data_bytes;
1862 out_of_space = False;
1864 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1865 BOOL got_exact_match = False;
1867 /* this is a heuristic to avoid seeking the dirptr except when
1868 absolutely necessary. It allows for a filename of about 40 chars */
1869 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1870 out_of_space = True;
1871 finished = False;
1872 } else {
1873 finished = !get_lanman2_dir_entry(conn,
1874 inbuf, outbuf,
1875 mask,dirtype,info_level,
1876 requires_resume_key,dont_descend,
1877 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1878 &last_entry_off, ea_list, ea_ctx);
1881 if (finished && out_of_space)
1882 finished = False;
1884 if (!finished && !out_of_space)
1885 numentries++;
1888 * As an optimisation if we know we aren't looking
1889 * for a wildcard name (ie. the name matches the wildcard exactly)
1890 * then we can finish on any (first) match.
1891 * This speeds up large directory searches. JRA.
1894 if(got_exact_match)
1895 finished = True;
1897 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1900 talloc_destroy(ea_ctx);
1902 /* Check if we can close the dirptr */
1903 if(close_after_first || (finished && close_if_end)) {
1904 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1905 dptr_close(&dptr_num);
1909 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1910 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1911 * the protocol level is less than NT1. Tested with smbclient. JRA.
1912 * This should fix the OS/2 client bug #2335.
1915 if(numentries == 0) {
1916 dptr_close(&dptr_num);
1917 if (Protocol < PROTOCOL_NT1) {
1918 return ERROR_DOS(ERRDOS,ERRnofiles);
1919 } else {
1920 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1924 /* At this point pdata points to numentries directory entries. */
1926 /* Set up the return parameter block */
1927 SSVAL(params,0,dptr_num);
1928 SSVAL(params,2,numentries);
1929 SSVAL(params,4,finished);
1930 SSVAL(params,6,0); /* Never an EA error */
1931 SSVAL(params,8,last_entry_off);
1933 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1935 if ((! *directory) && dptr_path(dptr_num))
1936 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1938 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1939 smb_fn_name(CVAL(inbuf,smb_com)),
1940 mask, directory, dirtype, numentries ) );
1943 * Force a name mangle here to ensure that the
1944 * mask as an 8.3 name is top of the mangled cache.
1945 * The reasons for this are subtle. Don't remove
1946 * this code unless you know what you are doing
1947 * (see PR#13758). JRA.
1950 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1951 mangle_map(mask, True, True, conn->params);
1953 return(-1);
1956 /****************************************************************************
1957 Reply to a TRANS2_FINDNEXT.
1958 ****************************************************************************/
1960 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1961 char **pparams, int total_params, char **ppdata, int total_data,
1962 unsigned int max_data_bytes)
1964 /* We must be careful here that we don't return more than the
1965 allowed number of data bytes. If this means returning fewer than
1966 maxentries then so be it. We assume that the redirector has
1967 enough room for the fixed number of parameter bytes it has
1968 requested. */
1969 char *params = *pparams;
1970 char *pdata = *ppdata;
1971 int dptr_num;
1972 int maxentries;
1973 uint16 info_level;
1974 uint32 resume_key;
1975 uint16 findnext_flags;
1976 BOOL close_after_request;
1977 BOOL close_if_end;
1978 BOOL requires_resume_key;
1979 BOOL continue_bit;
1980 BOOL mask_contains_wcard = False;
1981 pstring resume_name;
1982 pstring mask;
1983 pstring directory;
1984 char *p;
1985 uint16 dirtype;
1986 int numentries = 0;
1987 int i, last_entry_off=0;
1988 BOOL finished = False;
1989 BOOL dont_descend = False;
1990 BOOL out_of_space = False;
1991 int space_remaining;
1992 TALLOC_CTX *ea_ctx = NULL;
1993 struct ea_list *ea_list = NULL;
1994 NTSTATUS ntstatus = NT_STATUS_OK;
1996 if (total_params < 13) {
1997 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2000 dptr_num = SVAL(params,0);
2001 maxentries = SVAL(params,2);
2002 info_level = SVAL(params,4);
2003 resume_key = IVAL(params,6);
2004 findnext_flags = SVAL(params,10);
2005 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2006 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2007 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2008 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2010 *mask = *directory = *resume_name = 0;
2012 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2013 if (!NT_STATUS_IS_OK(ntstatus)) {
2014 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2015 complain (it thinks we're asking for the directory above the shared
2016 path or an invalid name). Catch this as the resume name is only compared, never used in
2017 a file access. JRA. */
2018 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2019 pstrcpy(resume_name, "..");
2020 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2021 pstrcpy(resume_name, ".");
2022 } else {
2023 return ERROR_NT(ntstatus);
2027 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2028 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2029 resume_key = %d resume name = %s continue=%d level = %d\n",
2030 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2031 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2033 if (!maxentries) {
2034 /* W2K3 seems to treat zero as 1. */
2035 maxentries = 1;
2038 switch (info_level) {
2039 case SMB_FIND_INFO_STANDARD:
2040 case SMB_FIND_EA_SIZE:
2041 case SMB_FIND_EA_LIST:
2042 case SMB_FIND_FILE_DIRECTORY_INFO:
2043 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2044 case SMB_FIND_FILE_NAMES_INFO:
2045 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2046 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2047 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2048 break;
2049 case SMB_FIND_FILE_UNIX:
2050 case SMB_FIND_FILE_UNIX_INFO2:
2051 if (!lp_unix_extensions()) {
2052 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2054 break;
2055 default:
2056 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2059 if (info_level == SMB_FIND_EA_LIST) {
2060 uint32 ea_size;
2062 if (total_data < 4) {
2063 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2066 ea_size = IVAL(pdata,0);
2067 if (ea_size != total_data) {
2068 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2069 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2070 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 if (!lp_ea_support(SNUM(conn))) {
2074 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2077 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2078 return ERROR_NT(NT_STATUS_NO_MEMORY);
2081 /* Pull out the list of names. */
2082 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2083 if (!ea_list) {
2084 talloc_destroy(ea_ctx);
2085 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2089 *ppdata = (char *)SMB_REALLOC(
2090 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2091 if(*ppdata == NULL) {
2092 talloc_destroy(ea_ctx);
2093 return ERROR_NT(NT_STATUS_NO_MEMORY);
2096 pdata = *ppdata;
2098 /* Realloc the params space */
2099 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2100 if(*pparams == NULL ) {
2101 talloc_destroy(ea_ctx);
2102 return ERROR_NT(NT_STATUS_NO_MEMORY);
2105 params = *pparams;
2107 /* Check that the dptr is valid */
2108 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2109 talloc_destroy(ea_ctx);
2110 return ERROR_DOS(ERRDOS,ERRnofiles);
2113 string_set(&conn->dirpath,dptr_path(dptr_num));
2115 /* Get the wildcard mask from the dptr */
2116 if((p = dptr_wcard(dptr_num))== NULL) {
2117 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2118 talloc_destroy(ea_ctx);
2119 return ERROR_DOS(ERRDOS,ERRnofiles);
2122 pstrcpy(mask, p);
2123 pstrcpy(directory,conn->dirpath);
2125 /* Get the attr mask from the dptr */
2126 dirtype = dptr_attr(dptr_num);
2128 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2129 dptr_num, mask, dirtype,
2130 (long)conn->dirptr,
2131 dptr_TellDir(conn->dirptr)));
2133 /* We don't need to check for VOL here as this is returned by
2134 a different TRANS2 call. */
2136 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2137 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2138 dont_descend = True;
2140 p = pdata;
2141 space_remaining = max_data_bytes;
2142 out_of_space = False;
2145 * Seek to the correct position. We no longer use the resume key but
2146 * depend on the last file name instead.
2149 if(*resume_name && !continue_bit) {
2150 SMB_STRUCT_STAT st;
2152 long current_pos = 0;
2154 * Remember, mangle_map is called by
2155 * get_lanman2_dir_entry(), so the resume name
2156 * could be mangled. Ensure we check the unmangled name.
2159 if (mangle_is_mangled(resume_name, conn->params)) {
2160 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2161 conn->params);
2165 * Fix for NT redirector problem triggered by resume key indexes
2166 * changing between directory scans. We now return a resume key of 0
2167 * and instead look for the filename to continue from (also given
2168 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2169 * findfirst/findnext (as is usual) then the directory pointer
2170 * should already be at the correct place.
2173 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2174 } /* end if resume_name && !continue_bit */
2176 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2177 BOOL got_exact_match = False;
2179 /* this is a heuristic to avoid seeking the dirptr except when
2180 absolutely necessary. It allows for a filename of about 40 chars */
2181 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2182 out_of_space = True;
2183 finished = False;
2184 } else {
2185 finished = !get_lanman2_dir_entry(conn,
2186 inbuf, outbuf,
2187 mask,dirtype,info_level,
2188 requires_resume_key,dont_descend,
2189 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2190 &last_entry_off, ea_list, ea_ctx);
2193 if (finished && out_of_space)
2194 finished = False;
2196 if (!finished && !out_of_space)
2197 numentries++;
2200 * As an optimisation if we know we aren't looking
2201 * for a wildcard name (ie. the name matches the wildcard exactly)
2202 * then we can finish on any (first) match.
2203 * This speeds up large directory searches. JRA.
2206 if(got_exact_match)
2207 finished = True;
2209 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2212 talloc_destroy(ea_ctx);
2214 /* Check if we can close the dirptr */
2215 if(close_after_request || (finished && close_if_end)) {
2216 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2217 dptr_close(&dptr_num); /* This frees up the saved mask */
2220 /* Set up the return parameter block */
2221 SSVAL(params,0,numentries);
2222 SSVAL(params,2,finished);
2223 SSVAL(params,4,0); /* Never an EA error */
2224 SSVAL(params,6,last_entry_off);
2226 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2228 if ((! *directory) && dptr_path(dptr_num))
2229 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2231 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2232 smb_fn_name(CVAL(inbuf,smb_com)),
2233 mask, directory, dirtype, numentries ) );
2235 return(-1);
2238 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2240 E_md4hash(lp_servicename(SNUM(conn)),objid);
2241 return objid;
2244 /****************************************************************************
2245 Reply to a TRANS2_QFSINFO (query filesystem info).
2246 ****************************************************************************/
2248 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2249 char **pparams, int total_params, char **ppdata, int total_data,
2250 unsigned int max_data_bytes)
2252 char *pdata;
2253 char *params = *pparams;
2254 uint16 info_level;
2255 int data_len, len;
2256 SMB_STRUCT_STAT st;
2257 const char *vname = volume_label(SNUM(conn));
2258 int snum = SNUM(conn);
2259 char *fstype = lp_fstype(SNUM(conn));
2260 int quota_flag = 0;
2262 if (total_params < 2) {
2263 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2266 info_level = SVAL(params,0);
2268 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2270 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2271 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2272 return ERROR_DOS(ERRSRV,ERRinvdevice);
2275 *ppdata = (char *)SMB_REALLOC(
2276 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2277 if (*ppdata == NULL ) {
2278 return ERROR_NT(NT_STATUS_NO_MEMORY);
2281 pdata = *ppdata;
2282 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2284 switch (info_level) {
2285 case SMB_INFO_ALLOCATION:
2287 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2288 data_len = 18;
2289 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2290 return(UNIXERROR(ERRHRD,ERRgeneral));
2293 block_size = lp_block_size(snum);
2294 if (bsize < block_size) {
2295 SMB_BIG_UINT factor = block_size/bsize;
2296 bsize = block_size;
2297 dsize /= factor;
2298 dfree /= factor;
2300 if (bsize > block_size) {
2301 SMB_BIG_UINT factor = bsize/block_size;
2302 bsize = block_size;
2303 dsize *= factor;
2304 dfree *= factor;
2306 bytes_per_sector = 512;
2307 sectors_per_unit = bsize/bytes_per_sector;
2309 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2310 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2311 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2313 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2314 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2315 SIVAL(pdata,l1_cUnit,dsize);
2316 SIVAL(pdata,l1_cUnitAvail,dfree);
2317 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2318 break;
2321 case SMB_INFO_VOLUME:
2322 /* Return volume name */
2324 * Add volume serial number - hash of a combination of
2325 * the called hostname and the service name.
2327 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2329 * Win2k3 and previous mess this up by sending a name length
2330 * one byte short. I believe only older clients (OS/2 Win9x) use
2331 * this call so try fixing this by adding a terminating null to
2332 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2334 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2335 SCVAL(pdata,l2_vol_cch,len);
2336 data_len = l2_vol_szVolLabel + len;
2337 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2338 (unsigned)st.st_ctime, len, vname));
2339 break;
2341 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2342 case SMB_FS_ATTRIBUTE_INFORMATION:
2345 #if defined(HAVE_SYS_QUOTAS)
2346 quota_flag = FILE_VOLUME_QUOTAS;
2347 #endif
2349 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2350 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2351 FILE_SUPPORTS_OBJECT_IDS|
2352 FILE_UNICODE_ON_DISK|
2353 quota_flag); /* FS ATTRIBUTES */
2355 SIVAL(pdata,4,255); /* Max filename component length */
2356 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2357 and will think we can't do long filenames */
2358 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2359 SIVAL(pdata,8,len);
2360 data_len = 12 + len;
2361 break;
2363 case SMB_QUERY_FS_LABEL_INFO:
2364 case SMB_FS_LABEL_INFORMATION:
2365 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2366 data_len = 4 + len;
2367 SIVAL(pdata,0,len);
2368 break;
2370 case SMB_QUERY_FS_VOLUME_INFO:
2371 case SMB_FS_VOLUME_INFORMATION:
2374 * Add volume serial number - hash of a combination of
2375 * the called hostname and the service name.
2377 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2378 (str_checksum(get_local_machine_name())<<16));
2380 /* Max label len is 32 characters. */
2381 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2382 SIVAL(pdata,12,len);
2383 data_len = 18+len;
2385 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2386 (int)strlen(vname),vname, lp_servicename(snum)));
2387 break;
2389 case SMB_QUERY_FS_SIZE_INFO:
2390 case SMB_FS_SIZE_INFORMATION:
2392 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2393 data_len = 24;
2394 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2395 return(UNIXERROR(ERRHRD,ERRgeneral));
2397 block_size = lp_block_size(snum);
2398 if (bsize < block_size) {
2399 SMB_BIG_UINT factor = block_size/bsize;
2400 bsize = block_size;
2401 dsize /= factor;
2402 dfree /= factor;
2404 if (bsize > block_size) {
2405 SMB_BIG_UINT factor = bsize/block_size;
2406 bsize = block_size;
2407 dsize *= factor;
2408 dfree *= factor;
2410 bytes_per_sector = 512;
2411 sectors_per_unit = bsize/bytes_per_sector;
2412 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2413 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2414 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2415 SBIG_UINT(pdata,0,dsize);
2416 SBIG_UINT(pdata,8,dfree);
2417 SIVAL(pdata,16,sectors_per_unit);
2418 SIVAL(pdata,20,bytes_per_sector);
2419 break;
2422 case SMB_FS_FULL_SIZE_INFORMATION:
2424 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2425 data_len = 32;
2426 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2427 return(UNIXERROR(ERRHRD,ERRgeneral));
2429 block_size = lp_block_size(snum);
2430 if (bsize < block_size) {
2431 SMB_BIG_UINT factor = block_size/bsize;
2432 bsize = block_size;
2433 dsize /= factor;
2434 dfree /= factor;
2436 if (bsize > block_size) {
2437 SMB_BIG_UINT factor = bsize/block_size;
2438 bsize = block_size;
2439 dsize *= factor;
2440 dfree *= factor;
2442 bytes_per_sector = 512;
2443 sectors_per_unit = bsize/bytes_per_sector;
2444 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2445 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2446 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2447 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2448 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2449 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2450 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2451 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2452 break;
2455 case SMB_QUERY_FS_DEVICE_INFO:
2456 case SMB_FS_DEVICE_INFORMATION:
2457 data_len = 8;
2458 SIVAL(pdata,0,0); /* dev type */
2459 SIVAL(pdata,4,0); /* characteristics */
2460 break;
2462 #ifdef HAVE_SYS_QUOTAS
2463 case SMB_FS_QUOTA_INFORMATION:
2465 * what we have to send --metze:
2467 * Unknown1: 24 NULL bytes
2468 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2469 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2470 * Quota Flags: 2 byte :
2471 * Unknown3: 6 NULL bytes
2473 * 48 bytes total
2475 * details for Quota Flags:
2477 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2478 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2479 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2480 * 0x0001 Enable Quotas: enable quota for this fs
2484 /* we need to fake up a fsp here,
2485 * because its not send in this call
2487 files_struct fsp;
2488 SMB_NTQUOTA_STRUCT quotas;
2490 ZERO_STRUCT(fsp);
2491 ZERO_STRUCT(quotas);
2493 fsp.conn = conn;
2494 fsp.fnum = -1;
2496 /* access check */
2497 if (current_user.ut.uid != 0) {
2498 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2499 lp_servicename(SNUM(conn)),conn->user));
2500 return ERROR_DOS(ERRDOS,ERRnoaccess);
2503 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2504 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2505 return ERROR_DOS(ERRSRV,ERRerror);
2508 data_len = 48;
2510 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2512 /* Unknown1 24 NULL bytes*/
2513 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2514 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2515 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2517 /* Default Soft Quota 8 bytes */
2518 SBIG_UINT(pdata,24,quotas.softlim);
2520 /* Default Hard Quota 8 bytes */
2521 SBIG_UINT(pdata,32,quotas.hardlim);
2523 /* Quota flag 2 bytes */
2524 SSVAL(pdata,40,quotas.qflags);
2526 /* Unknown3 6 NULL bytes */
2527 SSVAL(pdata,42,0);
2528 SIVAL(pdata,44,0);
2530 break;
2532 #endif /* HAVE_SYS_QUOTAS */
2533 case SMB_FS_OBJECTID_INFORMATION:
2535 unsigned char objid[16];
2536 memcpy(pdata,create_volume_objectid(conn, objid),16);
2537 data_len = 64;
2538 break;
2542 * Query the version and capabilities of the CIFS UNIX extensions
2543 * in use.
2546 case SMB_QUERY_CIFS_UNIX_INFO:
2547 if (!lp_unix_extensions()) {
2548 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2550 data_len = 12;
2551 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2552 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2553 /* We have POSIX ACLs, pathname and locking capability. */
2554 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2555 CIFS_UNIX_POSIX_ACLS_CAP|
2556 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2557 CIFS_UNIX_FCNTL_LOCKS_CAP|
2558 CIFS_UNIX_EXTATTR_CAP|
2559 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2560 /* Ensure we don't do this on signed or sealed data. */
2561 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2562 )));
2563 break;
2565 case SMB_QUERY_POSIX_FS_INFO:
2567 int rc;
2568 vfs_statvfs_struct svfs;
2570 if (!lp_unix_extensions()) {
2571 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2574 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2576 if (!rc) {
2577 data_len = 56;
2578 SIVAL(pdata,0,svfs.OptimalTransferSize);
2579 SIVAL(pdata,4,svfs.BlockSize);
2580 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2581 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2582 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2583 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2584 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2585 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2586 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2587 #ifdef EOPNOTSUPP
2588 } else if (rc == EOPNOTSUPP) {
2589 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2590 #endif /* EOPNOTSUPP */
2591 } else {
2592 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2593 return ERROR_DOS(ERRSRV,ERRerror);
2595 break;
2598 case SMB_QUERY_POSIX_WHOAMI:
2600 uint32_t flags = 0;
2601 uint32_t sid_bytes;
2602 int i;
2604 if (!lp_unix_extensions()) {
2605 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2608 if (max_data_bytes < 40) {
2609 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2612 /* We ARE guest if global_sid_Builtin_Guests is
2613 * in our list of SIDs.
2615 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2616 current_user.nt_user_token)) {
2617 flags |= SMB_WHOAMI_GUEST;
2620 /* We are NOT guest if global_sid_Authenticated_Users
2621 * is in our list of SIDs.
2623 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2624 current_user.nt_user_token)) {
2625 flags &= ~SMB_WHOAMI_GUEST;
2628 /* NOTE: 8 bytes for UID/GID, irrespective of native
2629 * platform size. This matches
2630 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2632 data_len = 4 /* flags */
2633 + 4 /* flag mask */
2634 + 8 /* uid */
2635 + 8 /* gid */
2636 + 4 /* ngroups */
2637 + 4 /* num_sids */
2638 + 4 /* SID bytes */
2639 + 4 /* pad/reserved */
2640 + (current_user.ut.ngroups * 8)
2641 /* groups list */
2642 + (current_user.nt_user_token->num_sids *
2643 SID_MAX_SIZE)
2644 /* SID list */;
2646 SIVAL(pdata, 0, flags);
2647 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2648 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2649 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2652 if (data_len >= max_data_bytes) {
2653 /* Potential overflow, skip the GIDs and SIDs. */
2655 SIVAL(pdata, 24, 0); /* num_groups */
2656 SIVAL(pdata, 28, 0); /* num_sids */
2657 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2658 SIVAL(pdata, 36, 0); /* reserved */
2660 data_len = 40;
2661 break;
2664 SIVAL(pdata, 24, current_user.ut.ngroups);
2665 SIVAL(pdata, 28,
2666 current_user.nt_user_token->num_sids);
2668 /* We walk the SID list twice, but this call is fairly
2669 * infrequent, and I don't expect that it's performance
2670 * sensitive -- jpeach
2672 for (i = 0, sid_bytes = 0;
2673 i < current_user.nt_user_token->num_sids; ++i) {
2674 sid_bytes +=
2675 sid_size(&current_user.nt_user_token->user_sids[i]);
2678 /* SID list byte count */
2679 SIVAL(pdata, 32, sid_bytes);
2681 /* 4 bytes pad/reserved - must be zero */
2682 SIVAL(pdata, 36, 0);
2683 data_len = 40;
2685 /* GID list */
2686 for (i = 0; i < current_user.ut.ngroups; ++i) {
2687 SBIG_UINT(pdata, data_len,
2688 (SMB_BIG_UINT)current_user.ut.groups[i]);
2689 data_len += 8;
2692 /* SID list */
2693 for (i = 0;
2694 i < current_user.nt_user_token->num_sids; ++i) {
2695 int sid_len =
2696 sid_size(&current_user.nt_user_token->user_sids[i]);
2698 sid_linearize(pdata + data_len, sid_len,
2699 &current_user.nt_user_token->user_sids[i]);
2700 data_len += sid_len;
2703 break;
2706 case SMB_MAC_QUERY_FS_INFO:
2708 * Thursby MAC extension... ONLY on NTFS filesystems
2709 * once we do streams then we don't need this
2711 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2712 data_len = 88;
2713 SIVAL(pdata,84,0x100); /* Don't support mac... */
2714 break;
2716 /* drop through */
2717 default:
2718 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2722 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2724 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2726 return -1;
2729 /****************************************************************************
2730 Reply to a TRANS2_SETFSINFO (set filesystem info).
2731 ****************************************************************************/
2733 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2734 char **pparams, int total_params, char **ppdata, int total_data,
2735 unsigned int max_data_bytes)
2737 char *pdata = *ppdata;
2738 char *params = *pparams;
2739 uint16 info_level;
2740 int outsize;
2742 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2744 /* */
2745 if (total_params < 4) {
2746 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2747 total_params));
2748 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2751 info_level = SVAL(params,2);
2753 switch(info_level) {
2754 case SMB_SET_CIFS_UNIX_INFO:
2756 uint16 client_unix_major;
2757 uint16 client_unix_minor;
2758 uint32 client_unix_cap_low;
2759 uint32 client_unix_cap_high;
2761 if (!lp_unix_extensions()) {
2762 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2765 /* There should be 12 bytes of capabilities set. */
2766 if (total_data < 8) {
2767 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2769 client_unix_major = SVAL(pdata,0);
2770 client_unix_minor = SVAL(pdata,2);
2771 client_unix_cap_low = IVAL(pdata,4);
2772 client_unix_cap_high = IVAL(pdata,8);
2773 /* Just print these values for now. */
2774 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2775 cap_low = 0x%x, cap_high = 0x%x\n",
2776 (unsigned int)client_unix_major,
2777 (unsigned int)client_unix_minor,
2778 (unsigned int)client_unix_cap_low,
2779 (unsigned int)client_unix_cap_high ));
2781 /* Here is where we must switch to posix pathname processing... */
2782 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2783 lp_set_posix_pathnames();
2784 mangle_change_to_posix();
2787 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2788 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2789 /* Client that knows how to do posix locks,
2790 * but not posix open/mkdir operations. Set a
2791 * default type for read/write checks. */
2793 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2796 break;
2798 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2800 NTSTATUS status;
2801 size_t param_len = 0;
2802 size_t data_len = total_data;
2804 if (!lp_unix_extensions()) {
2805 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2808 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2810 status = srv_request_encryption_setup(conn,
2811 (unsigned char **)ppdata,
2812 &data_len,
2813 (unsigned char **)pparams,
2814 &param_len
2817 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2818 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2819 } else if (!NT_STATUS_IS_OK(status)) {
2820 return ERROR_NT(status);
2823 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2825 if (NT_STATUS_IS_OK(status)) {
2826 /* Server-side transport encryption is now *on*. */
2827 status = srv_encryption_start(conn);
2828 if (!NT_STATUS_IS_OK(status)) {
2829 exit_server_cleanly("Failure in setting up encrypted transport");
2832 return -1;
2834 case SMB_FS_QUOTA_INFORMATION:
2836 files_struct *fsp = NULL;
2837 SMB_NTQUOTA_STRUCT quotas;
2839 ZERO_STRUCT(quotas);
2841 /* access check */
2842 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2843 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2844 lp_servicename(SNUM(conn)),conn->user));
2845 return ERROR_DOS(ERRSRV,ERRaccess);
2848 /* note: normaly there're 48 bytes,
2849 * but we didn't use the last 6 bytes for now
2850 * --metze
2852 fsp = file_fsp(params,0);
2853 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2854 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2855 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2858 if (total_data < 42) {
2859 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2860 total_data));
2861 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2864 /* unknown_1 24 NULL bytes in pdata*/
2866 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2867 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2868 #ifdef LARGE_SMB_OFF_T
2869 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2870 #else /* LARGE_SMB_OFF_T */
2871 if ((IVAL(pdata,28) != 0)&&
2872 ((quotas.softlim != 0xFFFFFFFF)||
2873 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2874 /* more than 32 bits? */
2875 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2877 #endif /* LARGE_SMB_OFF_T */
2879 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2880 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2881 #ifdef LARGE_SMB_OFF_T
2882 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2883 #else /* LARGE_SMB_OFF_T */
2884 if ((IVAL(pdata,36) != 0)&&
2885 ((quotas.hardlim != 0xFFFFFFFF)||
2886 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2887 /* more than 32 bits? */
2888 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2890 #endif /* LARGE_SMB_OFF_T */
2892 /* quota_flags 2 bytes **/
2893 quotas.qflags = SVAL(pdata,40);
2895 /* unknown_2 6 NULL bytes follow*/
2897 /* now set the quotas */
2898 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2899 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2900 return ERROR_DOS(ERRSRV,ERRerror);
2903 break;
2905 default:
2906 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2907 info_level));
2908 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2909 break;
2913 * sending this reply works fine,
2914 * but I'm not sure it's the same
2915 * like windows do...
2916 * --metze
2918 outsize = set_message(inbuf, outbuf,10,0,True);
2920 return outsize;
2923 #if defined(HAVE_POSIX_ACLS)
2924 /****************************************************************************
2925 Utility function to count the number of entries in a POSIX acl.
2926 ****************************************************************************/
2928 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2930 unsigned int ace_count = 0;
2931 int entry_id = SMB_ACL_FIRST_ENTRY;
2932 SMB_ACL_ENTRY_T entry;
2934 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2935 /* get_next... */
2936 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2937 entry_id = SMB_ACL_NEXT_ENTRY;
2939 ace_count++;
2941 return ace_count;
2944 /****************************************************************************
2945 Utility function to marshall a POSIX acl into wire format.
2946 ****************************************************************************/
2948 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2950 int entry_id = SMB_ACL_FIRST_ENTRY;
2951 SMB_ACL_ENTRY_T entry;
2953 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2954 SMB_ACL_TAG_T tagtype;
2955 SMB_ACL_PERMSET_T permset;
2956 unsigned char perms = 0;
2957 unsigned int own_grp;
2959 /* get_next... */
2960 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2961 entry_id = SMB_ACL_NEXT_ENTRY;
2964 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2965 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2966 return False;
2969 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2970 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2971 return False;
2974 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2975 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2976 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2978 SCVAL(pdata,1,perms);
2980 switch (tagtype) {
2981 case SMB_ACL_USER_OBJ:
2982 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2983 own_grp = (unsigned int)pst->st_uid;
2984 SIVAL(pdata,2,own_grp);
2985 SIVAL(pdata,6,0);
2986 break;
2987 case SMB_ACL_USER:
2989 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2990 if (!puid) {
2991 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2993 own_grp = (unsigned int)*puid;
2994 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2995 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2996 SIVAL(pdata,2,own_grp);
2997 SIVAL(pdata,6,0);
2998 break;
3000 case SMB_ACL_GROUP_OBJ:
3001 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3002 own_grp = (unsigned int)pst->st_gid;
3003 SIVAL(pdata,2,own_grp);
3004 SIVAL(pdata,6,0);
3005 break;
3006 case SMB_ACL_GROUP:
3008 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3009 if (!pgid) {
3010 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3012 own_grp = (unsigned int)*pgid;
3013 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3014 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3015 SIVAL(pdata,2,own_grp);
3016 SIVAL(pdata,6,0);
3017 break;
3019 case SMB_ACL_MASK:
3020 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3021 SIVAL(pdata,2,0xFFFFFFFF);
3022 SIVAL(pdata,6,0xFFFFFFFF);
3023 break;
3024 case SMB_ACL_OTHER:
3025 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3026 SIVAL(pdata,2,0xFFFFFFFF);
3027 SIVAL(pdata,6,0xFFFFFFFF);
3028 break;
3029 default:
3030 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3031 return False;
3033 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3036 return True;
3038 #endif
3040 /****************************************************************************
3041 Store the FILE_UNIX_BASIC info.
3042 ****************************************************************************/
3044 static char *store_file_unix_basic(connection_struct *conn,
3045 char *pdata,
3046 files_struct *fsp,
3047 const SMB_STRUCT_STAT *psbuf)
3049 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3050 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3052 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3053 pdata += 8;
3055 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3056 pdata += 8;
3058 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3059 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3060 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3061 pdata += 24;
3063 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3064 SIVAL(pdata,4,0);
3065 pdata += 8;
3067 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3068 SIVAL(pdata,4,0);
3069 pdata += 8;
3071 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3072 pdata += 4;
3074 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3075 SIVAL(pdata,4,0);
3076 pdata += 8;
3078 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3079 SIVAL(pdata,4,0);
3080 pdata += 8;
3082 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3083 pdata += 8;
3085 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3086 SIVAL(pdata,4,0);
3087 pdata += 8;
3089 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3090 SIVAL(pdata,4,0);
3091 pdata += 8;
3093 return pdata;
3096 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3097 * the chflags(2) (or equivalent) flags.
3099 * XXX: this really should be behind the VFS interface. To do this, we would
3100 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3101 * Each VFS module could then implement it's own mapping as appropriate for the
3102 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3104 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3105 info2_flags_map[] =
3107 #ifdef UF_NODUMP
3108 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3109 #endif
3111 #ifdef UF_IMMUTABLE
3112 { UF_IMMUTABLE, EXT_IMMUTABLE },
3113 #endif
3115 #ifdef UF_APPEND
3116 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3117 #endif
3119 #ifdef UF_HIDDEN
3120 { UF_HIDDEN, EXT_HIDDEN },
3121 #endif
3123 /* Do not remove. We need to guarantee that this array has at least one
3124 * entry to build on HP-UX.
3126 { 0, 0 }
3130 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3131 uint32 *smb_fflags, uint32 *smb_fmask)
3133 #ifdef HAVE_STAT_ST_FLAGS
3134 int i;
3136 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3137 *smb_fmask |= info2_flags_map[i].smb_fflag;
3138 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3139 *smb_fflags |= info2_flags_map[i].smb_fflag;
3142 #endif /* HAVE_STAT_ST_FLAGS */
3145 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3146 const uint32 smb_fflags,
3147 const uint32 smb_fmask,
3148 int *stat_fflags)
3150 #ifdef HAVE_STAT_ST_FLAGS
3151 uint32 max_fmask = 0;
3152 int i;
3154 *stat_fflags = psbuf->st_flags;
3156 /* For each flags requested in smb_fmask, check the state of the
3157 * corresponding flag in smb_fflags and set or clear the matching
3158 * stat flag.
3161 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3162 max_fmask |= info2_flags_map[i].smb_fflag;
3163 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3164 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3165 *stat_fflags |= info2_flags_map[i].stat_fflag;
3166 } else {
3167 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3172 /* If smb_fmask is asking to set any bits that are not supported by
3173 * our flag mappings, we should fail.
3175 if ((smb_fmask & max_fmask) != smb_fmask) {
3176 return False;
3179 return True;
3180 #else
3181 return False;
3182 #endif /* HAVE_STAT_ST_FLAGS */
3186 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3187 * of file flags and birth (create) time.
3189 static char *store_file_unix_basic_info2(connection_struct *conn,
3190 char *pdata,
3191 files_struct *fsp,
3192 const SMB_STRUCT_STAT *psbuf)
3194 uint32 file_flags = 0;
3195 uint32 flags_mask = 0;
3197 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3199 /* Create (birth) time 64 bit */
3200 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3201 pdata += 8;
3203 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3204 SIVAL(pdata, 0, file_flags); /* flags */
3205 SIVAL(pdata, 4, flags_mask); /* mask */
3206 pdata += 8;
3208 return pdata;
3211 /****************************************************************************
3212 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3213 ****************************************************************************/
3215 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3216 unsigned int tran_call,
3217 char **pparams, int total_params, char **ppdata, int total_data,
3218 unsigned int max_data_bytes)
3220 char *params = *pparams;
3221 char *pdata = *ppdata;
3222 unsigned int data_size = 0;
3223 unsigned int param_size = 2;
3224 uint16 info_level;
3225 smb_np_struct *p_pipe = NULL;
3227 if (!params) {
3228 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3231 if (total_params < 4) {
3232 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3235 p_pipe = get_rpc_pipe_p(params,0);
3236 if (p_pipe == NULL) {
3237 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3240 info_level = SVAL(params,2);
3242 *pparams = (char *)SMB_REALLOC(*pparams,2);
3243 if (*pparams == NULL) {
3244 return ERROR_NT(NT_STATUS_NO_MEMORY);
3246 params = *pparams;
3247 SSVAL(params,0,0);
3248 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3249 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3250 if (*ppdata == NULL ) {
3251 return ERROR_NT(NT_STATUS_NO_MEMORY);
3253 pdata = *ppdata;
3255 switch (info_level) {
3256 case SMB_FILE_STANDARD_INFORMATION:
3257 memset(pdata,24,0);
3258 SOFF_T(pdata,0,4096LL);
3259 SIVAL(pdata,16,1);
3260 SIVAL(pdata,20,1);
3261 data_size = 24;
3262 break;
3264 default:
3265 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3268 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3270 return(-1);
3273 /****************************************************************************
3274 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3275 file name or file id).
3276 ****************************************************************************/
3278 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3279 unsigned int tran_call,
3280 char **pparams, int total_params, char **ppdata, int total_data,
3281 unsigned int max_data_bytes)
3283 char *params = *pparams;
3284 char *pdata = *ppdata;
3285 uint16 info_level;
3286 int mode=0;
3287 int nlink;
3288 SMB_OFF_T file_size=0;
3289 SMB_BIG_UINT allocation_size=0;
3290 unsigned int data_size = 0;
3291 unsigned int param_size = 2;
3292 SMB_STRUCT_STAT sbuf;
3293 pstring fname, dos_fname;
3294 char *fullpathname;
3295 char *base_name;
3296 char *p;
3297 SMB_OFF_T pos = 0;
3298 BOOL delete_pending = False;
3299 int len;
3300 time_t create_time, mtime, atime;
3301 struct timespec create_time_ts, mtime_ts, atime_ts;
3302 files_struct *fsp = NULL;
3303 TALLOC_CTX *data_ctx = NULL;
3304 struct ea_list *ea_list = NULL;
3305 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3306 char *lock_data = NULL;
3308 if (!params)
3309 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3311 ZERO_STRUCT(sbuf);
3313 if (tran_call == TRANSACT2_QFILEINFO) {
3314 if (total_params < 4) {
3315 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3318 if (IS_IPC(conn)) {
3319 return call_trans2qpipeinfo(conn,
3320 inbuf,
3321 outbuf,
3322 length,
3323 bufsize,
3324 tran_call,
3325 pparams,
3326 total_params,
3327 ppdata,
3328 total_data,
3329 max_data_bytes);
3332 fsp = file_fsp(params,0);
3333 info_level = SVAL(params,2);
3335 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3337 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3338 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3341 if(fsp && (fsp->fake_file_handle)) {
3343 * This is actually for the QUOTA_FAKE_FILE --metze
3346 pstrcpy(fname, fsp->fsp_name);
3347 /* We know this name is ok, it's already passed the checks. */
3349 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3351 * This is actually a QFILEINFO on a directory
3352 * handle (returned from an NT SMB). NT5.0 seems
3353 * to do this call. JRA.
3355 /* We know this name is ok, it's already passed the checks. */
3356 pstrcpy(fname, fsp->fsp_name);
3358 if (INFO_LEVEL_IS_UNIX(info_level)) {
3359 /* Always do lstat for UNIX calls. */
3360 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3361 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3362 return UNIXERROR(ERRDOS,ERRbadpath);
3364 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3365 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3366 return UNIXERROR(ERRDOS,ERRbadpath);
3369 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3370 } else {
3372 * Original code - this is an open file.
3374 CHECK_FSP(fsp,conn);
3376 pstrcpy(fname, fsp->fsp_name);
3377 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3378 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3379 return(UNIXERROR(ERRDOS,ERRbadfid));
3381 pos = fsp->fh->position_information;
3382 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3383 access_mask = fsp->access_mask;
3385 } else {
3386 NTSTATUS status = NT_STATUS_OK;
3388 /* qpathinfo */
3389 if (total_params < 7) {
3390 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3393 info_level = SVAL(params,0);
3395 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3397 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3398 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3401 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 return ERROR_NT(status);
3406 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3409 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3411 return ERROR_NT(status);
3414 status = unix_convert(conn, fname, False, NULL, &sbuf);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 return ERROR_NT(status);
3418 status = check_name(conn, fname);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3421 return ERROR_NT(status);
3424 if (INFO_LEVEL_IS_UNIX(info_level)) {
3425 /* Always do lstat for UNIX calls. */
3426 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3427 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3428 return UNIXERROR(ERRDOS,ERRbadpath);
3430 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3431 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3432 return UNIXERROR(ERRDOS,ERRbadpath);
3435 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3436 if (delete_pending) {
3437 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3441 nlink = sbuf.st_nlink;
3443 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3444 /* NTFS does not seem to count ".." */
3445 nlink -= 1;
3448 if ((nlink > 0) && delete_pending) {
3449 nlink -= 1;
3452 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3453 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3456 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3457 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3459 p = strrchr_m(fname,'/');
3460 if (!p)
3461 base_name = fname;
3462 else
3463 base_name = p+1;
3465 mode = dos_mode(conn,fname,&sbuf);
3466 if (!mode)
3467 mode = FILE_ATTRIBUTE_NORMAL;
3469 fullpathname = fname;
3470 if (!(mode & aDIR))
3471 file_size = get_file_size(sbuf);
3473 /* Pull out any data sent here before we realloc. */
3474 switch (info_level) {
3475 case SMB_INFO_QUERY_EAS_FROM_LIST:
3477 /* Pull any EA list from the data portion. */
3478 uint32 ea_size;
3480 if (total_data < 4) {
3481 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3483 ea_size = IVAL(pdata,0);
3485 if (total_data > 0 && ea_size != total_data) {
3486 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3487 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3488 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3491 if (!lp_ea_support(SNUM(conn))) {
3492 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3495 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3496 return ERROR_NT(NT_STATUS_NO_MEMORY);
3499 /* Pull out the list of names. */
3500 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3501 if (!ea_list) {
3502 talloc_destroy(data_ctx);
3503 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3505 break;
3508 case SMB_QUERY_POSIX_LOCK:
3510 if (fsp == NULL || fsp->fh->fd == -1) {
3511 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3514 if (total_data != POSIX_LOCK_DATA_SIZE) {
3515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3518 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3519 return ERROR_NT(NT_STATUS_NO_MEMORY);
3522 /* Copy the lock range data. */
3523 lock_data = (char *)TALLOC_MEMDUP(
3524 data_ctx, pdata, total_data);
3525 if (!lock_data) {
3526 talloc_destroy(data_ctx);
3527 return ERROR_NT(NT_STATUS_NO_MEMORY);
3530 default:
3531 break;
3534 *pparams = (char *)SMB_REALLOC(*pparams,2);
3535 if (*pparams == NULL) {
3536 talloc_destroy(data_ctx);
3537 return ERROR_NT(NT_STATUS_NO_MEMORY);
3539 params = *pparams;
3540 SSVAL(params,0,0);
3541 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3542 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3543 if (*ppdata == NULL ) {
3544 talloc_destroy(data_ctx);
3545 return ERROR_NT(NT_STATUS_NO_MEMORY);
3547 pdata = *ppdata;
3549 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3550 mtime_ts = get_mtimespec(&sbuf);
3551 atime_ts = get_atimespec(&sbuf);
3553 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3555 if (fsp) {
3556 if (!null_timespec(fsp->pending_modtime)) {
3557 /* the pending modtime overrides the current modtime */
3558 mtime_ts = fsp->pending_modtime;
3560 } else {
3561 /* Do we have this path open ? */
3562 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3563 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3564 /* the pending modtime overrides the current modtime */
3565 mtime_ts = fsp1->pending_modtime;
3567 if (fsp1 && fsp1->initial_allocation_size) {
3568 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3572 if (lp_dos_filetime_resolution(SNUM(conn))) {
3573 dos_filetime_timespec(&create_time_ts);
3574 dos_filetime_timespec(&mtime_ts);
3575 dos_filetime_timespec(&atime_ts);
3578 create_time = convert_timespec_to_time_t(create_time_ts);
3579 mtime = convert_timespec_to_time_t(mtime_ts);
3580 atime = convert_timespec_to_time_t(atime_ts);
3582 /* NT expects the name to be in an exact form of the *full*
3583 filename. See the trans2 torture test */
3584 if (strequal(base_name,".")) {
3585 pstrcpy(dos_fname, "\\");
3586 } else {
3587 pstr_sprintf(dos_fname, "\\%s", fname);
3588 string_replace(dos_fname, '/', '\\');
3591 switch (info_level) {
3592 case SMB_INFO_STANDARD:
3593 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3594 data_size = 22;
3595 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3596 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3597 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3598 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3599 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3600 SSVAL(pdata,l1_attrFile,mode);
3601 break;
3603 case SMB_INFO_QUERY_EA_SIZE:
3605 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3606 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3607 data_size = 26;
3608 srv_put_dos_date2(pdata,0,create_time);
3609 srv_put_dos_date2(pdata,4,atime);
3610 srv_put_dos_date2(pdata,8,mtime); /* write time */
3611 SIVAL(pdata,12,(uint32)file_size);
3612 SIVAL(pdata,16,(uint32)allocation_size);
3613 SSVAL(pdata,20,mode);
3614 SIVAL(pdata,22,ea_size);
3615 break;
3618 case SMB_INFO_IS_NAME_VALID:
3619 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3620 if (tran_call == TRANSACT2_QFILEINFO) {
3621 /* os/2 needs this ? really ?*/
3622 return ERROR_DOS(ERRDOS,ERRbadfunc);
3624 data_size = 0;
3625 param_size = 0;
3626 break;
3628 case SMB_INFO_QUERY_EAS_FROM_LIST:
3630 size_t total_ea_len = 0;
3631 struct ea_list *ea_file_list = NULL;
3633 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3635 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3636 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3638 if (!ea_list || (total_ea_len > data_size)) {
3639 talloc_destroy(data_ctx);
3640 data_size = 4;
3641 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3642 break;
3645 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3646 talloc_destroy(data_ctx);
3647 break;
3650 case SMB_INFO_QUERY_ALL_EAS:
3652 /* We have data_size bytes to put EA's into. */
3653 size_t total_ea_len = 0;
3655 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3657 data_ctx = talloc_init("ea_ctx");
3658 if (!data_ctx) {
3659 return ERROR_NT(NT_STATUS_NO_MEMORY);
3662 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3663 if (!ea_list || (total_ea_len > data_size)) {
3664 talloc_destroy(data_ctx);
3665 data_size = 4;
3666 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3667 break;
3670 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3671 talloc_destroy(data_ctx);
3672 break;
3675 case SMB_FILE_BASIC_INFORMATION:
3676 case SMB_QUERY_FILE_BASIC_INFO:
3678 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3679 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3680 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3681 } else {
3682 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3683 data_size = 40;
3684 SIVAL(pdata,36,0);
3686 put_long_date_timespec(pdata,create_time_ts);
3687 put_long_date_timespec(pdata+8,atime_ts);
3688 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3689 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3690 SIVAL(pdata,32,mode);
3692 DEBUG(5,("SMB_QFBI - "));
3693 DEBUG(5,("create: %s ", ctime(&create_time)));
3694 DEBUG(5,("access: %s ", ctime(&atime)));
3695 DEBUG(5,("write: %s ", ctime(&mtime)));
3696 DEBUG(5,("change: %s ", ctime(&mtime)));
3697 DEBUG(5,("mode: %x\n", mode));
3698 break;
3700 case SMB_FILE_STANDARD_INFORMATION:
3701 case SMB_QUERY_FILE_STANDARD_INFO:
3703 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3704 data_size = 24;
3705 SOFF_T(pdata,0,allocation_size);
3706 SOFF_T(pdata,8,file_size);
3707 SIVAL(pdata,16,nlink);
3708 SCVAL(pdata,20,delete_pending?1:0);
3709 SCVAL(pdata,21,(mode&aDIR)?1:0);
3710 SSVAL(pdata,22,0); /* Padding. */
3711 break;
3713 case SMB_FILE_EA_INFORMATION:
3714 case SMB_QUERY_FILE_EA_INFO:
3716 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3717 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3718 data_size = 4;
3719 SIVAL(pdata,0,ea_size);
3720 break;
3723 /* Get the 8.3 name - used if NT SMB was negotiated. */
3724 case SMB_QUERY_FILE_ALT_NAME_INFO:
3725 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3727 pstring short_name;
3729 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3730 pstrcpy(short_name,base_name);
3731 /* Mangle if not already 8.3 */
3732 if(!mangle_is_8_3(short_name, True, conn->params)) {
3733 mangle_map(short_name,True,True,conn->params);
3735 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3736 data_size = 4 + len;
3737 SIVAL(pdata,0,len);
3738 break;
3741 case SMB_QUERY_FILE_NAME_INFO:
3743 this must be *exactly* right for ACLs on mapped drives to work
3745 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3746 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3747 data_size = 4 + len;
3748 SIVAL(pdata,0,len);
3749 break;
3751 case SMB_FILE_ALLOCATION_INFORMATION:
3752 case SMB_QUERY_FILE_ALLOCATION_INFO:
3753 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3754 data_size = 8;
3755 SOFF_T(pdata,0,allocation_size);
3756 break;
3758 case SMB_FILE_END_OF_FILE_INFORMATION:
3759 case SMB_QUERY_FILE_END_OF_FILEINFO:
3760 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3761 data_size = 8;
3762 SOFF_T(pdata,0,file_size);
3763 break;
3765 case SMB_QUERY_FILE_ALL_INFO:
3766 case SMB_FILE_ALL_INFORMATION:
3768 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3769 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3770 put_long_date_timespec(pdata,create_time_ts);
3771 put_long_date_timespec(pdata+8,atime_ts);
3772 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3773 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3774 SIVAL(pdata,32,mode);
3775 SIVAL(pdata,36,0); /* padding. */
3776 pdata += 40;
3777 SOFF_T(pdata,0,allocation_size);
3778 SOFF_T(pdata,8,file_size);
3779 SIVAL(pdata,16,nlink);
3780 SCVAL(pdata,20,delete_pending);
3781 SCVAL(pdata,21,(mode&aDIR)?1:0);
3782 SSVAL(pdata,22,0);
3783 pdata += 24;
3784 SIVAL(pdata,0,ea_size);
3785 pdata += 4; /* EA info */
3786 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3787 SIVAL(pdata,0,len);
3788 pdata += 4 + len;
3789 data_size = PTR_DIFF(pdata,(*ppdata));
3790 break;
3792 case SMB_FILE_INTERNAL_INFORMATION:
3793 /* This should be an index number - looks like
3794 dev/ino to me :-)
3796 I think this causes us to fail the IFSKIT
3797 BasicFileInformationTest. -tpot */
3799 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3800 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3801 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3802 data_size = 8;
3803 break;
3805 case SMB_FILE_ACCESS_INFORMATION:
3806 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3807 SIVAL(pdata,0,access_mask);
3808 data_size = 4;
3809 break;
3811 case SMB_FILE_NAME_INFORMATION:
3812 /* Pathname with leading '\'. */
3814 size_t byte_len;
3815 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3816 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3817 SIVAL(pdata,0,byte_len);
3818 data_size = 4 + byte_len;
3819 break;
3822 case SMB_FILE_DISPOSITION_INFORMATION:
3823 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3824 data_size = 1;
3825 SCVAL(pdata,0,delete_pending);
3826 break;
3828 case SMB_FILE_POSITION_INFORMATION:
3829 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3830 data_size = 8;
3831 SOFF_T(pdata,0,pos);
3832 break;
3834 case SMB_FILE_MODE_INFORMATION:
3835 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3836 SIVAL(pdata,0,mode);
3837 data_size = 4;
3838 break;
3840 case SMB_FILE_ALIGNMENT_INFORMATION:
3841 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3842 SIVAL(pdata,0,0); /* No alignment needed. */
3843 data_size = 4;
3844 break;
3846 #if 0
3848 * NT4 server just returns "invalid query" to this - if we try to answer
3849 * it then NTws gets a BSOD! (tridge).
3850 * W2K seems to want this. JRA.
3852 case SMB_QUERY_FILE_STREAM_INFO:
3853 #endif
3854 case SMB_FILE_STREAM_INFORMATION:
3855 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3856 if (mode & aDIR) {
3857 data_size = 0;
3858 } else {
3859 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3860 SIVAL(pdata,0,0); /* ??? */
3861 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3862 SOFF_T(pdata,8,file_size);
3863 SOFF_T(pdata,16,allocation_size);
3864 data_size = 24 + byte_len;
3866 break;
3868 case SMB_QUERY_COMPRESSION_INFO:
3869 case SMB_FILE_COMPRESSION_INFORMATION:
3870 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3871 SOFF_T(pdata,0,file_size);
3872 SIVAL(pdata,8,0); /* ??? */
3873 SIVAL(pdata,12,0); /* ??? */
3874 data_size = 16;
3875 break;
3877 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3878 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3879 put_long_date_timespec(pdata,create_time_ts);
3880 put_long_date_timespec(pdata+8,atime_ts);
3881 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3882 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3883 SOFF_T(pdata,32,allocation_size);
3884 SOFF_T(pdata,40,file_size);
3885 SIVAL(pdata,48,mode);
3886 SIVAL(pdata,52,0); /* ??? */
3887 data_size = 56;
3888 break;
3890 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3891 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3892 SIVAL(pdata,0,mode);
3893 SIVAL(pdata,4,0);
3894 data_size = 8;
3895 break;
3898 * CIFS UNIX Extensions.
3901 case SMB_QUERY_FILE_UNIX_BASIC:
3903 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3904 data_size = PTR_DIFF(pdata,(*ppdata));
3907 int i;
3908 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3910 for (i=0; i<100; i++)
3911 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3912 DEBUG(4,("\n"));
3915 break;
3917 case SMB_QUERY_FILE_UNIX_INFO2:
3919 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3920 data_size = PTR_DIFF(pdata,(*ppdata));
3923 int i;
3924 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3926 for (i=0; i<100; i++)
3927 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3928 DEBUG(4,("\n"));
3931 break;
3933 case SMB_QUERY_FILE_UNIX_LINK:
3935 pstring buffer;
3937 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3938 #ifdef S_ISLNK
3939 if(!S_ISLNK(sbuf.st_mode))
3940 return(UNIXERROR(ERRSRV,ERRbadlink));
3941 #else
3942 return(UNIXERROR(ERRDOS,ERRbadlink));
3943 #endif
3944 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3945 if (len == -1)
3946 return(UNIXERROR(ERRDOS,ERRnoaccess));
3947 buffer[len] = 0;
3948 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3949 pdata += len;
3950 data_size = PTR_DIFF(pdata,(*ppdata));
3952 break;
3955 #if defined(HAVE_POSIX_ACLS)
3956 case SMB_QUERY_POSIX_ACL:
3958 SMB_ACL_T file_acl = NULL;
3959 SMB_ACL_T def_acl = NULL;
3960 uint16 num_file_acls = 0;
3961 uint16 num_def_acls = 0;
3963 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3964 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3965 } else {
3966 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3969 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3970 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3971 fname ));
3972 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3975 if (S_ISDIR(sbuf.st_mode)) {
3976 if (fsp && fsp->is_directory) {
3977 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3978 } else {
3979 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3981 def_acl = free_empty_sys_acl(conn, def_acl);
3984 num_file_acls = count_acl_entries(conn, file_acl);
3985 num_def_acls = count_acl_entries(conn, def_acl);
3987 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3988 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3989 data_size,
3990 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3991 SMB_POSIX_ACL_HEADER_SIZE) ));
3992 if (file_acl) {
3993 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3995 if (def_acl) {
3996 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3998 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4001 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4002 SSVAL(pdata,2,num_file_acls);
4003 SSVAL(pdata,4,num_def_acls);
4004 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4005 if (file_acl) {
4006 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4008 if (def_acl) {
4009 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4011 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4013 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4014 if (file_acl) {
4015 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4017 if (def_acl) {
4018 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4020 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4023 if (file_acl) {
4024 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4026 if (def_acl) {
4027 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4029 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4030 break;
4032 #endif
4035 case SMB_QUERY_POSIX_LOCK:
4037 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4038 SMB_BIG_UINT count;
4039 SMB_BIG_UINT offset;
4040 uint32 lock_pid;
4041 enum brl_type lock_type;
4043 if (total_data != POSIX_LOCK_DATA_SIZE) {
4044 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4047 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4048 case POSIX_LOCK_TYPE_READ:
4049 lock_type = READ_LOCK;
4050 break;
4051 case POSIX_LOCK_TYPE_WRITE:
4052 lock_type = WRITE_LOCK;
4053 break;
4054 case POSIX_LOCK_TYPE_UNLOCK:
4055 default:
4056 /* There's no point in asking for an unlock... */
4057 talloc_destroy(data_ctx);
4058 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4061 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4062 #if defined(HAVE_LONGLONG)
4063 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4064 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4065 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4066 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4067 #else /* HAVE_LONGLONG */
4068 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4069 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4070 #endif /* HAVE_LONGLONG */
4072 status = query_lock(fsp,
4073 &lock_pid,
4074 &count,
4075 &offset,
4076 &lock_type,
4077 POSIX_LOCK);
4079 if (ERROR_WAS_LOCK_DENIED(status)) {
4080 /* Here we need to report who has it locked... */
4081 data_size = POSIX_LOCK_DATA_SIZE;
4083 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4084 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4085 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4086 #if defined(HAVE_LONGLONG)
4087 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4088 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4089 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4090 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4091 #else /* HAVE_LONGLONG */
4092 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4093 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4094 #endif /* HAVE_LONGLONG */
4096 } else if (NT_STATUS_IS_OK(status)) {
4097 /* For success we just return a copy of what we sent
4098 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4099 data_size = POSIX_LOCK_DATA_SIZE;
4100 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4101 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4102 } else {
4103 return ERROR_NT(status);
4105 break;
4108 default:
4109 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4112 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4114 return(-1);
4117 /****************************************************************************
4118 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4119 code.
4120 ****************************************************************************/
4122 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4124 SMB_STRUCT_STAT sbuf1, sbuf2;
4125 pstring last_component_oldname;
4126 pstring last_component_newname;
4127 NTSTATUS status = NT_STATUS_OK;
4129 ZERO_STRUCT(sbuf1);
4130 ZERO_STRUCT(sbuf2);
4132 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4133 if (!NT_STATUS_IS_OK(status)) {
4134 return status;
4137 status = check_name(conn, oldname);
4138 if (!NT_STATUS_IS_OK(status)) {
4139 return status;
4142 /* source must already exist. */
4143 if (!VALID_STAT(sbuf1)) {
4144 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4147 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4148 if (!NT_STATUS_IS_OK(status)) {
4149 return status;
4152 status = check_name(conn, newname);
4153 if (!NT_STATUS_IS_OK(status)) {
4154 return status;
4157 /* Disallow if newname already exists. */
4158 if (VALID_STAT(sbuf2)) {
4159 return NT_STATUS_OBJECT_NAME_COLLISION;
4162 /* No links from a directory. */
4163 if (S_ISDIR(sbuf1.st_mode)) {
4164 return NT_STATUS_FILE_IS_A_DIRECTORY;
4167 /* Ensure this is within the share. */
4168 status = reduce_name(conn, oldname);
4169 if (!NT_STATUS_IS_OK(status)) {
4170 return status;
4173 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4175 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4176 status = map_nt_error_from_unix(errno);
4177 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4178 nt_errstr(status), newname, oldname));
4181 return status;
4184 /****************************************************************************
4185 Deal with setting the time from any of the setfilepathinfo functions.
4186 ****************************************************************************/
4188 static NTSTATUS smb_set_file_time(connection_struct *conn,
4189 files_struct *fsp,
4190 const char *fname,
4191 const SMB_STRUCT_STAT *psbuf,
4192 struct timespec ts[2])
4194 uint32 action =
4195 FILE_NOTIFY_CHANGE_LAST_ACCESS
4196 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4199 if (!VALID_STAT(*psbuf)) {
4200 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4203 /* get some defaults (no modifications) if any info is zero or -1. */
4204 if (null_timespec(ts[0])) {
4205 ts[0] = get_atimespec(psbuf);
4206 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4209 if (null_timespec(ts[1])) {
4210 ts[1] = get_mtimespec(psbuf);
4211 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4214 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4215 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4218 * Try and set the times of this file if
4219 * they are different from the current values.
4223 struct timespec mts = get_mtimespec(psbuf);
4224 struct timespec ats = get_atimespec(psbuf);
4225 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4226 return NT_STATUS_OK;
4230 if(fsp != NULL) {
4232 * This was a setfileinfo on an open file.
4233 * NT does this a lot. We also need to
4234 * set the time here, as it can be read by
4235 * FindFirst/FindNext and with the patch for bug #2045
4236 * in smbd/fileio.c it ensures that this timestamp is
4237 * kept sticky even after a write. We save the request
4238 * away and will set it on file close and after a write. JRA.
4241 if (!null_timespec(ts[1])) {
4242 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4243 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4244 fsp_set_pending_modtime(fsp, ts[1]);
4248 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4250 if(file_ntimes(conn, fname, ts)!=0) {
4251 return map_nt_error_from_unix(errno);
4253 if (action != 0) {
4254 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4256 return NT_STATUS_OK;
4259 /****************************************************************************
4260 Deal with setting the dosmode from any of the setfilepathinfo functions.
4261 ****************************************************************************/
4263 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4264 const char *fname,
4265 SMB_STRUCT_STAT *psbuf,
4266 uint32 dosmode)
4268 if (!VALID_STAT(*psbuf)) {
4269 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4272 if (dosmode) {
4273 if (S_ISDIR(psbuf->st_mode)) {
4274 dosmode |= aDIR;
4275 } else {
4276 dosmode &= ~aDIR;
4280 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4282 /* check the mode isn't different, before changing it */
4283 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4285 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4286 fname, (unsigned int)dosmode ));
4288 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4289 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4290 fname, strerror(errno)));
4291 return map_nt_error_from_unix(errno);
4294 return NT_STATUS_OK;
4297 /****************************************************************************
4298 Deal with setting the size from any of the setfilepathinfo functions.
4299 ****************************************************************************/
4301 static NTSTATUS smb_set_file_size(connection_struct *conn,
4302 files_struct *fsp,
4303 const char *fname,
4304 SMB_STRUCT_STAT *psbuf,
4305 SMB_OFF_T size)
4307 NTSTATUS status = NT_STATUS_OK;
4308 files_struct *new_fsp = NULL;
4310 if (!VALID_STAT(*psbuf)) {
4311 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4314 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4316 if (size == get_file_size(*psbuf)) {
4317 return NT_STATUS_OK;
4320 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4321 fname, (double)size ));
4323 if (fsp && fsp->fh->fd != -1) {
4324 /* Handle based call. */
4325 if (vfs_set_filelen(fsp, size) == -1) {
4326 return map_nt_error_from_unix(errno);
4328 return NT_STATUS_OK;
4331 status = open_file_ntcreate(conn, fname, psbuf,
4332 FILE_WRITE_DATA,
4333 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4334 FILE_OPEN,
4336 FILE_ATTRIBUTE_NORMAL,
4337 FORCE_OPLOCK_BREAK_TO_NONE,
4338 NULL, &new_fsp);
4340 if (!NT_STATUS_IS_OK(status)) {
4341 /* NB. We check for open_was_deferred in the caller. */
4342 return status;
4345 if (vfs_set_filelen(new_fsp, size) == -1) {
4346 status = map_nt_error_from_unix(errno);
4347 close_file(new_fsp,NORMAL_CLOSE);
4348 return status;
4351 close_file(new_fsp,NORMAL_CLOSE);
4352 return NT_STATUS_OK;
4355 /****************************************************************************
4356 Deal with SMB_INFO_SET_EA.
4357 ****************************************************************************/
4359 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4360 const char *pdata,
4361 int total_data,
4362 files_struct *fsp,
4363 const char *fname)
4365 struct ea_list *ea_list = NULL;
4366 TALLOC_CTX *ctx = NULL;
4367 NTSTATUS status = NT_STATUS_OK;
4369 if (total_data < 10) {
4371 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4372 length. They seem to have no effect. Bug #3212. JRA */
4374 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4375 /* We're done. We only get EA info in this call. */
4376 return NT_STATUS_OK;
4379 return NT_STATUS_INVALID_PARAMETER;
4382 if (IVAL(pdata,0) > total_data) {
4383 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4384 IVAL(pdata,0), (unsigned int)total_data));
4385 return NT_STATUS_INVALID_PARAMETER;
4388 ctx = talloc_init("SMB_INFO_SET_EA");
4389 if (!ctx) {
4390 return NT_STATUS_NO_MEMORY;
4392 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4393 if (!ea_list) {
4394 talloc_destroy(ctx);
4395 return NT_STATUS_INVALID_PARAMETER;
4397 status = set_ea(conn, fsp, fname, ea_list);
4398 talloc_destroy(ctx);
4400 return status;
4403 /****************************************************************************
4404 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4405 ****************************************************************************/
4407 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4408 const char *pdata,
4409 int total_data,
4410 files_struct *fsp,
4411 const char *fname,
4412 SMB_STRUCT_STAT *psbuf)
4414 NTSTATUS status = NT_STATUS_OK;
4415 BOOL delete_on_close;
4416 uint32 dosmode = 0;
4418 if (total_data < 1) {
4419 return NT_STATUS_INVALID_PARAMETER;
4422 if (fsp == NULL) {
4423 return NT_STATUS_INVALID_HANDLE;
4426 delete_on_close = (CVAL(pdata,0) ? True : False);
4427 dosmode = dos_mode(conn, fname, psbuf);
4429 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4430 "delete_on_close = %u\n",
4431 fsp->fsp_name,
4432 (unsigned int)dosmode,
4433 (unsigned int)delete_on_close ));
4435 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 return status;
4441 /* The set is across all open files on this dev/inode pair. */
4442 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4443 return NT_STATUS_ACCESS_DENIED;
4445 return NT_STATUS_OK;
4448 /****************************************************************************
4449 Deal with SMB_FILE_POSITION_INFORMATION.
4450 ****************************************************************************/
4452 static NTSTATUS smb_file_position_information(connection_struct *conn,
4453 const char *pdata,
4454 int total_data,
4455 files_struct *fsp)
4457 SMB_BIG_UINT position_information;
4459 if (total_data < 8) {
4460 return NT_STATUS_INVALID_PARAMETER;
4463 if (fsp == NULL) {
4464 /* Ignore on pathname based set. */
4465 return NT_STATUS_OK;
4468 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4469 #ifdef LARGE_SMB_OFF_T
4470 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4471 #else /* LARGE_SMB_OFF_T */
4472 if (IVAL(pdata,4) != 0) {
4473 /* more than 32 bits? */
4474 return NT_STATUS_INVALID_PARAMETER;
4476 #endif /* LARGE_SMB_OFF_T */
4478 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4479 fsp->fsp_name, (double)position_information ));
4480 fsp->fh->position_information = position_information;
4481 return NT_STATUS_OK;
4484 /****************************************************************************
4485 Deal with SMB_FILE_MODE_INFORMATION.
4486 ****************************************************************************/
4488 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4489 const char *pdata,
4490 int total_data)
4492 uint32 mode;
4494 if (total_data < 4) {
4495 return NT_STATUS_INVALID_PARAMETER;
4497 mode = IVAL(pdata,0);
4498 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4499 return NT_STATUS_INVALID_PARAMETER;
4501 return NT_STATUS_OK;
4504 /****************************************************************************
4505 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4506 ****************************************************************************/
4508 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4509 char *inbuf,
4510 const char *pdata,
4511 int total_data,
4512 const char *fname)
4514 pstring link_target;
4515 const char *newname = fname;
4516 NTSTATUS status = NT_STATUS_OK;
4518 /* Set a symbolic link. */
4519 /* Don't allow this if follow links is false. */
4521 if (total_data == 0) {
4522 return NT_STATUS_INVALID_PARAMETER;
4525 if (!lp_symlinks(SNUM(conn))) {
4526 return NT_STATUS_ACCESS_DENIED;
4529 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4531 /* !widelinks forces the target path to be within the share. */
4532 /* This means we can interpret the target as a pathname. */
4533 if (!lp_widelinks(SNUM(conn))) {
4534 pstring rel_name;
4535 char *last_dirp = NULL;
4537 if (*link_target == '/') {
4538 /* No absolute paths allowed. */
4539 return NT_STATUS_ACCESS_DENIED;
4541 pstrcpy(rel_name, newname);
4542 last_dirp = strrchr_m(rel_name, '/');
4543 if (last_dirp) {
4544 last_dirp[1] = '\0';
4545 } else {
4546 pstrcpy(rel_name, "./");
4548 pstrcat(rel_name, link_target);
4550 status = check_name(conn, rel_name);
4551 if (!NT_STATUS_IS_OK(status)) {
4552 return status;
4556 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4557 newname, link_target ));
4559 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4560 return map_nt_error_from_unix(errno);
4563 return NT_STATUS_OK;
4566 /****************************************************************************
4567 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4568 ****************************************************************************/
4570 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4571 char *inbuf,
4572 char *outbuf,
4573 const char *pdata,
4574 int total_data,
4575 pstring fname)
4577 pstring oldname;
4578 NTSTATUS status = NT_STATUS_OK;
4580 /* Set a hard link. */
4581 if (total_data == 0) {
4582 return NT_STATUS_INVALID_PARAMETER;
4585 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4586 if (!NT_STATUS_IS_OK(status)) {
4587 return status;
4590 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4591 if (!NT_STATUS_IS_OK(status)) {
4592 return status;
4595 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4596 fname, oldname));
4598 return hardlink_internals(conn, oldname, fname);
4601 /****************************************************************************
4602 Deal with SMB_FILE_RENAME_INFORMATION.
4603 ****************************************************************************/
4605 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4606 char *inbuf,
4607 char *outbuf,
4608 const char *pdata,
4609 int total_data,
4610 files_struct *fsp,
4611 pstring fname)
4613 BOOL overwrite;
4614 /* uint32 root_fid; */ /* Not used */
4615 uint32 len;
4616 pstring newname;
4617 pstring base_name;
4618 BOOL dest_has_wcard = False;
4619 NTSTATUS status = NT_STATUS_OK;
4620 char *p;
4622 if (total_data < 13) {
4623 return NT_STATUS_INVALID_PARAMETER;
4626 overwrite = (CVAL(pdata,0) ? True : False);
4627 /* root_fid = IVAL(pdata,4); */
4628 len = IVAL(pdata,8);
4630 if (len > (total_data - 12) || (len == 0)) {
4631 return NT_STATUS_INVALID_PARAMETER;
4634 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4635 if (!NT_STATUS_IS_OK(status)) {
4636 return status;
4639 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4640 if (!NT_STATUS_IS_OK(status)) {
4641 return status;
4644 /* Check the new name has no '/' characters. */
4645 if (strchr_m(newname, '/')) {
4646 return NT_STATUS_NOT_SUPPORTED;
4649 /* Create the base directory. */
4650 pstrcpy(base_name, fname);
4651 p = strrchr_m(base_name, '/');
4652 if (p) {
4653 p[1] = '\0';
4654 } else {
4655 pstrcpy(base_name, "./");
4657 /* Append the new name. */
4658 pstrcat(base_name, newname);
4660 if (fsp) {
4661 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4662 fsp->fnum, fsp->fsp_name, base_name ));
4663 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4664 } else {
4665 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4666 fname, newname ));
4667 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4670 return status;
4673 /****************************************************************************
4674 Deal with SMB_SET_POSIX_ACL.
4675 ****************************************************************************/
4677 #if defined(HAVE_POSIX_ACLS)
4678 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4679 const char *pdata,
4680 int total_data,
4681 files_struct *fsp,
4682 const char *fname,
4683 SMB_STRUCT_STAT *psbuf)
4685 uint16 posix_acl_version;
4686 uint16 num_file_acls;
4687 uint16 num_def_acls;
4688 BOOL valid_file_acls = True;
4689 BOOL valid_def_acls = True;
4691 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4692 return NT_STATUS_INVALID_PARAMETER;
4694 posix_acl_version = SVAL(pdata,0);
4695 num_file_acls = SVAL(pdata,2);
4696 num_def_acls = SVAL(pdata,4);
4698 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4699 valid_file_acls = False;
4700 num_file_acls = 0;
4703 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4704 valid_def_acls = False;
4705 num_def_acls = 0;
4708 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4709 return NT_STATUS_INVALID_PARAMETER;
4712 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4713 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4714 return NT_STATUS_INVALID_PARAMETER;
4717 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4718 fname ? fname : fsp->fsp_name,
4719 (unsigned int)num_file_acls,
4720 (unsigned int)num_def_acls));
4722 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4723 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4724 return map_nt_error_from_unix(errno);
4727 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4728 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4729 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4730 return map_nt_error_from_unix(errno);
4732 return NT_STATUS_OK;
4734 #endif
4736 /****************************************************************************
4737 Deal with SMB_SET_POSIX_LOCK.
4738 ****************************************************************************/
4740 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4741 char *inbuf,
4742 int length,
4743 const char *pdata,
4744 int total_data,
4745 files_struct *fsp)
4747 SMB_BIG_UINT count;
4748 SMB_BIG_UINT offset;
4749 uint32 lock_pid;
4750 BOOL blocking_lock = False;
4751 enum brl_type lock_type;
4752 NTSTATUS status = NT_STATUS_OK;
4754 if (fsp == NULL || fsp->fh->fd == -1) {
4755 return NT_STATUS_INVALID_HANDLE;
4758 if (total_data != POSIX_LOCK_DATA_SIZE) {
4759 return NT_STATUS_INVALID_PARAMETER;
4762 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4763 case POSIX_LOCK_TYPE_READ:
4764 lock_type = READ_LOCK;
4765 break;
4766 case POSIX_LOCK_TYPE_WRITE:
4767 /* Return the right POSIX-mappable error code for files opened read-only. */
4768 if (!fsp->can_write) {
4769 return NT_STATUS_INVALID_HANDLE;
4771 lock_type = WRITE_LOCK;
4772 break;
4773 case POSIX_LOCK_TYPE_UNLOCK:
4774 lock_type = UNLOCK_LOCK;
4775 break;
4776 default:
4777 return NT_STATUS_INVALID_PARAMETER;
4780 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4781 blocking_lock = False;
4782 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4783 blocking_lock = True;
4784 } else {
4785 return NT_STATUS_INVALID_PARAMETER;
4788 if (!lp_blocking_locks(SNUM(conn))) {
4789 blocking_lock = False;
4792 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4793 #if defined(HAVE_LONGLONG)
4794 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4795 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4796 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4797 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4798 #else /* HAVE_LONGLONG */
4799 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4800 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4801 #endif /* HAVE_LONGLONG */
4803 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4804 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4805 fsp->fsp_name,
4806 (unsigned int)lock_type,
4807 (unsigned int)lock_pid,
4808 (double)count,
4809 (double)offset ));
4811 if (lock_type == UNLOCK_LOCK) {
4812 status = do_unlock(smbd_messaging_context(),
4813 fsp,
4814 lock_pid,
4815 count,
4816 offset,
4817 POSIX_LOCK);
4818 } else {
4819 uint32 block_smbpid;
4821 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4822 fsp,
4823 lock_pid,
4824 count,
4825 offset,
4826 lock_type,
4827 POSIX_LOCK,
4828 blocking_lock,
4829 &status,
4830 &block_smbpid);
4832 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4834 * A blocking lock was requested. Package up
4835 * this smb into a queued request and push it
4836 * onto the blocking lock queue.
4838 if(push_blocking_lock_request(br_lck,
4839 inbuf, length,
4840 fsp,
4841 -1, /* infinite timeout. */
4843 lock_pid,
4844 lock_type,
4845 POSIX_LOCK,
4846 offset,
4847 count,
4848 block_smbpid)) {
4849 TALLOC_FREE(br_lck);
4850 return status;
4853 TALLOC_FREE(br_lck);
4856 return status;
4859 /****************************************************************************
4860 Deal with SMB_INFO_STANDARD.
4861 ****************************************************************************/
4863 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4864 const char *pdata,
4865 int total_data,
4866 files_struct *fsp,
4867 const char *fname,
4868 const SMB_STRUCT_STAT *psbuf)
4870 struct timespec ts[2];
4872 if (total_data < 12) {
4873 return NT_STATUS_INVALID_PARAMETER;
4876 /* access time */
4877 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4878 /* write time */
4879 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4881 DEBUG(10,("smb_set_info_standard: file %s\n",
4882 fname ? fname : fsp->fsp_name ));
4884 return smb_set_file_time(conn,
4885 fsp,
4886 fname,
4887 psbuf,
4888 ts);
4891 /****************************************************************************
4892 Deal with SMB_SET_FILE_BASIC_INFO.
4893 ****************************************************************************/
4895 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4896 const char *pdata,
4897 int total_data,
4898 files_struct *fsp,
4899 const char *fname,
4900 SMB_STRUCT_STAT *psbuf)
4902 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4903 struct timespec write_time;
4904 struct timespec changed_time;
4905 uint32 dosmode = 0;
4906 struct timespec ts[2];
4907 NTSTATUS status = NT_STATUS_OK;
4909 if (total_data < 36) {
4910 return NT_STATUS_INVALID_PARAMETER;
4913 /* Set the attributes */
4914 dosmode = IVAL(pdata,32);
4915 status = smb_set_file_dosmode(conn,
4916 fname,
4917 psbuf,
4918 dosmode);
4919 if (!NT_STATUS_IS_OK(status)) {
4920 return status;
4923 /* Ignore create time at offset pdata. */
4925 /* access time */
4926 ts[0] = interpret_long_date(pdata+8);
4928 write_time = interpret_long_date(pdata+16);
4929 changed_time = interpret_long_date(pdata+24);
4931 /* mtime */
4932 ts[1] = timespec_min(&write_time, &changed_time);
4934 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4935 ts[1] = write_time;
4938 /* Prefer a defined time to an undefined one. */
4939 if (null_timespec(ts[1])) {
4940 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4943 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4944 fname ? fname : fsp->fsp_name ));
4946 return smb_set_file_time(conn,
4947 fsp,
4948 fname,
4949 psbuf,
4950 ts);
4953 /****************************************************************************
4954 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4955 ****************************************************************************/
4957 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4958 const char *pdata,
4959 int total_data,
4960 files_struct *fsp,
4961 const char *fname,
4962 SMB_STRUCT_STAT *psbuf)
4964 SMB_BIG_UINT allocation_size = 0;
4965 NTSTATUS status = NT_STATUS_OK;
4966 files_struct *new_fsp = NULL;
4968 if (!VALID_STAT(*psbuf)) {
4969 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4972 if (total_data < 8) {
4973 return NT_STATUS_INVALID_PARAMETER;
4976 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4977 #ifdef LARGE_SMB_OFF_T
4978 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4979 #else /* LARGE_SMB_OFF_T */
4980 if (IVAL(pdata,4) != 0) {
4981 /* more than 32 bits? */
4982 return NT_STATUS_INVALID_PARAMETER;
4984 #endif /* LARGE_SMB_OFF_T */
4986 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4987 fname, (double)allocation_size ));
4989 if (allocation_size) {
4990 allocation_size = smb_roundup(conn, allocation_size);
4993 if(allocation_size == get_file_size(*psbuf)) {
4994 return NT_STATUS_OK;
4997 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4998 fname, (double)allocation_size ));
5000 if (fsp && fsp->fh->fd != -1) {
5001 /* Open file handle. */
5002 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5003 return map_nt_error_from_unix(errno);
5005 return NT_STATUS_OK;
5008 /* Pathname or stat or directory file. */
5010 status = open_file_ntcreate(conn, fname, psbuf,
5011 FILE_WRITE_DATA,
5012 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5013 FILE_OPEN,
5015 FILE_ATTRIBUTE_NORMAL,
5016 FORCE_OPLOCK_BREAK_TO_NONE,
5017 NULL, &new_fsp);
5019 if (!NT_STATUS_IS_OK(status)) {
5020 /* NB. We check for open_was_deferred in the caller. */
5021 return status;
5023 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5024 status = map_nt_error_from_unix(errno);
5025 close_file(new_fsp,NORMAL_CLOSE);
5026 return status;
5029 close_file(new_fsp,NORMAL_CLOSE);
5030 return NT_STATUS_OK;
5033 /****************************************************************************
5034 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5035 ****************************************************************************/
5037 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5038 const char *pdata,
5039 int total_data,
5040 files_struct *fsp,
5041 const char *fname,
5042 SMB_STRUCT_STAT *psbuf)
5044 SMB_OFF_T size;
5046 if (total_data < 8) {
5047 return NT_STATUS_INVALID_PARAMETER;
5050 size = IVAL(pdata,0);
5051 #ifdef LARGE_SMB_OFF_T
5052 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5053 #else /* LARGE_SMB_OFF_T */
5054 if (IVAL(pdata,4) != 0) {
5055 /* more than 32 bits? */
5056 return NT_STATUS_INVALID_PARAMETER;
5058 #endif /* LARGE_SMB_OFF_T */
5059 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5060 "file %s to %.0f\n", fname, (double)size ));
5062 return smb_set_file_size(conn,
5063 fsp,
5064 fname,
5065 psbuf,
5066 size);
5069 /****************************************************************************
5070 Allow a UNIX info mknod.
5071 ****************************************************************************/
5073 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5074 const char *pdata,
5075 int total_data,
5076 const char *fname,
5077 SMB_STRUCT_STAT *psbuf)
5079 uint32 file_type = IVAL(pdata,56);
5080 #if defined(HAVE_MAKEDEV)
5081 uint32 dev_major = IVAL(pdata,60);
5082 uint32 dev_minor = IVAL(pdata,68);
5083 #endif
5084 SMB_DEV_T dev = (SMB_DEV_T)0;
5085 uint32 raw_unixmode = IVAL(pdata,84);
5086 NTSTATUS status;
5087 mode_t unixmode;
5089 if (total_data < 100) {
5090 return NT_STATUS_INVALID_PARAMETER;
5093 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5094 if (!NT_STATUS_IS_OK(status)) {
5095 return status;
5098 #if defined(HAVE_MAKEDEV)
5099 dev = makedev(dev_major, dev_minor);
5100 #endif
5102 switch (file_type) {
5103 #if defined(S_IFIFO)
5104 case UNIX_TYPE_FIFO:
5105 unixmode |= S_IFIFO;
5106 break;
5107 #endif
5108 #if defined(S_IFSOCK)
5109 case UNIX_TYPE_SOCKET:
5110 unixmode |= S_IFSOCK;
5111 break;
5112 #endif
5113 #if defined(S_IFCHR)
5114 case UNIX_TYPE_CHARDEV:
5115 unixmode |= S_IFCHR;
5116 break;
5117 #endif
5118 #if defined(S_IFBLK)
5119 case UNIX_TYPE_BLKDEV:
5120 unixmode |= S_IFBLK;
5121 break;
5122 #endif
5123 default:
5124 return NT_STATUS_INVALID_PARAMETER;
5127 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5128 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5130 /* Ok - do the mknod. */
5131 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5132 return map_nt_error_from_unix(errno);
5135 /* If any of the other "set" calls fail we
5136 * don't want to end up with a half-constructed mknod.
5139 if (lp_inherit_perms(SNUM(conn))) {
5140 inherit_access_acl(
5141 conn, parent_dirname(fname),
5142 fname, unixmode);
5145 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5146 status = map_nt_error_from_unix(errno);
5147 SMB_VFS_UNLINK(conn,fname);
5148 return status;
5150 return NT_STATUS_OK;
5153 /****************************************************************************
5154 Deal with SMB_SET_FILE_UNIX_BASIC.
5155 ****************************************************************************/
5157 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5158 const char *pdata,
5159 int total_data,
5160 files_struct *fsp,
5161 const char *fname,
5162 SMB_STRUCT_STAT *psbuf)
5164 struct timespec ts[2];
5165 uint32 raw_unixmode;
5166 mode_t unixmode;
5167 SMB_OFF_T size = 0;
5168 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5169 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5170 NTSTATUS status = NT_STATUS_OK;
5171 BOOL delete_on_fail = False;
5172 enum perm_type ptype;
5174 if (total_data < 100) {
5175 return NT_STATUS_INVALID_PARAMETER;
5178 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5179 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5180 size=IVAL(pdata,0); /* first 8 Bytes are size */
5181 #ifdef LARGE_SMB_OFF_T
5182 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5183 #else /* LARGE_SMB_OFF_T */
5184 if (IVAL(pdata,4) != 0) {
5185 /* more than 32 bits? */
5186 return NT_STATUS_INVALID_PARAMETER;
5188 #endif /* LARGE_SMB_OFF_T */
5191 ts[0] = interpret_long_date(pdata+24); /* access_time */
5192 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5193 set_owner = (uid_t)IVAL(pdata,40);
5194 set_grp = (gid_t)IVAL(pdata,48);
5195 raw_unixmode = IVAL(pdata,84);
5197 if (VALID_STAT(*psbuf)) {
5198 if (S_ISDIR(psbuf->st_mode)) {
5199 ptype = PERM_EXISTING_DIR;
5200 } else {
5201 ptype = PERM_EXISTING_FILE;
5203 } else {
5204 ptype = PERM_NEW_FILE;
5207 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5208 if (!NT_STATUS_IS_OK(status)) {
5209 return status;
5212 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5213 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5214 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5216 if (!VALID_STAT(*psbuf)) {
5218 * The only valid use of this is to create character and block
5219 * devices, and named pipes. This is deprecated (IMHO) and
5220 * a new info level should be used for mknod. JRA.
5223 status = smb_unix_mknod(conn,
5224 pdata,
5225 total_data,
5226 fname,
5227 psbuf);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 return status;
5232 /* Ensure we don't try and change anything else. */
5233 raw_unixmode = SMB_MODE_NO_CHANGE;
5234 size = get_file_size(*psbuf);
5235 ts[0] = get_atimespec(psbuf);
5236 ts[1] = get_mtimespec(psbuf);
5238 * We continue here as we might want to change the
5239 * owner uid/gid.
5241 delete_on_fail = True;
5244 #if 1
5245 /* Horrible backwards compatibility hack as an old server bug
5246 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5247 * */
5249 if (!size) {
5250 size = get_file_size(*psbuf);
5252 #endif
5255 * Deal with the UNIX specific mode set.
5258 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5259 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5260 (unsigned int)unixmode, fname ));
5261 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5262 return map_nt_error_from_unix(errno);
5267 * Deal with the UNIX specific uid set.
5270 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5271 int ret;
5273 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5274 (unsigned int)set_owner, fname ));
5276 if (S_ISLNK(psbuf->st_mode)) {
5277 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5278 } else {
5279 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5282 if (ret != 0) {
5283 status = map_nt_error_from_unix(errno);
5284 if (delete_on_fail) {
5285 SMB_VFS_UNLINK(conn,fname);
5287 return status;
5292 * Deal with the UNIX specific gid set.
5295 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5296 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5297 (unsigned int)set_owner, fname ));
5298 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5299 status = map_nt_error_from_unix(errno);
5300 if (delete_on_fail) {
5301 SMB_VFS_UNLINK(conn,fname);
5303 return status;
5307 /* Deal with any size changes. */
5309 status = smb_set_file_size(conn,
5310 fsp,
5311 fname,
5312 psbuf,
5313 size);
5314 if (!NT_STATUS_IS_OK(status)) {
5315 return status;
5318 /* Deal with any time changes. */
5320 return smb_set_file_time(conn,
5321 fsp,
5322 fname,
5323 psbuf,
5324 ts);
5327 /****************************************************************************
5328 Deal with SMB_SET_FILE_UNIX_INFO2.
5329 ****************************************************************************/
5331 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5332 const char *pdata,
5333 int total_data,
5334 files_struct *fsp,
5335 const char *fname,
5336 SMB_STRUCT_STAT *psbuf)
5338 NTSTATUS status;
5339 uint32 smb_fflags;
5340 uint32 smb_fmask;
5342 if (total_data < 116) {
5343 return NT_STATUS_INVALID_PARAMETER;
5346 /* Start by setting all the fields that are common between UNIX_BASIC
5347 * and UNIX_INFO2.
5349 status = smb_set_file_unix_basic(conn, pdata, total_data,
5350 fsp, fname, psbuf);
5351 if (!NT_STATUS_IS_OK(status)) {
5352 return status;
5355 smb_fflags = IVAL(pdata, 108);
5356 smb_fmask = IVAL(pdata, 112);
5358 /* NB: We should only attempt to alter the file flags if the client
5359 * sends a non-zero mask.
5361 if (smb_fmask != 0) {
5362 int stat_fflags = 0;
5364 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5365 &stat_fflags)) {
5366 /* Client asked to alter a flag we don't understand. */
5367 return NT_STATUS_INVALID_PARAMETER;
5370 if (fsp && fsp->fh->fd != -1) {
5371 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5372 return NT_STATUS_NOT_SUPPORTED;
5373 } else {
5374 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5375 return map_nt_error_from_unix(errno);
5380 /* XXX: need to add support for changing the create_time here. You
5381 * can do this for paths on Darwin with setattrlist(2). The right way
5382 * to hook this up is probably by extending the VFS utimes interface.
5385 return NT_STATUS_OK;
5388 /****************************************************************************
5389 Create a directory with POSIX semantics.
5390 ****************************************************************************/
5392 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5393 char **ppdata,
5394 int total_data,
5395 const char *fname,
5396 SMB_STRUCT_STAT *psbuf,
5397 int *pdata_return_size)
5399 NTSTATUS status = NT_STATUS_OK;
5400 uint32 raw_unixmode = 0;
5401 uint32 mod_unixmode = 0;
5402 mode_t unixmode = (mode_t)0;
5403 files_struct *fsp = NULL;
5404 uint16 info_level_return = 0;
5405 int info;
5406 char *pdata = *ppdata;
5408 if (total_data < 18) {
5409 return NT_STATUS_INVALID_PARAMETER;
5412 raw_unixmode = IVAL(pdata,8);
5413 /* Next 4 bytes are not yet defined. */
5415 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5416 if (!NT_STATUS_IS_OK(status)) {
5417 return status;
5420 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5422 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5423 fname, (unsigned int)unixmode ));
5425 status = open_directory(conn,
5426 fname,
5427 psbuf,
5428 FILE_READ_ATTRIBUTES, /* Just a stat open */
5429 FILE_SHARE_NONE, /* Ignored for stat opens */
5430 FILE_CREATE,
5432 mod_unixmode,
5433 &info,
5434 &fsp);
5436 if (NT_STATUS_IS_OK(status)) {
5437 close_file(fsp, NORMAL_CLOSE);
5440 info_level_return = SVAL(pdata,16);
5442 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5443 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5444 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5445 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5446 } else {
5447 *pdata_return_size = 12;
5450 /* Realloc the data size */
5451 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5452 if (*ppdata == NULL) {
5453 *pdata_return_size = 0;
5454 return NT_STATUS_NO_MEMORY;
5456 pdata = *ppdata;
5458 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5459 SSVAL(pdata,2,0); /* No fnum. */
5460 SIVAL(pdata,4,info); /* Was directory created. */
5462 switch (info_level_return) {
5463 case SMB_QUERY_FILE_UNIX_BASIC:
5464 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5465 SSVAL(pdata,10,0); /* Padding. */
5466 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5467 break;
5468 case SMB_QUERY_FILE_UNIX_INFO2:
5469 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5470 SSVAL(pdata,10,0); /* Padding. */
5471 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5472 break;
5473 default:
5474 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5475 SSVAL(pdata,10,0); /* Padding. */
5476 break;
5479 return status;
5482 /****************************************************************************
5483 Open/Create a file with POSIX semantics.
5484 ****************************************************************************/
5486 static NTSTATUS smb_posix_open(connection_struct *conn,
5487 char **ppdata,
5488 int total_data,
5489 const char *fname,
5490 SMB_STRUCT_STAT *psbuf,
5491 int *pdata_return_size)
5493 BOOL extended_oplock_granted = False;
5494 char *pdata = *ppdata;
5495 uint32 flags = 0;
5496 uint32 wire_open_mode = 0;
5497 uint32 raw_unixmode = 0;
5498 uint32 mod_unixmode = 0;
5499 uint32 create_disp = 0;
5500 uint32 access_mask = 0;
5501 uint32 create_options = 0;
5502 NTSTATUS status = NT_STATUS_OK;
5503 mode_t unixmode = (mode_t)0;
5504 files_struct *fsp = NULL;
5505 int oplock_request = 0;
5506 int info = 0;
5507 uint16 info_level_return = 0;
5509 if (total_data < 18) {
5510 return NT_STATUS_INVALID_PARAMETER;
5513 flags = IVAL(pdata,0);
5514 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5515 if (oplock_request) {
5516 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5519 wire_open_mode = IVAL(pdata,4);
5521 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5522 return smb_posix_mkdir(conn,
5523 ppdata,
5524 total_data,
5525 fname,
5526 psbuf,
5527 pdata_return_size);
5530 switch (wire_open_mode & SMB_ACCMODE) {
5531 case SMB_O_RDONLY:
5532 access_mask = FILE_READ_DATA;
5533 break;
5534 case SMB_O_WRONLY:
5535 access_mask = FILE_WRITE_DATA;
5536 break;
5537 case SMB_O_RDWR:
5538 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5539 break;
5540 default:
5541 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5542 (unsigned int)wire_open_mode ));
5543 return NT_STATUS_INVALID_PARAMETER;
5546 wire_open_mode &= ~SMB_ACCMODE;
5548 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5549 create_disp = FILE_CREATE;
5550 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5551 create_disp = FILE_OVERWRITE_IF;
5552 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5553 create_disp = FILE_OPEN_IF;
5554 } else {
5555 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5556 (unsigned int)wire_open_mode ));
5557 return NT_STATUS_INVALID_PARAMETER;
5560 raw_unixmode = IVAL(pdata,8);
5561 /* Next 4 bytes are not yet defined. */
5563 status = unix_perms_from_wire(conn,
5564 psbuf,
5565 raw_unixmode,
5566 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5567 &unixmode);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 return status;
5573 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5575 if (wire_open_mode & SMB_O_SYNC) {
5576 create_options |= FILE_WRITE_THROUGH;
5578 if (wire_open_mode & SMB_O_APPEND) {
5579 access_mask |= FILE_APPEND_DATA;
5581 if (wire_open_mode & SMB_O_DIRECT) {
5582 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5585 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5586 fname,
5587 (unsigned int)wire_open_mode,
5588 (unsigned int)unixmode ));
5590 status = open_file_ntcreate(conn,
5591 fname,
5592 psbuf,
5593 access_mask,
5594 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5595 create_disp,
5596 0, /* no create options yet. */
5597 mod_unixmode,
5598 oplock_request,
5599 &info,
5600 &fsp);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 return status;
5606 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5607 extended_oplock_granted = True;
5610 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5611 extended_oplock_granted = True;
5614 info_level_return = SVAL(pdata,16);
5616 /* Allocate the correct return size. */
5618 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5619 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5620 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5621 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5622 } else {
5623 *pdata_return_size = 12;
5626 /* Realloc the data size */
5627 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5628 if (*ppdata == NULL) {
5629 close_file(fsp,ERROR_CLOSE);
5630 *pdata_return_size = 0;
5631 return NT_STATUS_NO_MEMORY;
5633 pdata = *ppdata;
5635 if (extended_oplock_granted) {
5636 if (flags & REQUEST_BATCH_OPLOCK) {
5637 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5638 } else {
5639 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5641 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5642 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5643 } else {
5644 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5647 SSVAL(pdata,2,fsp->fnum);
5648 SIVAL(pdata,4,info); /* Was file created etc. */
5650 switch (info_level_return) {
5651 case SMB_QUERY_FILE_UNIX_BASIC:
5652 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5653 SSVAL(pdata,10,0); /* padding. */
5654 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5655 break;
5656 case SMB_QUERY_FILE_UNIX_INFO2:
5657 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5658 SSVAL(pdata,10,0); /* padding. */
5659 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5660 break;
5661 default:
5662 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5663 SSVAL(pdata,10,0); /* padding. */
5664 break;
5666 return NT_STATUS_OK;
5669 /****************************************************************************
5670 Delete a file with POSIX semantics.
5671 ****************************************************************************/
5673 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5674 const char *pdata,
5675 int total_data,
5676 const char *fname,
5677 SMB_STRUCT_STAT *psbuf)
5679 NTSTATUS status = NT_STATUS_OK;
5680 files_struct *fsp = NULL;
5681 uint16 flags = 0;
5682 int info = 0;
5684 if (total_data < 2) {
5685 return NT_STATUS_INVALID_PARAMETER;
5688 flags = SVAL(pdata,0);
5690 if (!VALID_STAT(*psbuf)) {
5691 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5694 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5695 !VALID_STAT_OF_DIR(*psbuf)) {
5696 return NT_STATUS_NOT_A_DIRECTORY;
5699 DEBUG(10,("smb_posix_unlink: %s %s\n",
5700 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5701 fname));
5703 if (VALID_STAT_OF_DIR(*psbuf)) {
5704 status = open_directory(conn,
5705 fname,
5706 psbuf,
5707 DELETE_ACCESS,
5708 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5709 FILE_OPEN,
5710 FILE_DELETE_ON_CLOSE,
5711 FILE_FLAG_POSIX_SEMANTICS|0777,
5712 &info,
5713 &fsp);
5714 } else {
5715 char del = 1;
5717 status = open_file_ntcreate(conn,
5718 fname,
5719 psbuf,
5720 DELETE_ACCESS,
5721 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5722 FILE_OPEN,
5724 FILE_FLAG_POSIX_SEMANTICS|0777,
5725 0, /* No oplock, but break existing ones. */
5726 &info,
5727 &fsp);
5729 * For file opens we must set the delete on close
5730 * after the open.
5733 if (!NT_STATUS_IS_OK(status)) {
5734 return status;
5737 status = smb_set_file_disposition_info(conn,
5738 &del,
5740 fsp,
5741 fname,
5742 psbuf);
5745 if (!NT_STATUS_IS_OK(status)) {
5746 return status;
5748 return close_file(fsp, NORMAL_CLOSE);
5751 /****************************************************************************
5752 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5753 ****************************************************************************/
5755 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5756 unsigned int tran_call,
5757 char **pparams, int total_params, char **ppdata, int total_data,
5758 unsigned int max_data_bytes)
5760 char *params = *pparams;
5761 char *pdata = *ppdata;
5762 uint16 info_level;
5763 SMB_STRUCT_STAT sbuf;
5764 pstring fname;
5765 files_struct *fsp = NULL;
5766 NTSTATUS status = NT_STATUS_OK;
5767 int data_return_size = 0;
5769 if (!params) {
5770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5773 ZERO_STRUCT(sbuf);
5775 if (tran_call == TRANSACT2_SETFILEINFO) {
5776 if (total_params < 4) {
5777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5780 fsp = file_fsp(params,0);
5781 info_level = SVAL(params,2);
5783 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5785 * This is actually a SETFILEINFO on a directory
5786 * handle (returned from an NT SMB). NT5.0 seems
5787 * to do this call. JRA.
5789 pstrcpy(fname, fsp->fsp_name);
5790 if (INFO_LEVEL_IS_UNIX(info_level)) {
5791 /* Always do lstat for UNIX calls. */
5792 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5793 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5794 return UNIXERROR(ERRDOS,ERRbadpath);
5796 } else {
5797 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5798 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5799 return UNIXERROR(ERRDOS,ERRbadpath);
5802 } else if (fsp && fsp->print_file) {
5804 * Doing a DELETE_ON_CLOSE should cancel a print job.
5806 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5807 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5809 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5811 SSVAL(params,0,0);
5812 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5813 return(-1);
5814 } else
5815 return (UNIXERROR(ERRDOS,ERRbadpath));
5816 } else {
5818 * Original code - this is an open file.
5820 CHECK_FSP(fsp,conn);
5822 pstrcpy(fname, fsp->fsp_name);
5824 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5825 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5826 return(UNIXERROR(ERRDOS,ERRbadfid));
5829 } else {
5830 /* set path info */
5831 if (total_params < 7) {
5832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5835 info_level = SVAL(params,0);
5836 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5837 if (!NT_STATUS_IS_OK(status)) {
5838 return ERROR_NT(status);
5841 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5844 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5846 return ERROR_NT(status);
5849 status = unix_convert(conn, fname, False, NULL, &sbuf);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 return ERROR_NT(status);
5854 status = check_name(conn, fname);
5855 if (!NT_STATUS_IS_OK(status)) {
5856 return ERROR_NT(status);
5859 if (INFO_LEVEL_IS_UNIX(info_level)) {
5861 * For CIFS UNIX extensions the target name may not exist.
5864 /* Always do lstat for UNIX calls. */
5865 SMB_VFS_LSTAT(conn,fname,&sbuf);
5867 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5868 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5869 return UNIXERROR(ERRDOS,ERRbadpath);
5873 if (!CAN_WRITE(conn)) {
5874 return ERROR_DOS(ERRSRV,ERRaccess);
5877 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5878 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5881 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5882 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5884 /* Realloc the parameter size */
5885 *pparams = (char *)SMB_REALLOC(*pparams,2);
5886 if (*pparams == NULL) {
5887 return ERROR_NT(NT_STATUS_NO_MEMORY);
5889 params = *pparams;
5891 SSVAL(params,0,0);
5893 if (fsp && !null_timespec(fsp->pending_modtime)) {
5894 /* the pending modtime overrides the current modtime */
5895 set_mtimespec(&sbuf, fsp->pending_modtime);
5898 switch (info_level) {
5900 case SMB_INFO_STANDARD:
5902 status = smb_set_info_standard(conn,
5903 pdata,
5904 total_data,
5905 fsp,
5906 fname,
5907 &sbuf);
5908 break;
5911 case SMB_INFO_SET_EA:
5913 status = smb_info_set_ea(conn,
5914 pdata,
5915 total_data,
5916 fsp,
5917 fname);
5918 break;
5921 case SMB_SET_FILE_BASIC_INFO:
5922 case SMB_FILE_BASIC_INFORMATION:
5924 status = smb_set_file_basic_info(conn,
5925 pdata,
5926 total_data,
5927 fsp,
5928 fname,
5929 &sbuf);
5930 break;
5933 case SMB_FILE_ALLOCATION_INFORMATION:
5934 case SMB_SET_FILE_ALLOCATION_INFO:
5936 status = smb_set_file_allocation_info(conn,
5937 pdata,
5938 total_data,
5939 fsp,
5940 fname,
5941 &sbuf);
5942 break;
5945 case SMB_FILE_END_OF_FILE_INFORMATION:
5946 case SMB_SET_FILE_END_OF_FILE_INFO:
5948 status = smb_set_file_end_of_file_info(conn,
5949 pdata,
5950 total_data,
5951 fsp,
5952 fname,
5953 &sbuf);
5954 break;
5957 case SMB_FILE_DISPOSITION_INFORMATION:
5958 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5960 #if 0
5961 /* JRA - We used to just ignore this on a path ?
5962 * Shouldn't this be invalid level on a pathname
5963 * based call ?
5965 if (tran_call != TRANSACT2_SETFILEINFO) {
5966 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5968 #endif
5969 status = smb_set_file_disposition_info(conn,
5970 pdata,
5971 total_data,
5972 fsp,
5973 fname,
5974 &sbuf);
5975 break;
5978 case SMB_FILE_POSITION_INFORMATION:
5980 status = smb_file_position_information(conn,
5981 pdata,
5982 total_data,
5983 fsp);
5984 break;
5987 /* From tridge Samba4 :
5988 * MODE_INFORMATION in setfileinfo (I have no
5989 * idea what "mode information" on a file is - it takes a value of 0,
5990 * 2, 4 or 6. What could it be?).
5993 case SMB_FILE_MODE_INFORMATION:
5995 status = smb_file_mode_information(conn,
5996 pdata,
5997 total_data);
5998 break;
6002 * CIFS UNIX extensions.
6005 case SMB_SET_FILE_UNIX_BASIC:
6007 status = smb_set_file_unix_basic(conn,
6008 pdata,
6009 total_data,
6010 fsp,
6011 fname,
6012 &sbuf);
6013 break;
6016 case SMB_SET_FILE_UNIX_INFO2:
6018 status = smb_set_file_unix_info2(conn,
6019 pdata,
6020 total_data,
6021 fsp,
6022 fname,
6023 &sbuf);
6024 break;
6027 case SMB_SET_FILE_UNIX_LINK:
6029 if (tran_call != TRANSACT2_SETPATHINFO) {
6030 /* We must have a pathname for this. */
6031 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6033 status = smb_set_file_unix_link(conn,
6034 inbuf,
6035 pdata,
6036 total_data,
6037 fname);
6038 break;
6041 case SMB_SET_FILE_UNIX_HLINK:
6043 if (tran_call != TRANSACT2_SETPATHINFO) {
6044 /* We must have a pathname for this. */
6045 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6047 status = smb_set_file_unix_hlink(conn,
6048 inbuf,
6049 outbuf,
6050 pdata,
6051 total_data,
6052 fname);
6053 break;
6056 case SMB_FILE_RENAME_INFORMATION:
6058 status = smb_file_rename_information(conn,
6059 inbuf,
6060 outbuf,
6061 pdata,
6062 total_data,
6063 fsp,
6064 fname);
6065 break;
6068 #if defined(HAVE_POSIX_ACLS)
6069 case SMB_SET_POSIX_ACL:
6071 status = smb_set_posix_acl(conn,
6072 pdata,
6073 total_data,
6074 fsp,
6075 fname,
6076 &sbuf);
6077 break;
6079 #endif
6081 case SMB_SET_POSIX_LOCK:
6083 if (tran_call != TRANSACT2_SETFILEINFO) {
6084 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6086 status = smb_set_posix_lock(conn,
6087 inbuf,
6088 length,
6089 pdata,
6090 total_data,
6091 fsp);
6092 break;
6095 case SMB_POSIX_PATH_OPEN:
6097 if (tran_call != TRANSACT2_SETPATHINFO) {
6098 /* We must have a pathname for this. */
6099 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6102 status = smb_posix_open(conn,
6103 ppdata,
6104 total_data,
6105 fname,
6106 &sbuf,
6107 &data_return_size);
6108 break;
6111 case SMB_POSIX_PATH_UNLINK:
6113 if (tran_call != TRANSACT2_SETPATHINFO) {
6114 /* We must have a pathname for this. */
6115 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6118 status = smb_posix_unlink(conn,
6119 pdata,
6120 total_data,
6121 fname,
6122 &sbuf);
6123 break;
6126 default:
6127 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6131 if (!NT_STATUS_IS_OK(status)) {
6132 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6133 /* We have re-scheduled this call. */
6134 return -1;
6136 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6137 /* We have re-scheduled this call. */
6138 return -1;
6140 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6141 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6143 return ERROR_NT(status);
6146 SSVAL(params,0,0);
6147 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6149 return -1;
6152 /****************************************************************************
6153 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6154 ****************************************************************************/
6156 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6157 char **pparams, int total_params, char **ppdata, int total_data,
6158 unsigned int max_data_bytes)
6160 char *params = *pparams;
6161 char *pdata = *ppdata;
6162 pstring directory;
6163 SMB_STRUCT_STAT sbuf;
6164 NTSTATUS status = NT_STATUS_OK;
6165 struct ea_list *ea_list = NULL;
6167 if (!CAN_WRITE(conn))
6168 return ERROR_DOS(ERRSRV,ERRaccess);
6170 if (total_params < 5) {
6171 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6174 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6175 if (!NT_STATUS_IS_OK(status)) {
6176 return ERROR_NT(status);
6179 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6181 status = unix_convert(conn, directory, False, NULL, &sbuf);
6182 if (!NT_STATUS_IS_OK(status)) {
6183 return ERROR_NT(status);
6186 status = check_name(conn, directory);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6189 return ERROR_NT(status);
6192 /* Any data in this call is an EA list. */
6193 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6194 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6198 * OS/2 workplace shell seems to send SET_EA requests of "null"
6199 * length (4 bytes containing IVAL 4).
6200 * They seem to have no effect. Bug #3212. JRA.
6203 if (total_data != 4) {
6204 if (total_data < 10) {
6205 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6208 if (IVAL(pdata,0) > total_data) {
6209 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6210 IVAL(pdata,0), (unsigned int)total_data));
6211 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6214 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6215 total_data - 4);
6216 if (!ea_list) {
6217 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6219 } else if (IVAL(pdata,0) != 4) {
6220 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6223 status = create_directory(conn, directory);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 return ERROR_NT(status);
6229 /* Try and set any given EA. */
6230 if (ea_list) {
6231 status = set_ea(conn, NULL, directory, ea_list);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 return ERROR_NT(status);
6237 /* Realloc the parameter and data sizes */
6238 *pparams = (char *)SMB_REALLOC(*pparams,2);
6239 if(*pparams == NULL) {
6240 return ERROR_NT(NT_STATUS_NO_MEMORY);
6242 params = *pparams;
6244 SSVAL(params,0,0);
6246 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6248 return(-1);
6251 /****************************************************************************
6252 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6253 We don't actually do this - we just send a null response.
6254 ****************************************************************************/
6256 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6257 char **pparams, int total_params, char **ppdata, int total_data,
6258 unsigned int max_data_bytes)
6260 static uint16 fnf_handle = 257;
6261 char *params = *pparams;
6262 uint16 info_level;
6264 if (total_params < 6) {
6265 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6268 info_level = SVAL(params,4);
6269 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6271 switch (info_level) {
6272 case 1:
6273 case 2:
6274 break;
6275 default:
6276 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6279 /* Realloc the parameter and data sizes */
6280 *pparams = (char *)SMB_REALLOC(*pparams,6);
6281 if (*pparams == NULL) {
6282 return ERROR_NT(NT_STATUS_NO_MEMORY);
6284 params = *pparams;
6286 SSVAL(params,0,fnf_handle);
6287 SSVAL(params,2,0); /* No changes */
6288 SSVAL(params,4,0); /* No EA errors */
6290 fnf_handle++;
6292 if(fnf_handle == 0)
6293 fnf_handle = 257;
6295 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6297 return(-1);
6300 /****************************************************************************
6301 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6302 changes). Currently this does nothing.
6303 ****************************************************************************/
6305 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6306 char **pparams, int total_params, char **ppdata, int total_data,
6307 unsigned int max_data_bytes)
6309 char *params = *pparams;
6311 DEBUG(3,("call_trans2findnotifynext\n"));
6313 /* Realloc the parameter and data sizes */
6314 *pparams = (char *)SMB_REALLOC(*pparams,4);
6315 if (*pparams == NULL) {
6316 return ERROR_NT(NT_STATUS_NO_MEMORY);
6318 params = *pparams;
6320 SSVAL(params,0,0); /* No changes */
6321 SSVAL(params,2,0); /* No EA errors */
6323 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6325 return(-1);
6328 /****************************************************************************
6329 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6330 ****************************************************************************/
6332 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6333 char **pparams, int total_params, char **ppdata, int total_data,
6334 unsigned int max_data_bytes)
6336 char *params = *pparams;
6337 pstring pathname;
6338 int reply_size = 0;
6339 int max_referral_level;
6340 NTSTATUS status = NT_STATUS_OK;
6342 DEBUG(10,("call_trans2getdfsreferral\n"));
6344 if (total_params < 3) {
6345 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6348 max_referral_level = SVAL(params,0);
6350 if(!lp_host_msdfs())
6351 return ERROR_DOS(ERRDOS,ERRbadfunc);
6353 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6354 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6355 return ERROR_NT(status);
6357 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6358 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6360 return(-1);
6363 #define LMCAT_SPL 0x53
6364 #define LMFUNC_GETJOBID 0x60
6366 /****************************************************************************
6367 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6368 ****************************************************************************/
6370 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6371 char **pparams, int total_params, char **ppdata, int total_data,
6372 unsigned int max_data_bytes)
6374 char *pdata = *ppdata;
6375 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6377 /* check for an invalid fid before proceeding */
6379 if (!fsp)
6380 return(ERROR_DOS(ERRDOS,ERRbadfid));
6382 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6383 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6384 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6385 if (*ppdata == NULL) {
6386 return ERROR_NT(NT_STATUS_NO_MEMORY);
6388 pdata = *ppdata;
6390 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6391 CAN ACCEPT THIS IN UNICODE. JRA. */
6393 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6394 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6395 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6396 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6397 return(-1);
6398 } else {
6399 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6400 return ERROR_DOS(ERRSRV,ERRerror);
6404 /****************************************************************************
6405 Reply to a SMBfindclose (stop trans2 directory search).
6406 ****************************************************************************/
6408 int reply_findclose(connection_struct *conn,
6409 char *inbuf,char *outbuf,int length,int bufsize)
6411 int outsize = 0;
6412 int dptr_num=SVALS(inbuf,smb_vwv0);
6413 START_PROFILE(SMBfindclose);
6415 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6417 dptr_close(&dptr_num);
6419 outsize = set_message(inbuf, outbuf,0,0,False);
6421 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6423 END_PROFILE(SMBfindclose);
6424 return(outsize);
6427 /****************************************************************************
6428 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6429 ****************************************************************************/
6431 int reply_findnclose(connection_struct *conn,
6432 char *inbuf,char *outbuf,int length,int bufsize)
6434 int outsize = 0;
6435 int dptr_num= -1;
6436 START_PROFILE(SMBfindnclose);
6438 dptr_num = SVAL(inbuf,smb_vwv0);
6440 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6442 /* We never give out valid handles for a
6443 findnotifyfirst - so any dptr_num is ok here.
6444 Just ignore it. */
6446 outsize = set_message(inbuf, outbuf,0,0,False);
6448 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6450 END_PROFILE(SMBfindnclose);
6451 return(outsize);
6454 int handle_trans2(connection_struct *conn,
6455 struct trans_state *state,
6456 char *inbuf, char *outbuf, int size, int bufsize)
6458 int outsize;
6460 if (Protocol >= PROTOCOL_NT1) {
6461 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6464 /* Now we must call the relevant TRANS2 function */
6465 switch(state->call) {
6466 case TRANSACT2_OPEN:
6468 START_PROFILE(Trans2_open);
6469 outsize = call_trans2open(
6470 conn, inbuf, outbuf, bufsize,
6471 &state->param, state->total_param,
6472 &state->data, state->total_data,
6473 state->max_data_return);
6474 END_PROFILE(Trans2_open);
6475 break;
6478 case TRANSACT2_FINDFIRST:
6480 START_PROFILE(Trans2_findfirst);
6481 outsize = call_trans2findfirst(
6482 conn, inbuf, outbuf, bufsize,
6483 &state->param, state->total_param,
6484 &state->data, state->total_data,
6485 state->max_data_return);
6486 END_PROFILE(Trans2_findfirst);
6487 break;
6490 case TRANSACT2_FINDNEXT:
6492 START_PROFILE(Trans2_findnext);
6493 outsize = call_trans2findnext(
6494 conn, inbuf, outbuf, size, bufsize,
6495 &state->param, state->total_param,
6496 &state->data, state->total_data,
6497 state->max_data_return);
6498 END_PROFILE(Trans2_findnext);
6499 break;
6502 case TRANSACT2_QFSINFO:
6504 START_PROFILE(Trans2_qfsinfo);
6505 outsize = call_trans2qfsinfo(
6506 conn, inbuf, outbuf, size, bufsize,
6507 &state->param, state->total_param,
6508 &state->data, state->total_data,
6509 state->max_data_return);
6510 END_PROFILE(Trans2_qfsinfo);
6511 break;
6514 case TRANSACT2_SETFSINFO:
6516 START_PROFILE(Trans2_setfsinfo);
6517 outsize = call_trans2setfsinfo(
6518 conn, inbuf, outbuf, size, bufsize,
6519 &state->param, state->total_param,
6520 &state->data, state->total_data,
6521 state->max_data_return);
6522 END_PROFILE(Trans2_setfsinfo);
6523 break;
6526 case TRANSACT2_QPATHINFO:
6527 case TRANSACT2_QFILEINFO:
6529 START_PROFILE(Trans2_qpathinfo);
6530 outsize = call_trans2qfilepathinfo(
6531 conn, inbuf, outbuf, size, bufsize, state->call,
6532 &state->param, state->total_param,
6533 &state->data, state->total_data,
6534 state->max_data_return);
6535 END_PROFILE(Trans2_qpathinfo);
6536 break;
6539 case TRANSACT2_SETPATHINFO:
6540 case TRANSACT2_SETFILEINFO:
6542 START_PROFILE(Trans2_setpathinfo);
6543 outsize = call_trans2setfilepathinfo(
6544 conn, inbuf, outbuf, size, bufsize, state->call,
6545 &state->param, state->total_param,
6546 &state->data, state->total_data,
6547 state->max_data_return);
6548 END_PROFILE(Trans2_setpathinfo);
6549 break;
6552 case TRANSACT2_FINDNOTIFYFIRST:
6554 START_PROFILE(Trans2_findnotifyfirst);
6555 outsize = call_trans2findnotifyfirst(
6556 conn, inbuf, outbuf, size, bufsize,
6557 &state->param, state->total_param,
6558 &state->data, state->total_data,
6559 state->max_data_return);
6560 END_PROFILE(Trans2_findnotifyfirst);
6561 break;
6564 case TRANSACT2_FINDNOTIFYNEXT:
6566 START_PROFILE(Trans2_findnotifynext);
6567 outsize = call_trans2findnotifynext(
6568 conn, inbuf, outbuf, size, bufsize,
6569 &state->param, state->total_param,
6570 &state->data, state->total_data,
6571 state->max_data_return);
6572 END_PROFILE(Trans2_findnotifynext);
6573 break;
6576 case TRANSACT2_MKDIR:
6578 START_PROFILE(Trans2_mkdir);
6579 outsize = call_trans2mkdir(
6580 conn, inbuf, outbuf, size, bufsize,
6581 &state->param, state->total_param,
6582 &state->data, state->total_data,
6583 state->max_data_return);
6584 END_PROFILE(Trans2_mkdir);
6585 break;
6588 case TRANSACT2_GET_DFS_REFERRAL:
6590 START_PROFILE(Trans2_get_dfs_referral);
6591 outsize = call_trans2getdfsreferral(
6592 conn, inbuf, outbuf, size, bufsize,
6593 &state->param, state->total_param,
6594 &state->data, state->total_data,
6595 state->max_data_return);
6596 END_PROFILE(Trans2_get_dfs_referral);
6597 break;
6600 case TRANSACT2_IOCTL:
6602 START_PROFILE(Trans2_ioctl);
6603 outsize = call_trans2ioctl(
6604 conn, inbuf, outbuf, size, bufsize,
6605 &state->param, state->total_param,
6606 &state->data, state->total_data,
6607 state->max_data_return);
6608 END_PROFILE(Trans2_ioctl);
6609 break;
6612 default:
6613 /* Error in request */
6614 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6615 outsize = ERROR_DOS(ERRSRV,ERRerror);
6618 return outsize;
6621 /****************************************************************************
6622 Reply to a SMBtrans2.
6623 ****************************************************************************/
6625 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6626 int size, int bufsize)
6628 int outsize = 0;
6629 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6630 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6631 unsigned int psoff = SVAL(inbuf, smb_psoff);
6632 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6633 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6634 struct trans_state *state;
6635 NTSTATUS result;
6637 START_PROFILE(SMBtrans2);
6639 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6640 if (!NT_STATUS_IS_OK(result)) {
6641 DEBUG(2, ("Got invalid trans2 request: %s\n",
6642 nt_errstr(result)));
6643 END_PROFILE(SMBtrans2);
6644 return ERROR_NT(result);
6647 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6648 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6649 && (tran_call != TRANSACT2_QFILEINFO)) {
6650 END_PROFILE(SMBtrans2);
6651 return ERROR_DOS(ERRSRV,ERRaccess);
6654 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6655 DEBUG(0, ("talloc failed\n"));
6656 END_PROFILE(SMBtrans2);
6657 return ERROR_NT(NT_STATUS_NO_MEMORY);
6660 state->cmd = SMBtrans2;
6662 state->mid = SVAL(inbuf, smb_mid);
6663 state->vuid = SVAL(inbuf, smb_uid);
6664 state->setup_count = SVAL(inbuf, smb_suwcnt);
6665 state->setup = NULL;
6666 state->total_param = SVAL(inbuf, smb_tpscnt);
6667 state->param = NULL;
6668 state->total_data = SVAL(inbuf, smb_tdscnt);
6669 state->data = NULL;
6670 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6671 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6672 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6673 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6674 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6676 state->call = tran_call;
6678 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6679 is so as a sanity check */
6680 if (state->setup_count != 1) {
6682 * Need to have rc=0 for ioctl to get job id for OS/2.
6683 * Network printing will fail if function is not successful.
6684 * Similar function in reply.c will be used if protocol
6685 * is LANMAN1.0 instead of LM1.2X002.
6686 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6687 * outbuf doesn't have to be set(only job id is used).
6689 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6690 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6691 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6692 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6693 } else {
6694 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6695 DEBUG(2,("Transaction is %d\n",tran_call));
6696 TALLOC_FREE(state);
6697 END_PROFILE(SMBtrans2);
6698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6702 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6703 goto bad_param;
6705 if (state->total_data) {
6706 /* Can't use talloc here, the core routines do realloc on the
6707 * params and data. */
6708 state->data = (char *)SMB_MALLOC(state->total_data);
6709 if (state->data == NULL) {
6710 DEBUG(0,("reply_trans2: data malloc fail for %u "
6711 "bytes !\n", (unsigned int)state->total_data));
6712 TALLOC_FREE(state);
6713 END_PROFILE(SMBtrans2);
6714 return(ERROR_DOS(ERRDOS,ERRnomem));
6716 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6717 goto bad_param;
6718 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6719 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6720 goto bad_param;
6722 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6725 if (state->total_param) {
6726 /* Can't use talloc here, the core routines do realloc on the
6727 * params and data. */
6728 state->param = (char *)SMB_MALLOC(state->total_param);
6729 if (state->param == NULL) {
6730 DEBUG(0,("reply_trans: param malloc fail for %u "
6731 "bytes !\n", (unsigned int)state->total_param));
6732 SAFE_FREE(state->data);
6733 TALLOC_FREE(state);
6734 END_PROFILE(SMBtrans2);
6735 return(ERROR_DOS(ERRDOS,ERRnomem));
6737 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6738 goto bad_param;
6739 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6740 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6741 goto bad_param;
6743 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6746 state->received_data = dscnt;
6747 state->received_param = pscnt;
6749 if ((state->received_param == state->total_param) &&
6750 (state->received_data == state->total_data)) {
6752 outsize = handle_trans2(conn, state, inbuf, outbuf,
6753 size, bufsize);
6754 SAFE_FREE(state->data);
6755 SAFE_FREE(state->param);
6756 TALLOC_FREE(state);
6757 END_PROFILE(SMBtrans2);
6758 return outsize;
6761 DLIST_ADD(conn->pending_trans, state);
6763 /* We need to send an interim response then receive the rest
6764 of the parameter/data bytes */
6765 outsize = set_message(inbuf, outbuf,0,0,False);
6766 show_msg(outbuf);
6767 END_PROFILE(SMBtrans2);
6768 return outsize;
6770 bad_param:
6772 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6773 SAFE_FREE(state->data);
6774 SAFE_FREE(state->param);
6775 TALLOC_FREE(state);
6776 END_PROFILE(SMBtrans2);
6777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6781 /****************************************************************************
6782 Reply to a SMBtranss2
6783 ****************************************************************************/
6785 int reply_transs2(connection_struct *conn,
6786 char *inbuf,char *outbuf,int size,int bufsize)
6788 int outsize = 0;
6789 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6790 struct trans_state *state;
6792 START_PROFILE(SMBtranss2);
6794 show_msg(inbuf);
6796 for (state = conn->pending_trans; state != NULL;
6797 state = state->next) {
6798 if (state->mid == SVAL(inbuf,smb_mid)) {
6799 break;
6803 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6804 END_PROFILE(SMBtranss2);
6805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6808 /* Revise state->total_param and state->total_data in case they have
6809 changed downwards */
6811 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6812 state->total_param = SVAL(inbuf, smb_tpscnt);
6813 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6814 state->total_data = SVAL(inbuf, smb_tdscnt);
6816 pcnt = SVAL(inbuf, smb_spscnt);
6817 poff = SVAL(inbuf, smb_spsoff);
6818 pdisp = SVAL(inbuf, smb_spsdisp);
6820 dcnt = SVAL(inbuf, smb_sdscnt);
6821 doff = SVAL(inbuf, smb_sdsoff);
6822 ddisp = SVAL(inbuf, smb_sdsdisp);
6824 state->received_param += pcnt;
6825 state->received_data += dcnt;
6827 if ((state->received_data > state->total_data) ||
6828 (state->received_param > state->total_param))
6829 goto bad_param;
6831 if (pcnt) {
6832 if (pdisp+pcnt > state->total_param)
6833 goto bad_param;
6834 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6835 goto bad_param;
6836 if (pdisp > state->total_param)
6837 goto bad_param;
6838 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6839 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6840 goto bad_param;
6841 if (state->param + pdisp < state->param)
6842 goto bad_param;
6844 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6845 pcnt);
6848 if (dcnt) {
6849 if (ddisp+dcnt > state->total_data)
6850 goto bad_param;
6851 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6852 goto bad_param;
6853 if (ddisp > state->total_data)
6854 goto bad_param;
6855 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6856 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6857 goto bad_param;
6858 if (state->data + ddisp < state->data)
6859 goto bad_param;
6861 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6862 dcnt);
6865 if ((state->received_param < state->total_param) ||
6866 (state->received_data < state->total_data)) {
6867 END_PROFILE(SMBtranss2);
6868 return -1;
6871 /* construct_reply_common has done us the favor to pre-fill the
6872 * command field with SMBtranss2 which is wrong :-)
6874 SCVAL(outbuf,smb_com,SMBtrans2);
6876 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6878 DLIST_REMOVE(conn->pending_trans, state);
6879 SAFE_FREE(state->data);
6880 SAFE_FREE(state->param);
6881 TALLOC_FREE(state);
6883 if (outsize == 0) {
6884 END_PROFILE(SMBtranss2);
6885 return(ERROR_DOS(ERRSRV,ERRnosupport));
6888 END_PROFILE(SMBtranss2);
6889 return(outsize);
6891 bad_param:
6893 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6894 DLIST_REMOVE(conn->pending_trans, state);
6895 SAFE_FREE(state->data);
6896 SAFE_FREE(state->param);
6897 TALLOC_FREE(state);
6898 END_PROFILE(SMBtranss2);
6899 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);