[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / smbd / trans2.c
blobb2ce5b8c26d7b42f8a7c01c8e6c6b59e7d3d2c43
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, 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, (const char *)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(char *outbuf,
581 int bufsize,
582 const char *params,
583 int paramsize,
584 const char *pdata,
585 int datasize,
586 int max_data_bytes)
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
596 int useable_space;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
610 for OS/2. */
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
622 show_msg(outbuf);
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
625 return 0;
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
685 else
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
693 } else {
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
717 show_msg(outbuf);
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
727 /* Sanity check */
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
731 return -1;
735 return 0;
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
748 int deny_mode;
749 int32 open_attr;
750 BOOL oplock_request;
751 #if 0
752 BOOL return_additional_info;
753 int16 open_sattr;
754 time_t open_time;
755 #endif
756 int open_ofun;
757 uint32 open_size;
758 char *pname;
759 pstring fname;
760 SMB_OFF_T size=0;
761 int fattr=0,mtime=0;
762 SMB_INO_T inode = 0;
763 SMB_STRUCT_STAT sbuf;
764 int smb_action = 0;
765 files_struct *fsp;
766 struct ea_list *ea_list = NULL;
767 uint16 flags = 0;
768 NTSTATUS status;
769 uint32 access_mask;
770 uint32 share_mode;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
790 #if 0
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
794 #endif
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
797 pname = &params[28];
799 if (IS_IPC(conn)) {
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
829 &access_mask,
830 &share_mode,
831 &create_disposition,
832 &create_options)) {
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
853 total_data - 4);
854 if (!ea_list) {
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
862 access_mask,
863 share_mode,
864 create_disposition,
865 create_options,
866 open_attr,
867 oplock_request,
868 &smb_action, &fsp);
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
873 return -1;
875 return ERROR_OPEN(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
881 inode = sbuf.st_ino;
882 if (fattr & aDIR) {
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
906 } else {
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
924 params = *pparams;
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
945 if (flags & 8) {
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
948 } else {
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
955 return -1;
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
968 return False;
969 if (conn->case_sensitive)
970 return strcmp(str,mask)==0;
971 if (StrCaseCmp(str,mask) != 0) {
972 return False;
974 if (dptr_has_wild(conn->dirptr)) {
975 return False;
977 return True;
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32 unix_filetype(mode_t mode)
986 if(S_ISREG(mode))
987 return UNIX_TYPE_FILE;
988 else if(S_ISDIR(mode))
989 return UNIX_TYPE_DIR;
990 #ifdef S_ISLNK
991 else if(S_ISLNK(mode))
992 return UNIX_TYPE_SYMLINK;
993 #endif
994 #ifdef S_ISCHR
995 else if(S_ISCHR(mode))
996 return UNIX_TYPE_CHARDEV;
997 #endif
998 #ifdef S_ISBLK
999 else if(S_ISBLK(mode))
1000 return UNIX_TYPE_BLKDEV;
1001 #endif
1002 #ifdef S_ISFIFO
1003 else if(S_ISFIFO(mode))
1004 return UNIX_TYPE_FIFO;
1005 #endif
1006 #ifdef S_ISSOCK
1007 else if(S_ISSOCK(mode))
1008 return UNIX_TYPE_SOCKET;
1009 #endif
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012 return UNIX_TYPE_UNKNOWN;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022 SMB_STRUCT_STAT *psbuf,
1023 uint32 perms,
1024 enum perm_type ptype,
1025 mode_t *ret_perms)
1027 mode_t ret = 0;
1029 if (perms == SMB_MODE_NO_CHANGE) {
1030 if (!VALID_STAT(*psbuf)) {
1031 return NT_STATUS_INVALID_PARAMETER;
1032 } else {
1033 *ret_perms = psbuf->st_mode;
1034 return NT_STATUS_OK;
1038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1047 #ifdef S_ISVTX
1048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1049 #endif
1050 #ifdef S_ISGID
1051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1052 #endif
1053 #ifdef S_ISUID
1054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1055 #endif
1057 switch (ptype) {
1058 case PERM_NEW_FILE:
1059 /* Apply mode mask */
1060 ret &= lp_create_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_create_mode(SNUM(conn));
1063 break;
1064 case PERM_NEW_DIR:
1065 ret &= lp_dir_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_dir_mode(SNUM(conn));
1068 break;
1069 case PERM_EXISTING_FILE:
1070 /* Apply mode mask */
1071 ret &= lp_security_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_security_mode(SNUM(conn));
1074 break;
1075 case PERM_EXISTING_DIR:
1076 /* Apply mode mask */
1077 ret &= lp_dir_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_dir_security_mode(SNUM(conn));
1080 break;
1083 *ret_perms = ret;
1084 return NT_STATUS_OK;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092 void *inbuf, char *outbuf,
1093 char *path_mask,uint32 dirtype,int info_level,
1094 int requires_resume_key,
1095 BOOL dont_descend,char **ppdata,
1096 char *base_data, int space_remaining,
1097 BOOL *out_of_space, BOOL *got_exact_match,
1098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1100 const char *dname;
1101 BOOL found = False;
1102 SMB_STRUCT_STAT sbuf;
1103 pstring mask;
1104 pstring pathreal;
1105 pstring fname;
1106 char *p, *q, *pdata = *ppdata;
1107 uint32 reskey=0;
1108 long prev_dirpos=0;
1109 uint32 mode=0;
1110 SMB_OFF_T file_size = 0;
1111 SMB_BIG_UINT allocation_size = 0;
1112 uint32 len;
1113 struct timespec mdate_ts, adate_ts, create_date_ts;
1114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1115 char *nameptr;
1116 char *last_entry_ptr;
1117 BOOL was_8_3;
1118 uint32 nt_extmode; /* Used for NT connections instead of mode */
1119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120 BOOL check_mangled_names = lp_manglednames(conn->params);
1122 *fname = 0;
1123 *out_of_space = False;
1124 *got_exact_match = False;
1126 ZERO_STRUCT(mdate_ts);
1127 ZERO_STRUCT(adate_ts);
1128 ZERO_STRUCT(create_date_ts);
1130 if (!conn->dirptr)
1131 return(False);
1133 p = strrchr_m(path_mask,'/');
1134 if(p != NULL) {
1135 if(p[1] == '\0')
1136 pstrcpy(mask,"*.*");
1137 else
1138 pstrcpy(mask, p+1);
1139 } else
1140 pstrcpy(mask, path_mask);
1143 while (!found) {
1144 BOOL got_match;
1145 BOOL ms_dfs_link = False;
1147 /* Needed if we run out of space */
1148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1155 * JRA.
1158 reskey = 0;
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn->dirptr,curr_dirpos));
1163 if (!dname)
1164 return(False);
1166 pstrcpy(fname,dname);
1168 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1169 got_match = mask_match(fname, mask, conn->case_sensitive);
1171 if(!got_match && check_mangled_names &&
1172 !mangle_is_8_3(fname, False, conn->params)) {
1175 * It turns out that NT matches wildcards against
1176 * both long *and* short names. This may explain some
1177 * of the wildcard wierdness from old DOS clients
1178 * that some people have been seeing.... JRA.
1181 pstring newname;
1182 pstrcpy( newname, fname);
1183 mangle_map( newname, True, False, conn->params);
1184 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1185 got_match = mask_match(newname, mask, conn->case_sensitive);
1188 if(got_match) {
1189 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1190 if (dont_descend && !isdots)
1191 continue;
1193 pstrcpy(pathreal,conn->dirpath);
1194 if(needslash)
1195 pstrcat(pathreal,"/");
1196 pstrcat(pathreal,dname);
1198 if (INFO_LEVEL_IS_UNIX(info_level)) {
1199 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201 pathreal,strerror(errno)));
1202 continue;
1204 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1205 pstring link_target;
1207 /* Needed to show the msdfs symlinks as
1208 * directories */
1210 if(lp_host_msdfs() &&
1211 lp_msdfs_root(SNUM(conn)) &&
1212 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1214 "as a directory\n",
1215 pathreal));
1216 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1218 } else {
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1221 pathreal,strerror(errno)));
1222 continue;
1226 if (ms_dfs_link) {
1227 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1228 } else {
1229 mode = dos_mode(conn,pathreal,&sbuf);
1232 if (!dir_check_ftype(conn,mode,dirtype)) {
1233 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1234 continue;
1237 if (!(mode & aDIR))
1238 file_size = get_file_size(sbuf);
1239 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1241 mdate_ts = get_mtimespec(&sbuf);
1242 adate_ts = get_atimespec(&sbuf);
1243 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1245 if (lp_dos_filetime_resolution(SNUM(conn))) {
1246 dos_filetime_timespec(&create_date_ts);
1247 dos_filetime_timespec(&mdate_ts);
1248 dos_filetime_timespec(&adate_ts);
1251 create_date = convert_timespec_to_time_t(create_date_ts);
1252 mdate = convert_timespec_to_time_t(mdate_ts);
1253 adate = convert_timespec_to_time_t(adate_ts);
1255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1257 found = True;
1259 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1263 mangle_map(fname,False,True,conn->params);
1265 p = pdata;
1266 last_entry_ptr = p;
1268 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1270 switch (info_level) {
1271 case SMB_FIND_INFO_STANDARD:
1272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1273 if(requires_resume_key) {
1274 SIVAL(p,0,reskey);
1275 p += 4;
1277 srv_put_dos_date2(p,0,create_date);
1278 srv_put_dos_date2(p,4,adate);
1279 srv_put_dos_date2(p,8,mdate);
1280 SIVAL(p,12,(uint32)file_size);
1281 SIVAL(p,16,(uint32)allocation_size);
1282 SSVAL(p,20,mode);
1283 p += 23;
1284 nameptr = p;
1285 p += align_string(outbuf, p, 0);
1286 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1288 if (len > 2) {
1289 SCVAL(nameptr, -1, len - 2);
1290 } else {
1291 SCVAL(nameptr, -1, 0);
1293 } else {
1294 if (len > 1) {
1295 SCVAL(nameptr, -1, len - 1);
1296 } else {
1297 SCVAL(nameptr, -1, 0);
1300 p += len;
1301 break;
1303 case SMB_FIND_EA_SIZE:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1305 if(requires_resume_key) {
1306 SIVAL(p,0,reskey);
1307 p += 4;
1309 srv_put_dos_date2(p,0,create_date);
1310 srv_put_dos_date2(p,4,adate);
1311 srv_put_dos_date2(p,8,mdate);
1312 SIVAL(p,12,(uint32)file_size);
1313 SIVAL(p,16,(uint32)allocation_size);
1314 SSVAL(p,20,mode);
1316 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1317 SIVAL(p,22,ea_size); /* Extended attributes */
1319 p += 27;
1320 nameptr = p - 1;
1321 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1322 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1323 if (len > 2) {
1324 len -= 2;
1325 } else {
1326 len = 0;
1328 } else {
1329 if (len > 1) {
1330 len -= 1;
1331 } else {
1332 len = 0;
1335 SCVAL(nameptr,0,len);
1336 p += len;
1337 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1338 break;
1340 case SMB_FIND_EA_LIST:
1342 struct ea_list *file_list = NULL;
1343 size_t ea_len = 0;
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1346 if (!name_list) {
1347 return False;
1349 if(requires_resume_key) {
1350 SIVAL(p,0,reskey);
1351 p += 4;
1353 srv_put_dos_date2(p,0,create_date);
1354 srv_put_dos_date2(p,4,adate);
1355 srv_put_dos_date2(p,8,mdate);
1356 SIVAL(p,12,(uint32)file_size);
1357 SIVAL(p,16,(uint32)allocation_size);
1358 SSVAL(p,20,mode);
1359 p += 22; /* p now points to the EA area. */
1361 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1362 name_list = ea_list_union(name_list, file_list, &ea_len);
1364 /* We need to determine if this entry will fit in the space available. */
1365 /* Max string size is 255 bytes. */
1366 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1367 /* Move the dirptr back to prev_dirpos */
1368 dptr_SeekDir(conn->dirptr, prev_dirpos);
1369 *out_of_space = True;
1370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1371 return False; /* Not finished - just out of space */
1374 /* Push the ea_data followed by the name. */
1375 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1376 nameptr = p;
1377 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1378 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1379 if (len > 2) {
1380 len -= 2;
1381 } else {
1382 len = 0;
1384 } else {
1385 if (len > 1) {
1386 len -= 1;
1387 } else {
1388 len = 0;
1391 SCVAL(nameptr,0,len);
1392 p += len + 1;
1393 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1394 break;
1397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1399 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1400 p += 4;
1401 SIVAL(p,0,reskey); p += 4;
1402 put_long_date_timespec(p,create_date_ts); p += 8;
1403 put_long_date_timespec(p,adate_ts); p += 8;
1404 put_long_date_timespec(p,mdate_ts); p += 8;
1405 put_long_date_timespec(p,mdate_ts); p += 8;
1406 SOFF_T(p,0,file_size); p += 8;
1407 SOFF_T(p,0,allocation_size); p += 8;
1408 SIVAL(p,0,nt_extmode); p += 4;
1409 q = p; p += 4; /* q is placeholder for name length. */
1411 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1412 SIVAL(p,0,ea_size); /* Extended attributes */
1413 p += 4;
1415 /* Clear the short name buffer. This is
1416 * IMPORTANT as not doing so will trigger
1417 * a Win2k client bug. JRA.
1419 if (!was_8_3 && check_mangled_names) {
1420 pstring mangled_name;
1421 pstrcpy(mangled_name, fname);
1422 mangle_map(mangled_name,True,True,
1423 conn->params);
1424 mangled_name[12] = 0;
1425 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1426 if (len < 24) {
1427 memset(p + 2 + len,'\0',24 - len);
1429 SSVAL(p, 0, len);
1430 } else {
1431 memset(p,'\0',26);
1433 p += 2 + 24;
1434 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1435 SIVAL(q,0,len);
1436 p += len;
1437 SIVAL(p,0,0); /* Ensure any padding is null. */
1438 len = PTR_DIFF(p, pdata);
1439 len = (len + 3) & ~3;
1440 SIVAL(pdata,0,len);
1441 p = pdata + len;
1442 break;
1444 case SMB_FIND_FILE_DIRECTORY_INFO:
1445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1446 p += 4;
1447 SIVAL(p,0,reskey); p += 4;
1448 put_long_date_timespec(p,create_date_ts); p += 8;
1449 put_long_date_timespec(p,adate_ts); p += 8;
1450 put_long_date_timespec(p,mdate_ts); p += 8;
1451 put_long_date_timespec(p,mdate_ts); p += 8;
1452 SOFF_T(p,0,file_size); p += 8;
1453 SOFF_T(p,0,allocation_size); p += 8;
1454 SIVAL(p,0,nt_extmode); p += 4;
1455 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1456 SIVAL(p,0,len);
1457 p += 4 + len;
1458 SIVAL(p,0,0); /* Ensure any padding is null. */
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1461 SIVAL(pdata,0,len);
1462 p = pdata + len;
1463 break;
1465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1467 p += 4;
1468 SIVAL(p,0,reskey); p += 4;
1469 put_long_date_timespec(p,create_date_ts); p += 8;
1470 put_long_date_timespec(p,adate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 put_long_date_timespec(p,mdate_ts); p += 8;
1473 SOFF_T(p,0,file_size); p += 8;
1474 SOFF_T(p,0,allocation_size); p += 8;
1475 SIVAL(p,0,nt_extmode); p += 4;
1476 q = p; p += 4; /* q is placeholder for name length. */
1478 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1479 SIVAL(p,0,ea_size); /* Extended attributes */
1480 p +=4;
1482 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1483 SIVAL(q, 0, len);
1484 p += len;
1486 SIVAL(p,0,0); /* Ensure any padding is null. */
1487 len = PTR_DIFF(p, pdata);
1488 len = (len + 3) & ~3;
1489 SIVAL(pdata,0,len);
1490 p = pdata + len;
1491 break;
1493 case SMB_FIND_FILE_NAMES_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1495 p += 4;
1496 SIVAL(p,0,reskey); p += 4;
1497 p += 4;
1498 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1499 acl on a dir (tridge) */
1500 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1501 SIVAL(p, -4, len);
1502 p += len;
1503 SIVAL(p,0,0); /* Ensure any padding is null. */
1504 len = PTR_DIFF(p, pdata);
1505 len = (len + 3) & ~3;
1506 SIVAL(pdata,0,len);
1507 p = pdata + len;
1508 break;
1510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1512 p += 4;
1513 SIVAL(p,0,reskey); p += 4;
1514 put_long_date_timespec(p,create_date_ts); p += 8;
1515 put_long_date_timespec(p,adate_ts); p += 8;
1516 put_long_date_timespec(p,mdate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 SOFF_T(p,0,file_size); p += 8;
1519 SOFF_T(p,0,allocation_size); p += 8;
1520 SIVAL(p,0,nt_extmode); p += 4;
1521 q = p; p += 4; /* q is placeholder for name length. */
1523 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1524 SIVAL(p,0,ea_size); /* Extended attributes */
1525 p +=4;
1527 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1528 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1529 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1530 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1531 SIVAL(q, 0, len);
1532 p += len;
1533 SIVAL(p,0,0); /* Ensure any padding is null. */
1534 len = PTR_DIFF(p, pdata);
1535 len = (len + 3) & ~3;
1536 SIVAL(pdata,0,len);
1537 p = pdata + len;
1538 break;
1540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1542 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1543 p += 4;
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1556 p +=4;
1558 /* Clear the short name buffer. This is
1559 * IMPORTANT as not doing so will trigger
1560 * a Win2k client bug. JRA.
1562 if (!was_8_3 && check_mangled_names) {
1563 pstring mangled_name;
1564 pstrcpy(mangled_name, fname);
1565 mangle_map(mangled_name,True,True,
1566 conn->params);
1567 mangled_name[12] = 0;
1568 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1569 SSVAL(p, 0, len);
1570 if (len < 24) {
1571 memset(p + 2 + len,'\0',24 - len);
1573 SSVAL(p, 0, len);
1574 } else {
1575 memset(p,'\0',26);
1577 p += 26;
1578 SSVAL(p,0,0); p += 2; /* Reserved ? */
1579 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1580 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1581 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1582 SIVAL(q,0,len);
1583 p += len;
1584 SIVAL(p,0,0); /* Ensure any padding is null. */
1585 len = PTR_DIFF(p, pdata);
1586 len = (len + 3) & ~3;
1587 SIVAL(pdata,0,len);
1588 p = pdata + len;
1589 break;
1591 /* CIFS UNIX Extension. */
1593 case SMB_FIND_FILE_UNIX:
1594 case SMB_FIND_FILE_UNIX_INFO2:
1595 p+= 4;
1596 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1598 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (info_level == SMB_FIND_FILE_UNIX) {
1601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1602 p = store_file_unix_basic(conn, p,
1603 NULL, &sbuf);
1604 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1605 } else {
1606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1607 p = store_file_unix_basic_info2(conn, p,
1608 NULL, &sbuf);
1609 nameptr = p;
1610 p += 4;
1611 len = srvstr_push(outbuf, p, fname, -1, 0);
1612 SIVAL(nameptr, 0, len);
1615 p += len;
1616 SIVAL(p,0,0); /* Ensure any padding is null. */
1618 len = PTR_DIFF(p, pdata);
1619 len = (len + 3) & ~3;
1620 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1621 p = pdata + len;
1622 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1624 break;
1626 default:
1627 return(False);
1631 if (PTR_DIFF(p,pdata) > space_remaining) {
1632 /* Move the dirptr back to prev_dirpos */
1633 dptr_SeekDir(conn->dirptr, prev_dirpos);
1634 *out_of_space = True;
1635 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1636 return False; /* Not finished - just out of space */
1639 /* Setup the last entry pointer, as an offset from base_data */
1640 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1641 /* Advance the data pointer to the next slot */
1642 *ppdata = p;
1644 return(found);
1647 /****************************************************************************
1648 Reply to a TRANS2_FINDFIRST.
1649 ****************************************************************************/
1651 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1652 char **pparams, int total_params, char **ppdata, int total_data,
1653 unsigned int max_data_bytes)
1655 /* We must be careful here that we don't return more than the
1656 allowed number of data bytes. If this means returning fewer than
1657 maxentries then so be it. We assume that the redirector has
1658 enough room for the fixed number of parameter bytes it has
1659 requested. */
1660 char *params = *pparams;
1661 char *pdata = *ppdata;
1662 uint32 dirtype;
1663 int maxentries;
1664 uint16 findfirst_flags;
1665 BOOL close_after_first;
1666 BOOL close_if_end;
1667 BOOL requires_resume_key;
1668 int info_level;
1669 pstring directory;
1670 pstring mask;
1671 char *p;
1672 int last_entry_off=0;
1673 int dptr_num = -1;
1674 int numentries = 0;
1675 int i;
1676 BOOL finished = False;
1677 BOOL dont_descend = False;
1678 BOOL out_of_space = False;
1679 int space_remaining;
1680 BOOL mask_contains_wcard = False;
1681 SMB_STRUCT_STAT sbuf;
1682 TALLOC_CTX *ea_ctx = NULL;
1683 struct ea_list *ea_list = NULL;
1684 NTSTATUS ntstatus = NT_STATUS_OK;
1686 if (total_params < 13) {
1687 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1690 dirtype = SVAL(params,0);
1691 maxentries = SVAL(params,2);
1692 findfirst_flags = SVAL(params,4);
1693 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1694 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1695 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1696 info_level = SVAL(params,6);
1698 *directory = *mask = 0;
1700 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1701 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1702 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1703 info_level, max_data_bytes));
1705 if (!maxentries) {
1706 /* W2K3 seems to treat zero as 1. */
1707 maxentries = 1;
1710 switch (info_level) {
1711 case SMB_FIND_INFO_STANDARD:
1712 case SMB_FIND_EA_SIZE:
1713 case SMB_FIND_EA_LIST:
1714 case SMB_FIND_FILE_DIRECTORY_INFO:
1715 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1716 case SMB_FIND_FILE_NAMES_INFO:
1717 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1718 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1719 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1720 break;
1721 case SMB_FIND_FILE_UNIX:
1722 case SMB_FIND_FILE_UNIX_INFO2:
1723 if (!lp_unix_extensions()) {
1724 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1726 break;
1727 default:
1728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1731 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1732 if (!NT_STATUS_IS_OK(ntstatus)) {
1733 return ERROR_NT(ntstatus);
1736 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1737 if (!NT_STATUS_IS_OK(ntstatus)) {
1738 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1739 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1741 return ERROR_NT(ntstatus);
1744 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1745 if (!NT_STATUS_IS_OK(ntstatus)) {
1746 return ERROR_NT(ntstatus);
1748 ntstatus = check_name(conn, directory);
1749 if (!NT_STATUS_IS_OK(ntstatus)) {
1750 return ERROR_NT(ntstatus);
1753 p = strrchr_m(directory,'/');
1754 if(p == NULL) {
1755 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1756 if((directory[0] == '.') && (directory[1] == '\0')) {
1757 pstrcpy(mask,"*");
1758 mask_contains_wcard = True;
1759 } else {
1760 pstrcpy(mask,directory);
1762 pstrcpy(directory,"./");
1763 } else {
1764 pstrcpy(mask,p+1);
1765 *p = 0;
1768 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1770 if (info_level == SMB_FIND_EA_LIST) {
1771 uint32 ea_size;
1773 if (total_data < 4) {
1774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1777 ea_size = IVAL(pdata,0);
1778 if (ea_size != total_data) {
1779 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1780 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1784 if (!lp_ea_support(SNUM(conn))) {
1785 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1788 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1789 return ERROR_NT(NT_STATUS_NO_MEMORY);
1792 /* Pull out the list of names. */
1793 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1794 if (!ea_list) {
1795 talloc_destroy(ea_ctx);
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 *ppdata = (char *)SMB_REALLOC(
1801 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1802 if(*ppdata == NULL ) {
1803 talloc_destroy(ea_ctx);
1804 return ERROR_NT(NT_STATUS_NO_MEMORY);
1806 pdata = *ppdata;
1808 /* Realloc the params space */
1809 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1810 if (*pparams == NULL) {
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_NO_MEMORY);
1814 params = *pparams;
1816 /* Save the wildcard match and attribs we are using on this directory -
1817 needed as lanman2 assumes these are being saved between calls */
1819 ntstatus = dptr_create(conn,
1820 directory,
1821 False,
1822 True,
1823 SVAL(inbuf,smb_pid),
1824 mask,
1825 mask_contains_wcard,
1826 dirtype,
1827 &conn->dirptr);
1829 if (!NT_STATUS_IS_OK(ntstatus)) {
1830 talloc_destroy(ea_ctx);
1831 return ERROR_NT(ntstatus);
1834 dptr_num = dptr_dnum(conn->dirptr);
1835 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1837 /* We don't need to check for VOL here as this is returned by
1838 a different TRANS2 call. */
1840 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1841 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1842 dont_descend = True;
1844 p = pdata;
1845 space_remaining = max_data_bytes;
1846 out_of_space = False;
1848 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1849 BOOL got_exact_match = False;
1851 /* this is a heuristic to avoid seeking the dirptr except when
1852 absolutely necessary. It allows for a filename of about 40 chars */
1853 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1854 out_of_space = True;
1855 finished = False;
1856 } else {
1857 finished = !get_lanman2_dir_entry(conn,
1858 inbuf, outbuf,
1859 mask,dirtype,info_level,
1860 requires_resume_key,dont_descend,
1861 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1862 &last_entry_off, ea_list, ea_ctx);
1865 if (finished && out_of_space)
1866 finished = False;
1868 if (!finished && !out_of_space)
1869 numentries++;
1872 * As an optimisation if we know we aren't looking
1873 * for a wildcard name (ie. the name matches the wildcard exactly)
1874 * then we can finish on any (first) match.
1875 * This speeds up large directory searches. JRA.
1878 if(got_exact_match)
1879 finished = True;
1881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1884 talloc_destroy(ea_ctx);
1886 /* Check if we can close the dirptr */
1887 if(close_after_first || (finished && close_if_end)) {
1888 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1889 dptr_close(&dptr_num);
1893 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1894 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1895 * the protocol level is less than NT1. Tested with smbclient. JRA.
1896 * This should fix the OS/2 client bug #2335.
1899 if(numentries == 0) {
1900 dptr_close(&dptr_num);
1901 if (Protocol < PROTOCOL_NT1) {
1902 return ERROR_DOS(ERRDOS,ERRnofiles);
1903 } else {
1904 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1908 /* At this point pdata points to numentries directory entries. */
1910 /* Set up the return parameter block */
1911 SSVAL(params,0,dptr_num);
1912 SSVAL(params,2,numentries);
1913 SSVAL(params,4,finished);
1914 SSVAL(params,6,0); /* Never an EA error */
1915 SSVAL(params,8,last_entry_off);
1917 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1919 if ((! *directory) && dptr_path(dptr_num))
1920 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1922 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1923 smb_fn_name(CVAL(inbuf,smb_com)),
1924 mask, directory, dirtype, numentries ) );
1927 * Force a name mangle here to ensure that the
1928 * mask as an 8.3 name is top of the mangled cache.
1929 * The reasons for this are subtle. Don't remove
1930 * this code unless you know what you are doing
1931 * (see PR#13758). JRA.
1934 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1935 mangle_map(mask, True, True, conn->params);
1937 return(-1);
1940 /****************************************************************************
1941 Reply to a TRANS2_FINDNEXT.
1942 ****************************************************************************/
1944 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1945 char **pparams, int total_params, char **ppdata, int total_data,
1946 unsigned int max_data_bytes)
1948 /* We must be careful here that we don't return more than the
1949 allowed number of data bytes. If this means returning fewer than
1950 maxentries then so be it. We assume that the redirector has
1951 enough room for the fixed number of parameter bytes it has
1952 requested. */
1953 char *params = *pparams;
1954 char *pdata = *ppdata;
1955 int dptr_num;
1956 int maxentries;
1957 uint16 info_level;
1958 uint32 resume_key;
1959 uint16 findnext_flags;
1960 BOOL close_after_request;
1961 BOOL close_if_end;
1962 BOOL requires_resume_key;
1963 BOOL continue_bit;
1964 BOOL mask_contains_wcard = False;
1965 pstring resume_name;
1966 pstring mask;
1967 pstring directory;
1968 char *p;
1969 uint16 dirtype;
1970 int numentries = 0;
1971 int i, last_entry_off=0;
1972 BOOL finished = False;
1973 BOOL dont_descend = False;
1974 BOOL out_of_space = False;
1975 int space_remaining;
1976 TALLOC_CTX *ea_ctx = NULL;
1977 struct ea_list *ea_list = NULL;
1978 NTSTATUS ntstatus = NT_STATUS_OK;
1980 if (total_params < 13) {
1981 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1984 dptr_num = SVAL(params,0);
1985 maxentries = SVAL(params,2);
1986 info_level = SVAL(params,4);
1987 resume_key = IVAL(params,6);
1988 findnext_flags = SVAL(params,10);
1989 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1990 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1991 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1992 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1994 *mask = *directory = *resume_name = 0;
1996 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1997 if (!NT_STATUS_IS_OK(ntstatus)) {
1998 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1999 complain (it thinks we're asking for the directory above the shared
2000 path or an invalid name). Catch this as the resume name is only compared, never used in
2001 a file access. JRA. */
2002 srvstr_pull(inbuf, resume_name, params+12,
2003 sizeof(resume_name), total_params - 12,
2004 STR_TERMINATE);
2006 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2007 return ERROR_NT(ntstatus);
2011 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2012 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2013 resume_key = %d resume name = %s continue=%d level = %d\n",
2014 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2015 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2017 if (!maxentries) {
2018 /* W2K3 seems to treat zero as 1. */
2019 maxentries = 1;
2022 switch (info_level) {
2023 case SMB_FIND_INFO_STANDARD:
2024 case SMB_FIND_EA_SIZE:
2025 case SMB_FIND_EA_LIST:
2026 case SMB_FIND_FILE_DIRECTORY_INFO:
2027 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2028 case SMB_FIND_FILE_NAMES_INFO:
2029 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2030 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2031 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2032 break;
2033 case SMB_FIND_FILE_UNIX:
2034 case SMB_FIND_FILE_UNIX_INFO2:
2035 if (!lp_unix_extensions()) {
2036 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2038 break;
2039 default:
2040 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2043 if (info_level == SMB_FIND_EA_LIST) {
2044 uint32 ea_size;
2046 if (total_data < 4) {
2047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2050 ea_size = IVAL(pdata,0);
2051 if (ea_size != total_data) {
2052 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2053 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2057 if (!lp_ea_support(SNUM(conn))) {
2058 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2061 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2062 return ERROR_NT(NT_STATUS_NO_MEMORY);
2065 /* Pull out the list of names. */
2066 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2067 if (!ea_list) {
2068 talloc_destroy(ea_ctx);
2069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 *ppdata = (char *)SMB_REALLOC(
2074 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2075 if(*ppdata == NULL) {
2076 talloc_destroy(ea_ctx);
2077 return ERROR_NT(NT_STATUS_NO_MEMORY);
2080 pdata = *ppdata;
2082 /* Realloc the params space */
2083 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2084 if(*pparams == NULL ) {
2085 talloc_destroy(ea_ctx);
2086 return ERROR_NT(NT_STATUS_NO_MEMORY);
2089 params = *pparams;
2091 /* Check that the dptr is valid */
2092 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2093 talloc_destroy(ea_ctx);
2094 return ERROR_DOS(ERRDOS,ERRnofiles);
2097 string_set(&conn->dirpath,dptr_path(dptr_num));
2099 /* Get the wildcard mask from the dptr */
2100 if((p = dptr_wcard(dptr_num))== NULL) {
2101 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2102 talloc_destroy(ea_ctx);
2103 return ERROR_DOS(ERRDOS,ERRnofiles);
2106 pstrcpy(mask, p);
2107 pstrcpy(directory,conn->dirpath);
2109 /* Get the attr mask from the dptr */
2110 dirtype = dptr_attr(dptr_num);
2112 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2113 dptr_num, mask, dirtype,
2114 (long)conn->dirptr,
2115 dptr_TellDir(conn->dirptr)));
2117 /* We don't need to check for VOL here as this is returned by
2118 a different TRANS2 call. */
2120 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2121 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2122 dont_descend = True;
2124 p = pdata;
2125 space_remaining = max_data_bytes;
2126 out_of_space = False;
2129 * Seek to the correct position. We no longer use the resume key but
2130 * depend on the last file name instead.
2133 if(*resume_name && !continue_bit) {
2134 SMB_STRUCT_STAT st;
2136 long current_pos = 0;
2138 * Remember, mangle_map is called by
2139 * get_lanman2_dir_entry(), so the resume name
2140 * could be mangled. Ensure we check the unmangled name.
2143 if (mangle_is_mangled(resume_name, conn->params)) {
2144 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2145 conn->params);
2149 * Fix for NT redirector problem triggered by resume key indexes
2150 * changing between directory scans. We now return a resume key of 0
2151 * and instead look for the filename to continue from (also given
2152 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2153 * findfirst/findnext (as is usual) then the directory pointer
2154 * should already be at the correct place.
2157 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2158 } /* end if resume_name && !continue_bit */
2160 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2161 BOOL got_exact_match = False;
2163 /* this is a heuristic to avoid seeking the dirptr except when
2164 absolutely necessary. It allows for a filename of about 40 chars */
2165 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2166 out_of_space = True;
2167 finished = False;
2168 } else {
2169 finished = !get_lanman2_dir_entry(conn,
2170 inbuf, outbuf,
2171 mask,dirtype,info_level,
2172 requires_resume_key,dont_descend,
2173 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2174 &last_entry_off, ea_list, ea_ctx);
2177 if (finished && out_of_space)
2178 finished = False;
2180 if (!finished && !out_of_space)
2181 numentries++;
2184 * As an optimisation if we know we aren't looking
2185 * for a wildcard name (ie. the name matches the wildcard exactly)
2186 * then we can finish on any (first) match.
2187 * This speeds up large directory searches. JRA.
2190 if(got_exact_match)
2191 finished = True;
2193 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2196 talloc_destroy(ea_ctx);
2198 /* Check if we can close the dirptr */
2199 if(close_after_request || (finished && close_if_end)) {
2200 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2201 dptr_close(&dptr_num); /* This frees up the saved mask */
2204 /* Set up the return parameter block */
2205 SSVAL(params,0,numentries);
2206 SSVAL(params,2,finished);
2207 SSVAL(params,4,0); /* Never an EA error */
2208 SSVAL(params,6,last_entry_off);
2210 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2212 if ((! *directory) && dptr_path(dptr_num))
2213 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2215 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2216 smb_fn_name(CVAL(inbuf,smb_com)),
2217 mask, directory, dirtype, numentries ) );
2219 return(-1);
2222 /****************************************************************************
2223 Reply to a TRANS2_QFSINFO (query filesystem info).
2224 ****************************************************************************/
2226 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2227 char **pparams, int total_params, char **ppdata, int total_data,
2228 unsigned int max_data_bytes)
2230 char *pdata;
2231 char *params = *pparams;
2232 uint16 info_level;
2233 int data_len, len;
2234 SMB_STRUCT_STAT st;
2235 const char *vname = volume_label(SNUM(conn));
2236 int snum = SNUM(conn);
2237 char *fstype = lp_fstype(SNUM(conn));
2238 int quota_flag = 0;
2240 if (total_params < 2) {
2241 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2244 info_level = SVAL(params,0);
2246 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2248 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2249 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2250 return ERROR_DOS(ERRSRV,ERRinvdevice);
2253 *ppdata = (char *)SMB_REALLOC(
2254 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2255 if (*ppdata == NULL ) {
2256 return ERROR_NT(NT_STATUS_NO_MEMORY);
2259 pdata = *ppdata;
2260 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2262 switch (info_level) {
2263 case SMB_INFO_ALLOCATION:
2265 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2266 data_len = 18;
2267 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2268 return(UNIXERROR(ERRHRD,ERRgeneral));
2271 block_size = lp_block_size(snum);
2272 if (bsize < block_size) {
2273 SMB_BIG_UINT factor = block_size/bsize;
2274 bsize = block_size;
2275 dsize /= factor;
2276 dfree /= factor;
2278 if (bsize > block_size) {
2279 SMB_BIG_UINT factor = bsize/block_size;
2280 bsize = block_size;
2281 dsize *= factor;
2282 dfree *= factor;
2284 bytes_per_sector = 512;
2285 sectors_per_unit = bsize/bytes_per_sector;
2287 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2289 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2291 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2292 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2293 SIVAL(pdata,l1_cUnit,dsize);
2294 SIVAL(pdata,l1_cUnitAvail,dfree);
2295 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2296 break;
2299 case SMB_INFO_VOLUME:
2300 /* Return volume name */
2302 * Add volume serial number - hash of a combination of
2303 * the called hostname and the service name.
2305 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2307 * Win2k3 and previous mess this up by sending a name length
2308 * one byte short. I believe only older clients (OS/2 Win9x) use
2309 * this call so try fixing this by adding a terminating null to
2310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2312 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2313 SCVAL(pdata,l2_vol_cch,len);
2314 data_len = l2_vol_szVolLabel + len;
2315 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2316 (unsigned)st.st_ctime, len, vname));
2317 break;
2319 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2320 case SMB_FS_ATTRIBUTE_INFORMATION:
2323 #if defined(HAVE_SYS_QUOTAS)
2324 quota_flag = FILE_VOLUME_QUOTAS;
2325 #endif
2327 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2328 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2329 quota_flag); /* FS ATTRIBUTES */
2331 SIVAL(pdata,4,255); /* Max filename component length */
2332 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2333 and will think we can't do long filenames */
2334 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2335 SIVAL(pdata,8,len);
2336 data_len = 12 + len;
2337 break;
2339 case SMB_QUERY_FS_LABEL_INFO:
2340 case SMB_FS_LABEL_INFORMATION:
2341 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2342 data_len = 4 + len;
2343 SIVAL(pdata,0,len);
2344 break;
2346 case SMB_QUERY_FS_VOLUME_INFO:
2347 case SMB_FS_VOLUME_INFORMATION:
2350 * Add volume serial number - hash of a combination of
2351 * the called hostname and the service name.
2353 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2354 (str_checksum(get_local_machine_name())<<16));
2356 /* Max label len is 32 characters. */
2357 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2358 SIVAL(pdata,12,len);
2359 data_len = 18+len;
2361 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2362 (int)strlen(vname),vname, lp_servicename(snum)));
2363 break;
2365 case SMB_QUERY_FS_SIZE_INFO:
2366 case SMB_FS_SIZE_INFORMATION:
2368 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2369 data_len = 24;
2370 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2371 return(UNIXERROR(ERRHRD,ERRgeneral));
2373 block_size = lp_block_size(snum);
2374 if (bsize < block_size) {
2375 SMB_BIG_UINT factor = block_size/bsize;
2376 bsize = block_size;
2377 dsize /= factor;
2378 dfree /= factor;
2380 if (bsize > block_size) {
2381 SMB_BIG_UINT factor = bsize/block_size;
2382 bsize = block_size;
2383 dsize *= factor;
2384 dfree *= factor;
2386 bytes_per_sector = 512;
2387 sectors_per_unit = bsize/bytes_per_sector;
2388 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2389 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2390 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2391 SBIG_UINT(pdata,0,dsize);
2392 SBIG_UINT(pdata,8,dfree);
2393 SIVAL(pdata,16,sectors_per_unit);
2394 SIVAL(pdata,20,bytes_per_sector);
2395 break;
2398 case SMB_FS_FULL_SIZE_INFORMATION:
2400 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2401 data_len = 32;
2402 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2403 return(UNIXERROR(ERRHRD,ERRgeneral));
2405 block_size = lp_block_size(snum);
2406 if (bsize < block_size) {
2407 SMB_BIG_UINT factor = block_size/bsize;
2408 bsize = block_size;
2409 dsize /= factor;
2410 dfree /= factor;
2412 if (bsize > block_size) {
2413 SMB_BIG_UINT factor = bsize/block_size;
2414 bsize = block_size;
2415 dsize *= factor;
2416 dfree *= factor;
2418 bytes_per_sector = 512;
2419 sectors_per_unit = bsize/bytes_per_sector;
2420 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2421 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2422 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2423 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2424 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2425 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2426 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2427 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2428 break;
2431 case SMB_QUERY_FS_DEVICE_INFO:
2432 case SMB_FS_DEVICE_INFORMATION:
2433 data_len = 8;
2434 SIVAL(pdata,0,0); /* dev type */
2435 SIVAL(pdata,4,0); /* characteristics */
2436 break;
2438 #ifdef HAVE_SYS_QUOTAS
2439 case SMB_FS_QUOTA_INFORMATION:
2441 * what we have to send --metze:
2443 * Unknown1: 24 NULL bytes
2444 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2445 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2446 * Quota Flags: 2 byte :
2447 * Unknown3: 6 NULL bytes
2449 * 48 bytes total
2451 * details for Quota Flags:
2453 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2454 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2455 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2456 * 0x0001 Enable Quotas: enable quota for this fs
2460 /* we need to fake up a fsp here,
2461 * because its not send in this call
2463 files_struct fsp;
2464 SMB_NTQUOTA_STRUCT quotas;
2466 ZERO_STRUCT(fsp);
2467 ZERO_STRUCT(quotas);
2469 fsp.conn = conn;
2470 fsp.fnum = -1;
2472 /* access check */
2473 if (current_user.ut.uid != 0) {
2474 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2475 lp_servicename(SNUM(conn)),conn->user));
2476 return ERROR_DOS(ERRDOS,ERRnoaccess);
2479 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2480 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2481 return ERROR_DOS(ERRSRV,ERRerror);
2484 data_len = 48;
2486 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2488 /* Unknown1 24 NULL bytes*/
2489 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2490 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2491 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2493 /* Default Soft Quota 8 bytes */
2494 SBIG_UINT(pdata,24,quotas.softlim);
2496 /* Default Hard Quota 8 bytes */
2497 SBIG_UINT(pdata,32,quotas.hardlim);
2499 /* Quota flag 2 bytes */
2500 SSVAL(pdata,40,quotas.qflags);
2502 /* Unknown3 6 NULL bytes */
2503 SSVAL(pdata,42,0);
2504 SIVAL(pdata,44,0);
2506 break;
2508 #endif /* HAVE_SYS_QUOTAS */
2509 case SMB_FS_OBJECTID_INFORMATION:
2510 data_len = 64;
2511 break;
2514 * Query the version and capabilities of the CIFS UNIX extensions
2515 * in use.
2518 case SMB_QUERY_CIFS_UNIX_INFO:
2519 if (!lp_unix_extensions()) {
2520 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2522 data_len = 12;
2523 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2524 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2525 /* We have POSIX ACLs, pathname and locking capability. */
2526 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2527 CIFS_UNIX_POSIX_ACLS_CAP|
2528 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2529 CIFS_UNIX_FCNTL_LOCKS_CAP|
2530 CIFS_UNIX_EXTATTR_CAP|
2531 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2532 break;
2534 case SMB_QUERY_POSIX_FS_INFO:
2536 int rc;
2537 vfs_statvfs_struct svfs;
2539 if (!lp_unix_extensions()) {
2540 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2543 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2545 if (!rc) {
2546 data_len = 56;
2547 SIVAL(pdata,0,svfs.OptimalTransferSize);
2548 SIVAL(pdata,4,svfs.BlockSize);
2549 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2550 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2551 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2552 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2553 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2554 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2555 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2556 #ifdef EOPNOTSUPP
2557 } else if (rc == EOPNOTSUPP) {
2558 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2559 #endif /* EOPNOTSUPP */
2560 } else {
2561 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2562 return ERROR_DOS(ERRSRV,ERRerror);
2564 break;
2567 case SMB_QUERY_POSIX_WHOAMI:
2569 uint32_t flags = 0;
2570 uint32_t sid_bytes;
2571 int i;
2573 if (!lp_unix_extensions()) {
2574 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2577 if (max_data_bytes < 40) {
2578 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2581 /* We ARE guest if global_sid_Builtin_Guests is
2582 * in our list of SIDs.
2584 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2585 current_user.nt_user_token)) {
2586 flags |= SMB_WHOAMI_GUEST;
2589 /* We are NOT guest if global_sid_Authenticated_Users
2590 * is in our list of SIDs.
2592 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2593 current_user.nt_user_token)) {
2594 flags &= ~SMB_WHOAMI_GUEST;
2597 /* NOTE: 8 bytes for UID/GID, irrespective of native
2598 * platform size. This matches
2599 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2601 data_len = 4 /* flags */
2602 + 4 /* flag mask */
2603 + 8 /* uid */
2604 + 8 /* gid */
2605 + 4 /* ngroups */
2606 + 4 /* num_sids */
2607 + 4 /* SID bytes */
2608 + 4 /* pad/reserved */
2609 + (current_user.ut.ngroups * 8)
2610 /* groups list */
2611 + (current_user.nt_user_token->num_sids *
2612 SID_MAX_SIZE)
2613 /* SID list */;
2615 SIVAL(pdata, 0, flags);
2616 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2617 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2618 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2621 if (data_len >= max_data_bytes) {
2622 /* Potential overflow, skip the GIDs and SIDs. */
2624 SIVAL(pdata, 24, 0); /* num_groups */
2625 SIVAL(pdata, 28, 0); /* num_sids */
2626 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2627 SIVAL(pdata, 36, 0); /* reserved */
2629 data_len = 40;
2630 break;
2633 SIVAL(pdata, 24, current_user.ut.ngroups);
2634 SIVAL(pdata, 28,
2635 current_user.nt_user_token->num_sids);
2637 /* We walk the SID list twice, but this call is fairly
2638 * infrequent, and I don't expect that it's performance
2639 * sensitive -- jpeach
2641 for (i = 0, sid_bytes = 0;
2642 i < current_user.nt_user_token->num_sids; ++i) {
2643 sid_bytes +=
2644 sid_size(&current_user.nt_user_token->user_sids[i]);
2647 /* SID list byte count */
2648 SIVAL(pdata, 32, sid_bytes);
2650 /* 4 bytes pad/reserved - must be zero */
2651 SIVAL(pdata, 36, 0);
2652 data_len = 40;
2654 /* GID list */
2655 for (i = 0; i < current_user.ut.ngroups; ++i) {
2656 SBIG_UINT(pdata, data_len,
2657 (SMB_BIG_UINT)current_user.ut.groups[i]);
2658 data_len += 8;
2661 /* SID list */
2662 for (i = 0;
2663 i < current_user.nt_user_token->num_sids; ++i) {
2664 int sid_len =
2665 sid_size(&current_user.nt_user_token->user_sids[i]);
2667 sid_linearize(pdata + data_len, sid_len,
2668 &current_user.nt_user_token->user_sids[i]);
2669 data_len += sid_len;
2672 break;
2675 case SMB_MAC_QUERY_FS_INFO:
2677 * Thursby MAC extension... ONLY on NTFS filesystems
2678 * once we do streams then we don't need this
2680 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2681 data_len = 88;
2682 SIVAL(pdata,84,0x100); /* Don't support mac... */
2683 break;
2685 /* drop through */
2686 default:
2687 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2691 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2693 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2695 return -1;
2698 /****************************************************************************
2699 Reply to a TRANS2_SETFSINFO (set filesystem info).
2700 ****************************************************************************/
2702 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2703 char **pparams, int total_params, char **ppdata, int total_data,
2704 unsigned int max_data_bytes)
2706 char *pdata = *ppdata;
2707 char *params = *pparams;
2708 uint16 info_level;
2709 int outsize;
2711 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2713 /* */
2714 if (total_params < 4) {
2715 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2716 total_params));
2717 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2720 info_level = SVAL(params,2);
2722 switch(info_level) {
2723 case SMB_SET_CIFS_UNIX_INFO:
2725 uint16 client_unix_major;
2726 uint16 client_unix_minor;
2727 uint32 client_unix_cap_low;
2728 uint32 client_unix_cap_high;
2730 if (!lp_unix_extensions()) {
2731 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2734 /* There should be 12 bytes of capabilities set. */
2735 if (total_data < 8) {
2736 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2738 client_unix_major = SVAL(pdata,0);
2739 client_unix_minor = SVAL(pdata,2);
2740 client_unix_cap_low = IVAL(pdata,4);
2741 client_unix_cap_high = IVAL(pdata,8);
2742 /* Just print these values for now. */
2743 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2744 cap_low = 0x%x, cap_high = 0x%x\n",
2745 (unsigned int)client_unix_major,
2746 (unsigned int)client_unix_minor,
2747 (unsigned int)client_unix_cap_low,
2748 (unsigned int)client_unix_cap_high ));
2750 /* Here is where we must switch to posix pathname processing... */
2751 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2752 lp_set_posix_pathnames();
2753 mangle_change_to_posix();
2756 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2757 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2758 /* Client that knows how to do posix locks,
2759 * but not posix open/mkdir operations. Set a
2760 * default type for read/write checks. */
2762 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2765 break;
2767 case SMB_FS_QUOTA_INFORMATION:
2769 files_struct *fsp = NULL;
2770 SMB_NTQUOTA_STRUCT quotas;
2772 ZERO_STRUCT(quotas);
2774 /* access check */
2775 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2776 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2777 lp_servicename(SNUM(conn)),conn->user));
2778 return ERROR_DOS(ERRSRV,ERRaccess);
2781 /* note: normaly there're 48 bytes,
2782 * but we didn't use the last 6 bytes for now
2783 * --metze
2785 fsp = file_fsp(params,0);
2786 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2787 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2788 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2791 if (total_data < 42) {
2792 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2793 total_data));
2794 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2797 /* unknown_1 24 NULL bytes in pdata*/
2799 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2800 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2801 #ifdef LARGE_SMB_OFF_T
2802 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2803 #else /* LARGE_SMB_OFF_T */
2804 if ((IVAL(pdata,28) != 0)&&
2805 ((quotas.softlim != 0xFFFFFFFF)||
2806 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2807 /* more than 32 bits? */
2808 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2810 #endif /* LARGE_SMB_OFF_T */
2812 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2813 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2814 #ifdef LARGE_SMB_OFF_T
2815 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2816 #else /* LARGE_SMB_OFF_T */
2817 if ((IVAL(pdata,36) != 0)&&
2818 ((quotas.hardlim != 0xFFFFFFFF)||
2819 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2820 /* more than 32 bits? */
2821 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2823 #endif /* LARGE_SMB_OFF_T */
2825 /* quota_flags 2 bytes **/
2826 quotas.qflags = SVAL(pdata,40);
2828 /* unknown_2 6 NULL bytes follow*/
2830 /* now set the quotas */
2831 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2832 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2833 return ERROR_DOS(ERRSRV,ERRerror);
2836 break;
2838 default:
2839 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2840 info_level));
2841 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2842 break;
2846 * sending this reply works fine,
2847 * but I'm not sure it's the same
2848 * like windows do...
2849 * --metze
2851 outsize = set_message(outbuf,10,0,True);
2853 return outsize;
2856 #if defined(HAVE_POSIX_ACLS)
2857 /****************************************************************************
2858 Utility function to count the number of entries in a POSIX acl.
2859 ****************************************************************************/
2861 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2863 unsigned int ace_count = 0;
2864 int entry_id = SMB_ACL_FIRST_ENTRY;
2865 SMB_ACL_ENTRY_T entry;
2867 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2868 /* get_next... */
2869 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2870 entry_id = SMB_ACL_NEXT_ENTRY;
2872 ace_count++;
2874 return ace_count;
2877 /****************************************************************************
2878 Utility function to marshall a POSIX acl into wire format.
2879 ****************************************************************************/
2881 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2883 int entry_id = SMB_ACL_FIRST_ENTRY;
2884 SMB_ACL_ENTRY_T entry;
2886 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2887 SMB_ACL_TAG_T tagtype;
2888 SMB_ACL_PERMSET_T permset;
2889 unsigned char perms = 0;
2890 unsigned int own_grp;
2892 /* get_next... */
2893 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2894 entry_id = SMB_ACL_NEXT_ENTRY;
2897 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2898 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2899 return False;
2902 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2903 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2904 return False;
2907 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2908 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2909 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2911 SCVAL(pdata,1,perms);
2913 switch (tagtype) {
2914 case SMB_ACL_USER_OBJ:
2915 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2916 own_grp = (unsigned int)pst->st_uid;
2917 SIVAL(pdata,2,own_grp);
2918 SIVAL(pdata,6,0);
2919 break;
2920 case SMB_ACL_USER:
2922 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2923 if (!puid) {
2924 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2926 own_grp = (unsigned int)*puid;
2927 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2928 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2929 SIVAL(pdata,2,own_grp);
2930 SIVAL(pdata,6,0);
2931 break;
2933 case SMB_ACL_GROUP_OBJ:
2934 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2935 own_grp = (unsigned int)pst->st_gid;
2936 SIVAL(pdata,2,own_grp);
2937 SIVAL(pdata,6,0);
2938 break;
2939 case SMB_ACL_GROUP:
2941 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2942 if (!pgid) {
2943 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2945 own_grp = (unsigned int)*pgid;
2946 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2947 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2948 SIVAL(pdata,2,own_grp);
2949 SIVAL(pdata,6,0);
2950 break;
2952 case SMB_ACL_MASK:
2953 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2954 SIVAL(pdata,2,0xFFFFFFFF);
2955 SIVAL(pdata,6,0xFFFFFFFF);
2956 break;
2957 case SMB_ACL_OTHER:
2958 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2959 SIVAL(pdata,2,0xFFFFFFFF);
2960 SIVAL(pdata,6,0xFFFFFFFF);
2961 break;
2962 default:
2963 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2964 return False;
2966 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2969 return True;
2971 #endif
2973 /****************************************************************************
2974 Store the FILE_UNIX_BASIC info.
2975 ****************************************************************************/
2977 static char *store_file_unix_basic(connection_struct *conn,
2978 char *pdata,
2979 files_struct *fsp,
2980 const SMB_STRUCT_STAT *psbuf)
2982 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2983 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2985 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
2986 pdata += 8;
2988 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2989 pdata += 8;
2991 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
2992 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
2993 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
2994 pdata += 24;
2996 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
2997 SIVAL(pdata,4,0);
2998 pdata += 8;
3000 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3001 SIVAL(pdata,4,0);
3002 pdata += 8;
3004 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3005 pdata += 4;
3007 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3008 SIVAL(pdata,4,0);
3009 pdata += 8;
3011 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3012 SIVAL(pdata,4,0);
3013 pdata += 8;
3015 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3016 pdata += 8;
3018 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3019 SIVAL(pdata,4,0);
3020 pdata += 8;
3022 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3023 SIVAL(pdata,4,0);
3024 pdata += 8;
3026 return pdata;
3029 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3030 * the chflags(2) (or equivalent) flags.
3032 * XXX: this really should be behind the VFS interface. To do this, we would
3033 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3034 * Each VFS module could then implement it's own mapping as appropriate for the
3035 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3037 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3038 info2_flags_map[] =
3040 #ifdef UF_NODUMP
3041 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3042 #endif
3044 #ifdef UF_IMMUTABLE
3045 { UF_IMMUTABLE, EXT_IMMUTABLE },
3046 #endif
3048 #ifdef UF_APPEND
3049 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3050 #endif
3052 #ifdef UF_HIDDEN
3053 { UF_HIDDEN, EXT_HIDDEN },
3054 #endif
3056 /* Do not remove. We need to guarantee that this array has at least one
3057 * entry to build on HP-UX.
3059 { 0, 0 }
3063 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3064 uint32 *smb_fflags, uint32 *smb_fmask)
3066 #ifdef HAVE_STAT_ST_FLAGS
3067 int i;
3069 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3070 *smb_fmask |= info2_flags_map[i].smb_fflag;
3071 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3072 *smb_fflags |= info2_flags_map[i].smb_fflag;
3075 #endif /* HAVE_STAT_ST_FLAGS */
3078 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3079 const uint32 smb_fflags,
3080 const uint32 smb_fmask,
3081 int *stat_fflags)
3083 #ifdef HAVE_STAT_ST_FLAGS
3084 uint32 max_fmask = 0;
3085 int i;
3087 *stat_fflags = psbuf->st_flags;
3089 /* For each flags requested in smb_fmask, check the state of the
3090 * corresponding flag in smb_fflags and set or clear the matching
3091 * stat flag.
3094 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3095 max_fmask |= info2_flags_map[i].smb_fflag;
3096 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3097 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3098 *stat_fflags |= info2_flags_map[i].stat_fflag;
3099 } else {
3100 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3105 /* If smb_fmask is asking to set any bits that are not supported by
3106 * our flag mappings, we should fail.
3108 if ((smb_fmask & max_fmask) != smb_fmask) {
3109 return False;
3112 return True;
3113 #else
3114 return False;
3115 #endif /* HAVE_STAT_ST_FLAGS */
3119 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3120 * of file flags and birth (create) time.
3122 static char *store_file_unix_basic_info2(connection_struct *conn,
3123 char *pdata,
3124 files_struct *fsp,
3125 const SMB_STRUCT_STAT *psbuf)
3127 uint32 file_flags = 0;
3128 uint32 flags_mask = 0;
3130 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3132 /* Create (birth) time 64 bit */
3133 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3134 pdata += 8;
3136 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3137 SIVAL(pdata, 0, file_flags); /* flags */
3138 SIVAL(pdata, 4, flags_mask); /* mask */
3139 pdata += 8;
3141 return pdata;
3144 /****************************************************************************
3145 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3146 file name or file id).
3147 ****************************************************************************/
3149 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3150 unsigned int tran_call,
3151 char **pparams, int total_params, char **ppdata, int total_data,
3152 unsigned int max_data_bytes)
3154 char *params = *pparams;
3155 char *pdata = *ppdata;
3156 uint16 info_level;
3157 int mode=0;
3158 int nlink;
3159 SMB_OFF_T file_size=0;
3160 SMB_BIG_UINT allocation_size=0;
3161 unsigned int data_size = 0;
3162 unsigned int param_size = 2;
3163 SMB_STRUCT_STAT sbuf;
3164 pstring fname, dos_fname;
3165 char *fullpathname;
3166 char *base_name;
3167 char *p;
3168 SMB_OFF_T pos = 0;
3169 BOOL delete_pending = False;
3170 int len;
3171 time_t create_time, mtime, atime;
3172 struct timespec create_time_ts, mtime_ts, atime_ts;
3173 files_struct *fsp = NULL;
3174 TALLOC_CTX *data_ctx = NULL;
3175 struct ea_list *ea_list = NULL;
3176 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3177 char *lock_data = NULL;
3179 if (!params)
3180 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3182 ZERO_STRUCT(sbuf);
3184 if (tran_call == TRANSACT2_QFILEINFO) {
3185 if (total_params < 4) {
3186 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3189 fsp = file_fsp(params,0);
3190 info_level = SVAL(params,2);
3192 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3194 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3195 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3198 if(fsp && (fsp->fake_file_handle)) {
3200 * This is actually for the QUOTA_FAKE_FILE --metze
3203 pstrcpy(fname, fsp->fsp_name);
3204 /* We know this name is ok, it's already passed the checks. */
3206 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3208 * This is actually a QFILEINFO on a directory
3209 * handle (returned from an NT SMB). NT5.0 seems
3210 * to do this call. JRA.
3212 /* We know this name is ok, it's already passed the checks. */
3213 pstrcpy(fname, fsp->fsp_name);
3215 if (INFO_LEVEL_IS_UNIX(info_level)) {
3216 /* Always do lstat for UNIX calls. */
3217 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3218 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3219 return UNIXERROR(ERRDOS,ERRbadpath);
3221 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3222 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3223 return UNIXERROR(ERRDOS,ERRbadpath);
3226 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3227 } else {
3229 * Original code - this is an open file.
3231 CHECK_FSP(fsp,conn);
3233 pstrcpy(fname, fsp->fsp_name);
3234 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3235 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3236 return(UNIXERROR(ERRDOS,ERRbadfid));
3238 pos = fsp->fh->position_information;
3239 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3240 access_mask = fsp->access_mask;
3242 } else {
3243 NTSTATUS status = NT_STATUS_OK;
3245 /* qpathinfo */
3246 if (total_params < 7) {
3247 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3250 info_level = SVAL(params,0);
3252 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3254 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3255 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3258 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 return ERROR_NT(status);
3263 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3266 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3268 return ERROR_NT(status);
3271 status = unix_convert(conn, fname, False, NULL, &sbuf);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 return ERROR_NT(status);
3275 status = check_name(conn, fname);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3278 return ERROR_NT(status);
3281 if (INFO_LEVEL_IS_UNIX(info_level)) {
3282 /* Always do lstat for UNIX calls. */
3283 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3284 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3285 return UNIXERROR(ERRDOS,ERRbadpath);
3287 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3288 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3289 return UNIXERROR(ERRDOS,ERRbadpath);
3292 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3293 if (delete_pending) {
3294 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3298 nlink = sbuf.st_nlink;
3300 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3301 /* NTFS does not seem to count ".." */
3302 nlink -= 1;
3305 if ((nlink > 0) && delete_pending) {
3306 nlink -= 1;
3309 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3310 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3313 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3314 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3316 p = strrchr_m(fname,'/');
3317 if (!p)
3318 base_name = fname;
3319 else
3320 base_name = p+1;
3322 mode = dos_mode(conn,fname,&sbuf);
3323 if (!mode)
3324 mode = FILE_ATTRIBUTE_NORMAL;
3326 fullpathname = fname;
3327 if (!(mode & aDIR))
3328 file_size = get_file_size(sbuf);
3330 /* Pull out any data sent here before we realloc. */
3331 switch (info_level) {
3332 case SMB_INFO_QUERY_EAS_FROM_LIST:
3334 /* Pull any EA list from the data portion. */
3335 uint32 ea_size;
3337 if (total_data < 4) {
3338 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3340 ea_size = IVAL(pdata,0);
3342 if (total_data > 0 && ea_size != total_data) {
3343 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3344 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3345 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3348 if (!lp_ea_support(SNUM(conn))) {
3349 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3352 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3353 return ERROR_NT(NT_STATUS_NO_MEMORY);
3356 /* Pull out the list of names. */
3357 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3358 if (!ea_list) {
3359 talloc_destroy(data_ctx);
3360 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3362 break;
3365 case SMB_QUERY_POSIX_LOCK:
3367 if (fsp == NULL || fsp->fh->fd == -1) {
3368 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3371 if (total_data != POSIX_LOCK_DATA_SIZE) {
3372 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3375 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3376 return ERROR_NT(NT_STATUS_NO_MEMORY);
3379 /* Copy the lock range data. */
3380 lock_data = (char *)TALLOC_MEMDUP(
3381 data_ctx, pdata, total_data);
3382 if (!lock_data) {
3383 talloc_destroy(data_ctx);
3384 return ERROR_NT(NT_STATUS_NO_MEMORY);
3387 default:
3388 break;
3391 *pparams = (char *)SMB_REALLOC(*pparams,2);
3392 if (*pparams == NULL) {
3393 talloc_destroy(data_ctx);
3394 return ERROR_NT(NT_STATUS_NO_MEMORY);
3396 params = *pparams;
3397 SSVAL(params,0,0);
3398 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3399 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3400 if (*ppdata == NULL ) {
3401 talloc_destroy(data_ctx);
3402 return ERROR_NT(NT_STATUS_NO_MEMORY);
3404 pdata = *ppdata;
3406 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3407 mtime_ts = get_mtimespec(&sbuf);
3408 atime_ts = get_atimespec(&sbuf);
3410 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3412 if (fsp) {
3413 if (!null_timespec(fsp->pending_modtime)) {
3414 /* the pending modtime overrides the current modtime */
3415 mtime_ts = fsp->pending_modtime;
3417 } else {
3418 /* Do we have this path open ? */
3419 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3420 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3421 /* the pending modtime overrides the current modtime */
3422 mtime_ts = fsp1->pending_modtime;
3424 if (fsp1 && fsp1->initial_allocation_size) {
3425 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3429 if (lp_dos_filetime_resolution(SNUM(conn))) {
3430 dos_filetime_timespec(&create_time_ts);
3431 dos_filetime_timespec(&mtime_ts);
3432 dos_filetime_timespec(&atime_ts);
3435 create_time = convert_timespec_to_time_t(create_time_ts);
3436 mtime = convert_timespec_to_time_t(mtime_ts);
3437 atime = convert_timespec_to_time_t(atime_ts);
3439 /* NT expects the name to be in an exact form of the *full*
3440 filename. See the trans2 torture test */
3441 if (strequal(base_name,".")) {
3442 pstrcpy(dos_fname, "\\");
3443 } else {
3444 pstr_sprintf(dos_fname, "\\%s", fname);
3445 string_replace(dos_fname, '/', '\\');
3448 switch (info_level) {
3449 case SMB_INFO_STANDARD:
3450 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3451 data_size = 22;
3452 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3453 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3454 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3455 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3456 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3457 SSVAL(pdata,l1_attrFile,mode);
3458 break;
3460 case SMB_INFO_QUERY_EA_SIZE:
3462 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3463 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3464 data_size = 26;
3465 srv_put_dos_date2(pdata,0,create_time);
3466 srv_put_dos_date2(pdata,4,atime);
3467 srv_put_dos_date2(pdata,8,mtime); /* write time */
3468 SIVAL(pdata,12,(uint32)file_size);
3469 SIVAL(pdata,16,(uint32)allocation_size);
3470 SSVAL(pdata,20,mode);
3471 SIVAL(pdata,22,ea_size);
3472 break;
3475 case SMB_INFO_IS_NAME_VALID:
3476 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3477 if (tran_call == TRANSACT2_QFILEINFO) {
3478 /* os/2 needs this ? really ?*/
3479 return ERROR_DOS(ERRDOS,ERRbadfunc);
3481 data_size = 0;
3482 param_size = 0;
3483 break;
3485 case SMB_INFO_QUERY_EAS_FROM_LIST:
3487 size_t total_ea_len = 0;
3488 struct ea_list *ea_file_list = NULL;
3490 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3492 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3493 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3495 if (!ea_list || (total_ea_len > data_size)) {
3496 talloc_destroy(data_ctx);
3497 data_size = 4;
3498 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3499 break;
3502 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3503 talloc_destroy(data_ctx);
3504 break;
3507 case SMB_INFO_QUERY_ALL_EAS:
3509 /* We have data_size bytes to put EA's into. */
3510 size_t total_ea_len = 0;
3512 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3514 data_ctx = talloc_init("ea_ctx");
3515 if (!data_ctx) {
3516 return ERROR_NT(NT_STATUS_NO_MEMORY);
3519 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3520 if (!ea_list || (total_ea_len > data_size)) {
3521 talloc_destroy(data_ctx);
3522 data_size = 4;
3523 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3524 break;
3527 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3528 talloc_destroy(data_ctx);
3529 break;
3532 case SMB_FILE_BASIC_INFORMATION:
3533 case SMB_QUERY_FILE_BASIC_INFO:
3535 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3536 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3537 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3538 } else {
3539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3540 data_size = 40;
3541 SIVAL(pdata,36,0);
3543 put_long_date_timespec(pdata,create_time_ts);
3544 put_long_date_timespec(pdata+8,atime_ts);
3545 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3546 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3547 SIVAL(pdata,32,mode);
3549 DEBUG(5,("SMB_QFBI - "));
3550 DEBUG(5,("create: %s ", ctime(&create_time)));
3551 DEBUG(5,("access: %s ", ctime(&atime)));
3552 DEBUG(5,("write: %s ", ctime(&mtime)));
3553 DEBUG(5,("change: %s ", ctime(&mtime)));
3554 DEBUG(5,("mode: %x\n", mode));
3555 break;
3557 case SMB_FILE_STANDARD_INFORMATION:
3558 case SMB_QUERY_FILE_STANDARD_INFO:
3560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3561 data_size = 24;
3562 SOFF_T(pdata,0,allocation_size);
3563 SOFF_T(pdata,8,file_size);
3564 SIVAL(pdata,16,nlink);
3565 SCVAL(pdata,20,delete_pending?1:0);
3566 SCVAL(pdata,21,(mode&aDIR)?1:0);
3567 SSVAL(pdata,22,0); /* Padding. */
3568 break;
3570 case SMB_FILE_EA_INFORMATION:
3571 case SMB_QUERY_FILE_EA_INFO:
3573 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3574 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3575 data_size = 4;
3576 SIVAL(pdata,0,ea_size);
3577 break;
3580 /* Get the 8.3 name - used if NT SMB was negotiated. */
3581 case SMB_QUERY_FILE_ALT_NAME_INFO:
3582 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3584 pstring short_name;
3586 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3587 pstrcpy(short_name,base_name);
3588 /* Mangle if not already 8.3 */
3589 if(!mangle_is_8_3(short_name, True, conn->params)) {
3590 mangle_map(short_name,True,True,conn->params);
3592 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3593 data_size = 4 + len;
3594 SIVAL(pdata,0,len);
3595 break;
3598 case SMB_QUERY_FILE_NAME_INFO:
3600 this must be *exactly* right for ACLs on mapped drives to work
3602 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3603 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3604 data_size = 4 + len;
3605 SIVAL(pdata,0,len);
3606 break;
3608 case SMB_FILE_ALLOCATION_INFORMATION:
3609 case SMB_QUERY_FILE_ALLOCATION_INFO:
3610 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3611 data_size = 8;
3612 SOFF_T(pdata,0,allocation_size);
3613 break;
3615 case SMB_FILE_END_OF_FILE_INFORMATION:
3616 case SMB_QUERY_FILE_END_OF_FILEINFO:
3617 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3618 data_size = 8;
3619 SOFF_T(pdata,0,file_size);
3620 break;
3622 case SMB_QUERY_FILE_ALL_INFO:
3623 case SMB_FILE_ALL_INFORMATION:
3625 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3626 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3627 put_long_date_timespec(pdata,create_time_ts);
3628 put_long_date_timespec(pdata+8,atime_ts);
3629 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3630 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3631 SIVAL(pdata,32,mode);
3632 SIVAL(pdata,36,0); /* padding. */
3633 pdata += 40;
3634 SOFF_T(pdata,0,allocation_size);
3635 SOFF_T(pdata,8,file_size);
3636 SIVAL(pdata,16,nlink);
3637 SCVAL(pdata,20,delete_pending);
3638 SCVAL(pdata,21,(mode&aDIR)?1:0);
3639 SSVAL(pdata,22,0);
3640 pdata += 24;
3641 SIVAL(pdata,0,ea_size);
3642 pdata += 4; /* EA info */
3643 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3644 SIVAL(pdata,0,len);
3645 pdata += 4 + len;
3646 data_size = PTR_DIFF(pdata,(*ppdata));
3647 break;
3649 case SMB_FILE_INTERNAL_INFORMATION:
3650 /* This should be an index number - looks like
3651 dev/ino to me :-)
3653 I think this causes us to fail the IFSKIT
3654 BasicFileInformationTest. -tpot */
3656 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3657 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3658 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3659 data_size = 8;
3660 break;
3662 case SMB_FILE_ACCESS_INFORMATION:
3663 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3664 SIVAL(pdata,0,access_mask);
3665 data_size = 4;
3666 break;
3668 case SMB_FILE_NAME_INFORMATION:
3669 /* Pathname with leading '\'. */
3671 size_t byte_len;
3672 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3673 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3674 SIVAL(pdata,0,byte_len);
3675 data_size = 4 + byte_len;
3676 break;
3679 case SMB_FILE_DISPOSITION_INFORMATION:
3680 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3681 data_size = 1;
3682 SCVAL(pdata,0,delete_pending);
3683 break;
3685 case SMB_FILE_POSITION_INFORMATION:
3686 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3687 data_size = 8;
3688 SOFF_T(pdata,0,pos);
3689 break;
3691 case SMB_FILE_MODE_INFORMATION:
3692 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3693 SIVAL(pdata,0,mode);
3694 data_size = 4;
3695 break;
3697 case SMB_FILE_ALIGNMENT_INFORMATION:
3698 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3699 SIVAL(pdata,0,0); /* No alignment needed. */
3700 data_size = 4;
3701 break;
3703 #if 0
3705 * NT4 server just returns "invalid query" to this - if we try to answer
3706 * it then NTws gets a BSOD! (tridge).
3707 * W2K seems to want this. JRA.
3709 case SMB_QUERY_FILE_STREAM_INFO:
3710 #endif
3711 case SMB_FILE_STREAM_INFORMATION:
3712 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3713 if (mode & aDIR) {
3714 data_size = 0;
3715 } else {
3716 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3717 SIVAL(pdata,0,0); /* ??? */
3718 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3719 SOFF_T(pdata,8,file_size);
3720 SOFF_T(pdata,16,allocation_size);
3721 data_size = 24 + byte_len;
3723 break;
3725 case SMB_QUERY_COMPRESSION_INFO:
3726 case SMB_FILE_COMPRESSION_INFORMATION:
3727 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3728 SOFF_T(pdata,0,file_size);
3729 SIVAL(pdata,8,0); /* ??? */
3730 SIVAL(pdata,12,0); /* ??? */
3731 data_size = 16;
3732 break;
3734 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3735 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3736 put_long_date_timespec(pdata,create_time_ts);
3737 put_long_date_timespec(pdata+8,atime_ts);
3738 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3739 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3740 SOFF_T(pdata,32,allocation_size);
3741 SOFF_T(pdata,40,file_size);
3742 SIVAL(pdata,48,mode);
3743 SIVAL(pdata,52,0); /* ??? */
3744 data_size = 56;
3745 break;
3747 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3748 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3749 SIVAL(pdata,0,mode);
3750 SIVAL(pdata,4,0);
3751 data_size = 8;
3752 break;
3755 * CIFS UNIX Extensions.
3758 case SMB_QUERY_FILE_UNIX_BASIC:
3760 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3761 data_size = PTR_DIFF(pdata,(*ppdata));
3764 int i;
3765 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3767 for (i=0; i<100; i++)
3768 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3769 DEBUG(4,("\n"));
3772 break;
3774 case SMB_QUERY_FILE_UNIX_INFO2:
3776 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3777 data_size = PTR_DIFF(pdata,(*ppdata));
3780 int i;
3781 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3783 for (i=0; i<100; i++)
3784 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3785 DEBUG(4,("\n"));
3788 break;
3790 case SMB_QUERY_FILE_UNIX_LINK:
3792 pstring buffer;
3794 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3795 #ifdef S_ISLNK
3796 if(!S_ISLNK(sbuf.st_mode))
3797 return(UNIXERROR(ERRSRV,ERRbadlink));
3798 #else
3799 return(UNIXERROR(ERRDOS,ERRbadlink));
3800 #endif
3801 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3802 if (len == -1)
3803 return(UNIXERROR(ERRDOS,ERRnoaccess));
3804 buffer[len] = 0;
3805 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3806 pdata += len;
3807 data_size = PTR_DIFF(pdata,(*ppdata));
3809 break;
3812 #if defined(HAVE_POSIX_ACLS)
3813 case SMB_QUERY_POSIX_ACL:
3815 SMB_ACL_T file_acl = NULL;
3816 SMB_ACL_T def_acl = NULL;
3817 uint16 num_file_acls = 0;
3818 uint16 num_def_acls = 0;
3820 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3821 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3822 } else {
3823 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3826 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3827 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3828 fname ));
3829 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3832 if (S_ISDIR(sbuf.st_mode)) {
3833 if (fsp && fsp->is_directory) {
3834 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3835 } else {
3836 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3838 def_acl = free_empty_sys_acl(conn, def_acl);
3841 num_file_acls = count_acl_entries(conn, file_acl);
3842 num_def_acls = count_acl_entries(conn, def_acl);
3844 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3845 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3846 data_size,
3847 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3848 SMB_POSIX_ACL_HEADER_SIZE) ));
3849 if (file_acl) {
3850 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3852 if (def_acl) {
3853 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3855 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3858 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3859 SSVAL(pdata,2,num_file_acls);
3860 SSVAL(pdata,4,num_def_acls);
3861 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3862 if (file_acl) {
3863 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3865 if (def_acl) {
3866 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3868 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3870 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3871 if (file_acl) {
3872 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3874 if (def_acl) {
3875 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3877 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3880 if (file_acl) {
3881 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3883 if (def_acl) {
3884 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3886 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3887 break;
3889 #endif
3892 case SMB_QUERY_POSIX_LOCK:
3894 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3895 SMB_BIG_UINT count;
3896 SMB_BIG_UINT offset;
3897 uint32 lock_pid;
3898 enum brl_type lock_type;
3900 if (total_data != POSIX_LOCK_DATA_SIZE) {
3901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3904 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3905 case POSIX_LOCK_TYPE_READ:
3906 lock_type = READ_LOCK;
3907 break;
3908 case POSIX_LOCK_TYPE_WRITE:
3909 lock_type = WRITE_LOCK;
3910 break;
3911 case POSIX_LOCK_TYPE_UNLOCK:
3912 default:
3913 /* There's no point in asking for an unlock... */
3914 talloc_destroy(data_ctx);
3915 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3918 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3919 #if defined(HAVE_LONGLONG)
3920 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3921 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3922 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3923 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3924 #else /* HAVE_LONGLONG */
3925 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3926 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3927 #endif /* HAVE_LONGLONG */
3929 status = query_lock(fsp,
3930 &lock_pid,
3931 &count,
3932 &offset,
3933 &lock_type,
3934 POSIX_LOCK);
3936 if (ERROR_WAS_LOCK_DENIED(status)) {
3937 /* Here we need to report who has it locked... */
3938 data_size = POSIX_LOCK_DATA_SIZE;
3940 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3941 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3942 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3943 #if defined(HAVE_LONGLONG)
3944 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3945 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3946 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3947 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3948 #else /* HAVE_LONGLONG */
3949 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3950 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3951 #endif /* HAVE_LONGLONG */
3953 } else if (NT_STATUS_IS_OK(status)) {
3954 /* For success we just return a copy of what we sent
3955 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3956 data_size = POSIX_LOCK_DATA_SIZE;
3957 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3958 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3959 } else {
3960 return ERROR_NT(status);
3962 break;
3965 default:
3966 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3969 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3971 return(-1);
3974 /****************************************************************************
3975 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3976 code.
3977 ****************************************************************************/
3979 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3981 SMB_STRUCT_STAT sbuf1, sbuf2;
3982 pstring last_component_oldname;
3983 pstring last_component_newname;
3984 NTSTATUS status = NT_STATUS_OK;
3986 ZERO_STRUCT(sbuf1);
3987 ZERO_STRUCT(sbuf2);
3989 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 return status;
3994 status = check_name(conn, oldname);
3995 if (!NT_STATUS_IS_OK(status)) {
3996 return status;
3999 /* source must already exist. */
4000 if (!VALID_STAT(sbuf1)) {
4001 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4004 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4005 if (!NT_STATUS_IS_OK(status)) {
4006 return status;
4009 status = check_name(conn, newname);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 return status;
4014 /* Disallow if newname already exists. */
4015 if (VALID_STAT(sbuf2)) {
4016 return NT_STATUS_OBJECT_NAME_COLLISION;
4019 /* No links from a directory. */
4020 if (S_ISDIR(sbuf1.st_mode)) {
4021 return NT_STATUS_FILE_IS_A_DIRECTORY;
4024 /* Ensure this is within the share. */
4025 status = reduce_name(conn, oldname);
4026 if (!NT_STATUS_IS_OK(status)) {
4027 return status;
4030 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4032 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4033 status = map_nt_error_from_unix(errno);
4034 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4035 nt_errstr(status), newname, oldname));
4038 return status;
4041 /****************************************************************************
4042 Deal with setting the time from any of the setfilepathinfo functions.
4043 ****************************************************************************/
4045 static NTSTATUS smb_set_file_time(connection_struct *conn,
4046 files_struct *fsp,
4047 const char *fname,
4048 const SMB_STRUCT_STAT *psbuf,
4049 struct timespec ts[2])
4051 uint32 action =
4052 FILE_NOTIFY_CHANGE_LAST_ACCESS
4053 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4056 if (!VALID_STAT(*psbuf)) {
4057 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4060 /* get some defaults (no modifications) if any info is zero or -1. */
4061 if (null_timespec(ts[0])) {
4062 ts[0] = get_atimespec(psbuf);
4063 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4066 if (null_timespec(ts[1])) {
4067 ts[1] = get_mtimespec(psbuf);
4068 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4071 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4072 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4075 * Try and set the times of this file if
4076 * they are different from the current values.
4080 struct timespec mts = get_mtimespec(psbuf);
4081 struct timespec ats = get_atimespec(psbuf);
4082 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4083 return NT_STATUS_OK;
4087 if(fsp != NULL) {
4089 * This was a setfileinfo on an open file.
4090 * NT does this a lot. We also need to
4091 * set the time here, as it can be read by
4092 * FindFirst/FindNext and with the patch for bug #2045
4093 * in smbd/fileio.c it ensures that this timestamp is
4094 * kept sticky even after a write. We save the request
4095 * away and will set it on file close and after a write. JRA.
4098 if (!null_timespec(ts[1])) {
4099 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4100 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4101 fsp_set_pending_modtime(fsp, ts[1]);
4105 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4107 if(file_ntimes(conn, fname, ts)!=0) {
4108 return map_nt_error_from_unix(errno);
4110 if (action != 0) {
4111 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4113 return NT_STATUS_OK;
4116 /****************************************************************************
4117 Deal with setting the dosmode from any of the setfilepathinfo functions.
4118 ****************************************************************************/
4120 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4121 const char *fname,
4122 SMB_STRUCT_STAT *psbuf,
4123 uint32 dosmode)
4125 if (!VALID_STAT(*psbuf)) {
4126 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4129 if (dosmode) {
4130 if (S_ISDIR(psbuf->st_mode)) {
4131 dosmode |= aDIR;
4132 } else {
4133 dosmode &= ~aDIR;
4137 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4139 /* check the mode isn't different, before changing it */
4140 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4142 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4143 fname, (unsigned int)dosmode ));
4145 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4146 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4147 fname, strerror(errno)));
4148 return map_nt_error_from_unix(errno);
4151 return NT_STATUS_OK;
4154 /****************************************************************************
4155 Deal with setting the size from any of the setfilepathinfo functions.
4156 ****************************************************************************/
4158 static NTSTATUS smb_set_file_size(connection_struct *conn,
4159 files_struct *fsp,
4160 const char *fname,
4161 SMB_STRUCT_STAT *psbuf,
4162 SMB_OFF_T size)
4164 NTSTATUS status = NT_STATUS_OK;
4165 files_struct *new_fsp = NULL;
4167 if (!VALID_STAT(*psbuf)) {
4168 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4171 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4173 if (size == get_file_size(*psbuf)) {
4174 return NT_STATUS_OK;
4177 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4178 fname, (double)size ));
4180 if (fsp && fsp->fh->fd != -1) {
4181 /* Handle based call. */
4182 if (vfs_set_filelen(fsp, size) == -1) {
4183 return map_nt_error_from_unix(errno);
4185 return NT_STATUS_OK;
4188 status = open_file_ntcreate(conn, fname, psbuf,
4189 FILE_WRITE_DATA,
4190 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4191 FILE_OPEN,
4193 FILE_ATTRIBUTE_NORMAL,
4194 FORCE_OPLOCK_BREAK_TO_NONE,
4195 NULL, &new_fsp);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 /* NB. We check for open_was_deferred in the caller. */
4199 return status;
4202 if (vfs_set_filelen(new_fsp, size) == -1) {
4203 status = map_nt_error_from_unix(errno);
4204 close_file(new_fsp,NORMAL_CLOSE);
4205 return status;
4208 close_file(new_fsp,NORMAL_CLOSE);
4209 return NT_STATUS_OK;
4212 /****************************************************************************
4213 Deal with SMB_INFO_SET_EA.
4214 ****************************************************************************/
4216 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4217 const char *pdata,
4218 int total_data,
4219 files_struct *fsp,
4220 const char *fname)
4222 struct ea_list *ea_list = NULL;
4223 TALLOC_CTX *ctx = NULL;
4224 NTSTATUS status = NT_STATUS_OK;
4226 if (total_data < 10) {
4228 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4229 length. They seem to have no effect. Bug #3212. JRA */
4231 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4232 /* We're done. We only get EA info in this call. */
4233 return NT_STATUS_OK;
4236 return NT_STATUS_INVALID_PARAMETER;
4239 if (IVAL(pdata,0) > total_data) {
4240 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4241 IVAL(pdata,0), (unsigned int)total_data));
4242 return NT_STATUS_INVALID_PARAMETER;
4245 ctx = talloc_init("SMB_INFO_SET_EA");
4246 if (!ctx) {
4247 return NT_STATUS_NO_MEMORY;
4249 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4250 if (!ea_list) {
4251 talloc_destroy(ctx);
4252 return NT_STATUS_INVALID_PARAMETER;
4254 status = set_ea(conn, fsp, fname, ea_list);
4255 talloc_destroy(ctx);
4257 return status;
4260 /****************************************************************************
4261 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4262 ****************************************************************************/
4264 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4265 const char *pdata,
4266 int total_data,
4267 files_struct *fsp,
4268 const char *fname,
4269 SMB_STRUCT_STAT *psbuf)
4271 NTSTATUS status = NT_STATUS_OK;
4272 BOOL delete_on_close;
4273 uint32 dosmode = 0;
4275 if (total_data < 1) {
4276 return NT_STATUS_INVALID_PARAMETER;
4279 if (fsp == NULL) {
4280 return NT_STATUS_INVALID_HANDLE;
4283 delete_on_close = (CVAL(pdata,0) ? True : False);
4284 dosmode = dos_mode(conn, fname, psbuf);
4286 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4287 "delete_on_close = %u\n",
4288 fsp->fsp_name,
4289 (unsigned int)dosmode,
4290 (unsigned int)delete_on_close ));
4292 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4294 if (!NT_STATUS_IS_OK(status)) {
4295 return status;
4298 /* The set is across all open files on this dev/inode pair. */
4299 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4300 return NT_STATUS_ACCESS_DENIED;
4302 return NT_STATUS_OK;
4305 /****************************************************************************
4306 Deal with SMB_FILE_POSITION_INFORMATION.
4307 ****************************************************************************/
4309 static NTSTATUS smb_file_position_information(connection_struct *conn,
4310 const char *pdata,
4311 int total_data,
4312 files_struct *fsp)
4314 SMB_BIG_UINT position_information;
4316 if (total_data < 8) {
4317 return NT_STATUS_INVALID_PARAMETER;
4320 if (fsp == NULL) {
4321 /* Ignore on pathname based set. */
4322 return NT_STATUS_OK;
4325 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4326 #ifdef LARGE_SMB_OFF_T
4327 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4328 #else /* LARGE_SMB_OFF_T */
4329 if (IVAL(pdata,4) != 0) {
4330 /* more than 32 bits? */
4331 return NT_STATUS_INVALID_PARAMETER;
4333 #endif /* LARGE_SMB_OFF_T */
4335 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4336 fsp->fsp_name, (double)position_information ));
4337 fsp->fh->position_information = position_information;
4338 return NT_STATUS_OK;
4341 /****************************************************************************
4342 Deal with SMB_FILE_MODE_INFORMATION.
4343 ****************************************************************************/
4345 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4346 const char *pdata,
4347 int total_data)
4349 uint32 mode;
4351 if (total_data < 4) {
4352 return NT_STATUS_INVALID_PARAMETER;
4354 mode = IVAL(pdata,0);
4355 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4356 return NT_STATUS_INVALID_PARAMETER;
4358 return NT_STATUS_OK;
4361 /****************************************************************************
4362 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4363 ****************************************************************************/
4365 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4366 char *inbuf,
4367 const char *pdata,
4368 int total_data,
4369 const char *fname)
4371 pstring link_target;
4372 const char *newname = fname;
4373 NTSTATUS status = NT_STATUS_OK;
4375 /* Set a symbolic link. */
4376 /* Don't allow this if follow links is false. */
4378 if (total_data == 0) {
4379 return NT_STATUS_INVALID_PARAMETER;
4382 if (!lp_symlinks(SNUM(conn))) {
4383 return NT_STATUS_ACCESS_DENIED;
4386 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4388 /* !widelinks forces the target path to be within the share. */
4389 /* This means we can interpret the target as a pathname. */
4390 if (!lp_widelinks(SNUM(conn))) {
4391 pstring rel_name;
4392 char *last_dirp = NULL;
4394 if (*link_target == '/') {
4395 /* No absolute paths allowed. */
4396 return NT_STATUS_ACCESS_DENIED;
4398 pstrcpy(rel_name, newname);
4399 last_dirp = strrchr_m(rel_name, '/');
4400 if (last_dirp) {
4401 last_dirp[1] = '\0';
4402 } else {
4403 pstrcpy(rel_name, "./");
4405 pstrcat(rel_name, link_target);
4407 status = check_name(conn, rel_name);
4408 if (!NT_STATUS_IS_OK(status)) {
4409 return status;
4413 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4414 newname, link_target ));
4416 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4417 return map_nt_error_from_unix(errno);
4420 return NT_STATUS_OK;
4423 /****************************************************************************
4424 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4425 ****************************************************************************/
4427 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4428 char *inbuf,
4429 char *outbuf,
4430 const char *pdata,
4431 int total_data,
4432 pstring fname)
4434 pstring oldname;
4435 NTSTATUS status = NT_STATUS_OK;
4437 /* Set a hard link. */
4438 if (total_data == 0) {
4439 return NT_STATUS_INVALID_PARAMETER;
4442 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 return status;
4447 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 return status;
4452 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4453 fname, oldname));
4455 return hardlink_internals(conn, oldname, fname);
4458 /****************************************************************************
4459 Deal with SMB_FILE_RENAME_INFORMATION.
4460 ****************************************************************************/
4462 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4463 char *inbuf,
4464 char *outbuf,
4465 const char *pdata,
4466 int total_data,
4467 files_struct *fsp,
4468 pstring fname)
4470 BOOL overwrite;
4471 /* uint32 root_fid; */ /* Not used */
4472 uint32 len;
4473 pstring newname;
4474 pstring base_name;
4475 BOOL dest_has_wcard = False;
4476 NTSTATUS status = NT_STATUS_OK;
4477 char *p;
4479 if (total_data < 13) {
4480 return NT_STATUS_INVALID_PARAMETER;
4483 overwrite = (CVAL(pdata,0) ? True : False);
4484 /* root_fid = IVAL(pdata,4); */
4485 len = IVAL(pdata,8);
4487 if (len > (total_data - 12) || (len == 0)) {
4488 return NT_STATUS_INVALID_PARAMETER;
4491 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4492 if (!NT_STATUS_IS_OK(status)) {
4493 return status;
4496 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4497 if (!NT_STATUS_IS_OK(status)) {
4498 return status;
4501 /* Check the new name has no '/' characters. */
4502 if (strchr_m(newname, '/')) {
4503 return NT_STATUS_NOT_SUPPORTED;
4506 /* Create the base directory. */
4507 pstrcpy(base_name, fname);
4508 p = strrchr_m(base_name, '/');
4509 if (p) {
4510 p[1] = '\0';
4511 } else {
4512 pstrcpy(base_name, "./");
4514 /* Append the new name. */
4515 pstrcat(base_name, newname);
4517 if (fsp) {
4518 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4519 fsp->fnum, fsp->fsp_name, base_name ));
4520 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4521 } else {
4522 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4523 fname, newname ));
4524 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4527 return status;
4530 /****************************************************************************
4531 Deal with SMB_SET_POSIX_ACL.
4532 ****************************************************************************/
4534 #if defined(HAVE_POSIX_ACLS)
4535 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4536 const char *pdata,
4537 int total_data,
4538 files_struct *fsp,
4539 const char *fname,
4540 SMB_STRUCT_STAT *psbuf)
4542 uint16 posix_acl_version;
4543 uint16 num_file_acls;
4544 uint16 num_def_acls;
4545 BOOL valid_file_acls = True;
4546 BOOL valid_def_acls = True;
4548 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4549 return NT_STATUS_INVALID_PARAMETER;
4551 posix_acl_version = SVAL(pdata,0);
4552 num_file_acls = SVAL(pdata,2);
4553 num_def_acls = SVAL(pdata,4);
4555 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4556 valid_file_acls = False;
4557 num_file_acls = 0;
4560 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4561 valid_def_acls = False;
4562 num_def_acls = 0;
4565 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4566 return NT_STATUS_INVALID_PARAMETER;
4569 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4570 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4571 return NT_STATUS_INVALID_PARAMETER;
4574 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4575 fname ? fname : fsp->fsp_name,
4576 (unsigned int)num_file_acls,
4577 (unsigned int)num_def_acls));
4579 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4580 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4581 return map_nt_error_from_unix(errno);
4584 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4585 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4586 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4587 return map_nt_error_from_unix(errno);
4589 return NT_STATUS_OK;
4591 #endif
4593 /****************************************************************************
4594 Deal with SMB_SET_POSIX_LOCK.
4595 ****************************************************************************/
4597 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4598 char *inbuf,
4599 int length,
4600 const char *pdata,
4601 int total_data,
4602 files_struct *fsp)
4604 SMB_BIG_UINT count;
4605 SMB_BIG_UINT offset;
4606 uint32 lock_pid;
4607 BOOL blocking_lock = False;
4608 enum brl_type lock_type;
4609 NTSTATUS status = NT_STATUS_OK;
4611 if (fsp == NULL || fsp->fh->fd == -1) {
4612 return NT_STATUS_INVALID_HANDLE;
4615 if (total_data != POSIX_LOCK_DATA_SIZE) {
4616 return NT_STATUS_INVALID_PARAMETER;
4619 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4620 case POSIX_LOCK_TYPE_READ:
4621 lock_type = READ_LOCK;
4622 break;
4623 case POSIX_LOCK_TYPE_WRITE:
4624 /* Return the right POSIX-mappable error code for files opened read-only. */
4625 if (!fsp->can_write) {
4626 return NT_STATUS_INVALID_HANDLE;
4628 lock_type = WRITE_LOCK;
4629 break;
4630 case POSIX_LOCK_TYPE_UNLOCK:
4631 lock_type = UNLOCK_LOCK;
4632 break;
4633 default:
4634 return NT_STATUS_INVALID_PARAMETER;
4637 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4638 blocking_lock = False;
4639 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4640 blocking_lock = True;
4641 } else {
4642 return NT_STATUS_INVALID_PARAMETER;
4645 if (!lp_blocking_locks(SNUM(conn))) {
4646 blocking_lock = False;
4649 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4650 #if defined(HAVE_LONGLONG)
4651 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4652 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4653 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4654 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4655 #else /* HAVE_LONGLONG */
4656 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4657 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4658 #endif /* HAVE_LONGLONG */
4660 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4661 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4662 fsp->fsp_name,
4663 (unsigned int)lock_type,
4664 (unsigned int)lock_pid,
4665 (double)count,
4666 (double)offset ));
4668 if (lock_type == UNLOCK_LOCK) {
4669 status = do_unlock(fsp,
4670 lock_pid,
4671 count,
4672 offset,
4673 POSIX_LOCK);
4674 } else {
4675 uint32 block_smbpid;
4677 struct byte_range_lock *br_lck = do_lock(fsp,
4678 lock_pid,
4679 count,
4680 offset,
4681 lock_type,
4682 POSIX_LOCK,
4683 blocking_lock,
4684 &status,
4685 &block_smbpid);
4687 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4689 * A blocking lock was requested. Package up
4690 * this smb into a queued request and push it
4691 * onto the blocking lock queue.
4693 if(push_blocking_lock_request(br_lck,
4694 inbuf, length,
4695 fsp,
4696 -1, /* infinite timeout. */
4698 lock_pid,
4699 lock_type,
4700 POSIX_LOCK,
4701 offset,
4702 count,
4703 block_smbpid)) {
4704 TALLOC_FREE(br_lck);
4705 return status;
4708 TALLOC_FREE(br_lck);
4711 return status;
4714 /****************************************************************************
4715 Deal with SMB_INFO_STANDARD.
4716 ****************************************************************************/
4718 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4719 const char *pdata,
4720 int total_data,
4721 files_struct *fsp,
4722 const char *fname,
4723 const SMB_STRUCT_STAT *psbuf)
4725 struct timespec ts[2];
4727 if (total_data < 12) {
4728 return NT_STATUS_INVALID_PARAMETER;
4731 /* access time */
4732 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4733 /* write time */
4734 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4736 DEBUG(10,("smb_set_info_standard: file %s\n",
4737 fname ? fname : fsp->fsp_name ));
4739 return smb_set_file_time(conn,
4740 fsp,
4741 fname,
4742 psbuf,
4743 ts);
4746 /****************************************************************************
4747 Deal with SMB_SET_FILE_BASIC_INFO.
4748 ****************************************************************************/
4750 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4751 const char *pdata,
4752 int total_data,
4753 files_struct *fsp,
4754 const char *fname,
4755 SMB_STRUCT_STAT *psbuf)
4757 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4758 struct timespec write_time;
4759 struct timespec changed_time;
4760 uint32 dosmode = 0;
4761 struct timespec ts[2];
4762 NTSTATUS status = NT_STATUS_OK;
4764 if (total_data < 36) {
4765 return NT_STATUS_INVALID_PARAMETER;
4768 /* Set the attributes */
4769 dosmode = IVAL(pdata,32);
4770 status = smb_set_file_dosmode(conn,
4771 fname,
4772 psbuf,
4773 dosmode);
4774 if (!NT_STATUS_IS_OK(status)) {
4775 return status;
4778 /* Ignore create time at offset pdata. */
4780 /* access time */
4781 ts[0] = interpret_long_date(pdata+8);
4783 write_time = interpret_long_date(pdata+16);
4784 changed_time = interpret_long_date(pdata+24);
4786 /* mtime */
4787 ts[1] = timespec_min(&write_time, &changed_time);
4789 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4790 ts[1] = write_time;
4793 /* Prefer a defined time to an undefined one. */
4794 if (null_timespec(ts[1])) {
4795 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4798 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4799 fname ? fname : fsp->fsp_name ));
4801 return smb_set_file_time(conn,
4802 fsp,
4803 fname,
4804 psbuf,
4805 ts);
4808 /****************************************************************************
4809 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4810 ****************************************************************************/
4812 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4813 const char *pdata,
4814 int total_data,
4815 files_struct *fsp,
4816 const char *fname,
4817 SMB_STRUCT_STAT *psbuf)
4819 SMB_BIG_UINT allocation_size = 0;
4820 NTSTATUS status = NT_STATUS_OK;
4821 files_struct *new_fsp = NULL;
4823 if (!VALID_STAT(*psbuf)) {
4824 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4827 if (total_data < 8) {
4828 return NT_STATUS_INVALID_PARAMETER;
4831 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4832 #ifdef LARGE_SMB_OFF_T
4833 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4834 #else /* LARGE_SMB_OFF_T */
4835 if (IVAL(pdata,4) != 0) {
4836 /* more than 32 bits? */
4837 return NT_STATUS_INVALID_PARAMETER;
4839 #endif /* LARGE_SMB_OFF_T */
4841 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4842 fname, (double)allocation_size ));
4844 if (allocation_size) {
4845 allocation_size = smb_roundup(conn, allocation_size);
4848 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4849 fname, (double)allocation_size ));
4851 if (fsp && fsp->fh->fd != -1) {
4852 /* Open file handle. */
4853 /* Only change if needed. */
4854 if (allocation_size != get_file_size(*psbuf)) {
4855 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4856 return map_nt_error_from_unix(errno);
4859 /* But always update the time. */
4860 if (null_timespec(fsp->pending_modtime)) {
4862 * This is equivalent to a write. Ensure it's seen immediately
4863 * if there are no pending writes.
4865 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
4867 return NT_STATUS_OK;
4870 /* Pathname or stat or directory file. */
4872 status = open_file_ntcreate(conn, fname, psbuf,
4873 FILE_WRITE_DATA,
4874 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4875 FILE_OPEN,
4877 FILE_ATTRIBUTE_NORMAL,
4878 FORCE_OPLOCK_BREAK_TO_NONE,
4879 NULL, &new_fsp);
4881 if (!NT_STATUS_IS_OK(status)) {
4882 /* NB. We check for open_was_deferred in the caller. */
4883 return status;
4886 /* Only change if needed. */
4887 if (allocation_size != get_file_size(*psbuf)) {
4888 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4889 status = map_nt_error_from_unix(errno);
4890 close_file(new_fsp,NORMAL_CLOSE);
4891 return status;
4895 /* Changing the allocation size should set the last mod time. */
4896 /* Don't need to call set_filetime as this will be flushed on
4897 * close. */
4899 fsp_set_pending_modtime(new_fsp, timespec_current());
4901 close_file(new_fsp,NORMAL_CLOSE);
4902 return NT_STATUS_OK;
4905 /****************************************************************************
4906 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4907 ****************************************************************************/
4909 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4910 const char *pdata,
4911 int total_data,
4912 files_struct *fsp,
4913 const char *fname,
4914 SMB_STRUCT_STAT *psbuf)
4916 SMB_OFF_T size;
4918 if (total_data < 8) {
4919 return NT_STATUS_INVALID_PARAMETER;
4922 size = IVAL(pdata,0);
4923 #ifdef LARGE_SMB_OFF_T
4924 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4925 #else /* LARGE_SMB_OFF_T */
4926 if (IVAL(pdata,4) != 0) {
4927 /* more than 32 bits? */
4928 return NT_STATUS_INVALID_PARAMETER;
4930 #endif /* LARGE_SMB_OFF_T */
4931 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4932 "file %s to %.0f\n", fname, (double)size ));
4934 return smb_set_file_size(conn,
4935 fsp,
4936 fname,
4937 psbuf,
4938 size);
4941 /****************************************************************************
4942 Allow a UNIX info mknod.
4943 ****************************************************************************/
4945 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4946 const char *pdata,
4947 int total_data,
4948 const char *fname,
4949 SMB_STRUCT_STAT *psbuf)
4951 uint32 file_type = IVAL(pdata,56);
4952 #if defined(HAVE_MAKEDEV)
4953 uint32 dev_major = IVAL(pdata,60);
4954 uint32 dev_minor = IVAL(pdata,68);
4955 #endif
4956 SMB_DEV_T dev = (SMB_DEV_T)0;
4957 uint32 raw_unixmode = IVAL(pdata,84);
4958 NTSTATUS status;
4959 mode_t unixmode;
4961 if (total_data < 100) {
4962 return NT_STATUS_INVALID_PARAMETER;
4965 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4966 if (!NT_STATUS_IS_OK(status)) {
4967 return status;
4970 #if defined(HAVE_MAKEDEV)
4971 dev = makedev(dev_major, dev_minor);
4972 #endif
4974 switch (file_type) {
4975 #if defined(S_IFIFO)
4976 case UNIX_TYPE_FIFO:
4977 unixmode |= S_IFIFO;
4978 break;
4979 #endif
4980 #if defined(S_IFSOCK)
4981 case UNIX_TYPE_SOCKET:
4982 unixmode |= S_IFSOCK;
4983 break;
4984 #endif
4985 #if defined(S_IFCHR)
4986 case UNIX_TYPE_CHARDEV:
4987 unixmode |= S_IFCHR;
4988 break;
4989 #endif
4990 #if defined(S_IFBLK)
4991 case UNIX_TYPE_BLKDEV:
4992 unixmode |= S_IFBLK;
4993 break;
4994 #endif
4995 default:
4996 return NT_STATUS_INVALID_PARAMETER;
4999 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5000 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5002 /* Ok - do the mknod. */
5003 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5004 return map_nt_error_from_unix(errno);
5007 /* If any of the other "set" calls fail we
5008 * don't want to end up with a half-constructed mknod.
5011 if (lp_inherit_perms(SNUM(conn))) {
5012 inherit_access_acl(
5013 conn, parent_dirname(fname),
5014 fname, unixmode);
5017 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5018 status = map_nt_error_from_unix(errno);
5019 SMB_VFS_UNLINK(conn,fname);
5020 return status;
5022 return NT_STATUS_OK;
5025 /****************************************************************************
5026 Deal with SMB_SET_FILE_UNIX_BASIC.
5027 ****************************************************************************/
5029 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5030 const char *pdata,
5031 int total_data,
5032 files_struct *fsp,
5033 const char *fname,
5034 SMB_STRUCT_STAT *psbuf)
5036 struct timespec ts[2];
5037 uint32 raw_unixmode;
5038 mode_t unixmode;
5039 SMB_OFF_T size = 0;
5040 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5041 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5042 NTSTATUS status = NT_STATUS_OK;
5043 BOOL delete_on_fail = False;
5044 enum perm_type ptype;
5046 if (total_data < 100) {
5047 return NT_STATUS_INVALID_PARAMETER;
5050 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5051 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5052 size=IVAL(pdata,0); /* first 8 Bytes are size */
5053 #ifdef LARGE_SMB_OFF_T
5054 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5055 #else /* LARGE_SMB_OFF_T */
5056 if (IVAL(pdata,4) != 0) {
5057 /* more than 32 bits? */
5058 return NT_STATUS_INVALID_PARAMETER;
5060 #endif /* LARGE_SMB_OFF_T */
5063 ts[0] = interpret_long_date(pdata+24); /* access_time */
5064 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5065 set_owner = (uid_t)IVAL(pdata,40);
5066 set_grp = (gid_t)IVAL(pdata,48);
5067 raw_unixmode = IVAL(pdata,84);
5069 if (VALID_STAT(*psbuf)) {
5070 if (S_ISDIR(psbuf->st_mode)) {
5071 ptype = PERM_EXISTING_DIR;
5072 } else {
5073 ptype = PERM_EXISTING_FILE;
5075 } else {
5076 ptype = PERM_NEW_FILE;
5079 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5080 if (!NT_STATUS_IS_OK(status)) {
5081 return status;
5084 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5085 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5086 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5088 if (!VALID_STAT(*psbuf)) {
5090 * The only valid use of this is to create character and block
5091 * devices, and named pipes. This is deprecated (IMHO) and
5092 * a new info level should be used for mknod. JRA.
5095 status = smb_unix_mknod(conn,
5096 pdata,
5097 total_data,
5098 fname,
5099 psbuf);
5100 if (!NT_STATUS_IS_OK(status)) {
5101 return status;
5104 /* Ensure we don't try and change anything else. */
5105 raw_unixmode = SMB_MODE_NO_CHANGE;
5106 size = get_file_size(*psbuf);
5107 ts[0] = get_atimespec(psbuf);
5108 ts[1] = get_mtimespec(psbuf);
5110 * We continue here as we might want to change the
5111 * owner uid/gid.
5113 delete_on_fail = True;
5116 #if 1
5117 /* Horrible backwards compatibility hack as an old server bug
5118 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5119 * */
5121 if (!size) {
5122 size = get_file_size(*psbuf);
5124 #endif
5127 * Deal with the UNIX specific mode set.
5130 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5131 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5132 (unsigned int)unixmode, fname ));
5133 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5134 return map_nt_error_from_unix(errno);
5139 * Deal with the UNIX specific uid set.
5142 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5143 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5144 (unsigned int)set_owner, fname ));
5145 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5146 status = map_nt_error_from_unix(errno);
5147 if (delete_on_fail) {
5148 SMB_VFS_UNLINK(conn,fname);
5150 return status;
5155 * Deal with the UNIX specific gid set.
5158 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5159 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5160 (unsigned int)set_owner, fname ));
5161 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5162 status = map_nt_error_from_unix(errno);
5163 if (delete_on_fail) {
5164 SMB_VFS_UNLINK(conn,fname);
5166 return status;
5170 /* Deal with any size changes. */
5172 status = smb_set_file_size(conn,
5173 fsp,
5174 fname,
5175 psbuf,
5176 size);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 return status;
5181 /* Deal with any time changes. */
5183 return smb_set_file_time(conn,
5184 fsp,
5185 fname,
5186 psbuf,
5187 ts);
5190 /****************************************************************************
5191 Deal with SMB_SET_FILE_UNIX_INFO2.
5192 ****************************************************************************/
5194 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5195 const char *pdata,
5196 int total_data,
5197 files_struct *fsp,
5198 const char *fname,
5199 SMB_STRUCT_STAT *psbuf)
5201 NTSTATUS status;
5202 uint32 smb_fflags;
5203 uint32 smb_fmask;
5205 if (total_data < 116) {
5206 return NT_STATUS_INVALID_PARAMETER;
5209 /* Start by setting all the fields that are common between UNIX_BASIC
5210 * and UNIX_INFO2.
5212 status = smb_set_file_unix_basic(conn, pdata, total_data,
5213 fsp, fname, psbuf);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 return status;
5218 smb_fflags = IVAL(pdata, 108);
5219 smb_fmask = IVAL(pdata, 112);
5221 /* NB: We should only attempt to alter the file flags if the client
5222 * sends a non-zero mask.
5224 if (smb_fmask != 0) {
5225 int stat_fflags = 0;
5227 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5228 &stat_fflags)) {
5229 /* Client asked to alter a flag we don't understand. */
5230 return NT_STATUS_INVALID_PARAMETER;
5233 if (fsp && fsp->fh->fd != -1) {
5234 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5235 return NT_STATUS_NOT_SUPPORTED;
5236 } else {
5237 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5238 return map_nt_error_from_unix(errno);
5243 /* XXX: need to add support for changing the create_time here. You
5244 * can do this for paths on Darwin with setattrlist(2). The right way
5245 * to hook this up is probably by extending the VFS utimes interface.
5248 return NT_STATUS_OK;
5251 /****************************************************************************
5252 Create a directory with POSIX semantics.
5253 ****************************************************************************/
5255 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5256 char **ppdata,
5257 int total_data,
5258 const char *fname,
5259 SMB_STRUCT_STAT *psbuf,
5260 int *pdata_return_size)
5262 NTSTATUS status = NT_STATUS_OK;
5263 uint32 raw_unixmode = 0;
5264 uint32 mod_unixmode = 0;
5265 mode_t unixmode = (mode_t)0;
5266 files_struct *fsp = NULL;
5267 uint16 info_level_return = 0;
5268 int info;
5269 char *pdata = *ppdata;
5271 if (total_data < 18) {
5272 return NT_STATUS_INVALID_PARAMETER;
5275 raw_unixmode = IVAL(pdata,8);
5276 /* Next 4 bytes are not yet defined. */
5278 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5279 if (!NT_STATUS_IS_OK(status)) {
5280 return status;
5283 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5285 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5286 fname, (unsigned int)unixmode ));
5288 status = open_directory(conn,
5289 fname,
5290 psbuf,
5291 FILE_READ_ATTRIBUTES, /* Just a stat open */
5292 FILE_SHARE_NONE, /* Ignored for stat opens */
5293 FILE_CREATE,
5295 mod_unixmode,
5296 &info,
5297 &fsp);
5299 if (NT_STATUS_IS_OK(status)) {
5300 close_file(fsp, NORMAL_CLOSE);
5303 info_level_return = SVAL(pdata,16);
5305 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5306 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5307 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5308 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5309 } else {
5310 *pdata_return_size = 12;
5313 /* Realloc the data size */
5314 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5315 if (*ppdata == NULL) {
5316 *pdata_return_size = 0;
5317 return NT_STATUS_NO_MEMORY;
5319 pdata = *ppdata;
5321 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5322 SSVAL(pdata,2,0); /* No fnum. */
5323 SIVAL(pdata,4,info); /* Was directory created. */
5325 switch (info_level_return) {
5326 case SMB_QUERY_FILE_UNIX_BASIC:
5327 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5328 SSVAL(pdata,10,0); /* Padding. */
5329 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5330 break;
5331 case SMB_QUERY_FILE_UNIX_INFO2:
5332 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5333 SSVAL(pdata,10,0); /* Padding. */
5334 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5335 break;
5336 default:
5337 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5338 SSVAL(pdata,10,0); /* Padding. */
5339 break;
5342 return status;
5345 /****************************************************************************
5346 Open/Create a file with POSIX semantics.
5347 ****************************************************************************/
5349 static NTSTATUS smb_posix_open(connection_struct *conn,
5350 char **ppdata,
5351 int total_data,
5352 const char *fname,
5353 SMB_STRUCT_STAT *psbuf,
5354 int *pdata_return_size)
5356 BOOL extended_oplock_granted = False;
5357 char *pdata = *ppdata;
5358 uint32 flags = 0;
5359 uint32 wire_open_mode = 0;
5360 uint32 raw_unixmode = 0;
5361 uint32 mod_unixmode = 0;
5362 uint32 create_disp = 0;
5363 uint32 access_mask = 0;
5364 uint32 create_options = 0;
5365 NTSTATUS status = NT_STATUS_OK;
5366 mode_t unixmode = (mode_t)0;
5367 files_struct *fsp = NULL;
5368 int oplock_request = 0;
5369 int info = 0;
5370 uint16 info_level_return = 0;
5372 if (total_data < 18) {
5373 return NT_STATUS_INVALID_PARAMETER;
5376 flags = IVAL(pdata,0);
5377 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5378 if (oplock_request) {
5379 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5382 wire_open_mode = IVAL(pdata,4);
5384 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5385 return smb_posix_mkdir(conn,
5386 ppdata,
5387 total_data,
5388 fname,
5389 psbuf,
5390 pdata_return_size);
5393 switch (wire_open_mode & SMB_ACCMODE) {
5394 case SMB_O_RDONLY:
5395 access_mask = FILE_READ_DATA;
5396 break;
5397 case SMB_O_WRONLY:
5398 access_mask = FILE_WRITE_DATA;
5399 break;
5400 case SMB_O_RDWR:
5401 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5402 break;
5403 default:
5404 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5405 (unsigned int)wire_open_mode ));
5406 return NT_STATUS_INVALID_PARAMETER;
5409 wire_open_mode &= ~SMB_ACCMODE;
5411 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5412 create_disp = FILE_CREATE;
5413 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5414 create_disp = FILE_OVERWRITE_IF;
5415 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5416 create_disp = FILE_OPEN_IF;
5417 } else {
5418 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5419 (unsigned int)wire_open_mode ));
5420 return NT_STATUS_INVALID_PARAMETER;
5423 raw_unixmode = IVAL(pdata,8);
5424 /* Next 4 bytes are not yet defined. */
5426 status = unix_perms_from_wire(conn,
5427 psbuf,
5428 raw_unixmode,
5429 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5430 &unixmode);
5432 if (!NT_STATUS_IS_OK(status)) {
5433 return status;
5436 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5438 if (wire_open_mode & SMB_O_SYNC) {
5439 create_options |= FILE_WRITE_THROUGH;
5441 if (wire_open_mode & SMB_O_APPEND) {
5442 access_mask |= FILE_APPEND_DATA;
5444 if (wire_open_mode & SMB_O_DIRECT) {
5445 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5448 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5449 fname,
5450 (unsigned int)wire_open_mode,
5451 (unsigned int)unixmode ));
5453 status = open_file_ntcreate(conn,
5454 fname,
5455 psbuf,
5456 access_mask,
5457 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5458 create_disp,
5459 0, /* no create options yet. */
5460 mod_unixmode,
5461 oplock_request,
5462 &info,
5463 &fsp);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 return status;
5469 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5470 extended_oplock_granted = True;
5473 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5474 extended_oplock_granted = True;
5477 info_level_return = SVAL(pdata,16);
5479 /* Allocate the correct return size. */
5481 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5482 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5483 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5484 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5485 } else {
5486 *pdata_return_size = 12;
5489 /* Realloc the data size */
5490 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5491 if (*ppdata == NULL) {
5492 close_file(fsp,ERROR_CLOSE);
5493 *pdata_return_size = 0;
5494 return NT_STATUS_NO_MEMORY;
5496 pdata = *ppdata;
5498 if (extended_oplock_granted) {
5499 if (flags & REQUEST_BATCH_OPLOCK) {
5500 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5501 } else {
5502 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5504 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5505 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5506 } else {
5507 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5510 SSVAL(pdata,2,fsp->fnum);
5511 SIVAL(pdata,4,info); /* Was file created etc. */
5513 switch (info_level_return) {
5514 case SMB_QUERY_FILE_UNIX_BASIC:
5515 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5516 SSVAL(pdata,10,0); /* padding. */
5517 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5518 break;
5519 case SMB_QUERY_FILE_UNIX_INFO2:
5520 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5521 SSVAL(pdata,10,0); /* padding. */
5522 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5523 break;
5524 default:
5525 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5526 SSVAL(pdata,10,0); /* padding. */
5527 break;
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Delete a file with POSIX semantics.
5534 ****************************************************************************/
5536 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5537 const char *pdata,
5538 int total_data,
5539 const char *fname,
5540 SMB_STRUCT_STAT *psbuf)
5542 NTSTATUS status = NT_STATUS_OK;
5543 files_struct *fsp = NULL;
5544 uint16 flags = 0;
5545 char del = 1;
5546 int info = 0;
5547 int i;
5548 struct share_mode_lock *lck = NULL;
5550 if (total_data < 2) {
5551 return NT_STATUS_INVALID_PARAMETER;
5554 flags = SVAL(pdata,0);
5556 if (!VALID_STAT(*psbuf)) {
5557 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5560 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5561 !VALID_STAT_OF_DIR(*psbuf)) {
5562 return NT_STATUS_NOT_A_DIRECTORY;
5565 DEBUG(10,("smb_posix_unlink: %s %s\n",
5566 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5567 fname));
5569 if (VALID_STAT_OF_DIR(*psbuf)) {
5570 status = open_directory(conn,
5571 fname,
5572 psbuf,
5573 DELETE_ACCESS,
5574 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5575 FILE_OPEN,
5577 FILE_FLAG_POSIX_SEMANTICS|0777,
5578 &info,
5579 &fsp);
5580 } else {
5582 status = open_file_ntcreate(conn,
5583 fname,
5584 psbuf,
5585 DELETE_ACCESS,
5586 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5587 FILE_OPEN,
5589 FILE_FLAG_POSIX_SEMANTICS|0777,
5590 0, /* No oplock, but break existing ones. */
5591 &info,
5592 &fsp);
5595 if (!NT_STATUS_IS_OK(status)) {
5596 return status;
5600 * Don't lie to client. If we can't really delete due to
5601 * non-POSIX opens return SHARING_VIOLATION.
5604 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
5605 if (lck == NULL) {
5606 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5607 "lock for file %s\n", fsp->fsp_name));
5608 close_file(fsp, NORMAL_CLOSE);
5609 return NT_STATUS_INVALID_PARAMETER;
5613 * See if others still have the file open. If this is the case, then
5614 * don't delete. If all opens are POSIX delete we can set the delete
5615 * on close disposition.
5617 for (i=0; i<lck->num_share_modes; i++) {
5618 struct share_mode_entry *e = &lck->share_modes[i];
5619 if (is_valid_share_mode_entry(e)) {
5620 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5621 continue;
5623 /* Fail with sharing violation. */
5624 close_file(fsp, NORMAL_CLOSE);
5625 TALLOC_FREE(lck);
5626 return NT_STATUS_SHARING_VIOLATION;
5631 * Set the delete on close.
5633 status = smb_set_file_disposition_info(conn,
5634 &del,
5636 fsp,
5637 fname,
5638 psbuf);
5640 if (!NT_STATUS_IS_OK(status)) {
5641 close_file(fsp, NORMAL_CLOSE);
5642 TALLOC_FREE(lck);
5643 return status;
5645 TALLOC_FREE(lck);
5646 return close_file(fsp, NORMAL_CLOSE);
5649 /****************************************************************************
5650 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5651 ****************************************************************************/
5653 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5654 unsigned int tran_call,
5655 char **pparams, int total_params, char **ppdata, int total_data,
5656 unsigned int max_data_bytes)
5658 char *params = *pparams;
5659 char *pdata = *ppdata;
5660 uint16 info_level;
5661 SMB_STRUCT_STAT sbuf;
5662 pstring fname;
5663 files_struct *fsp = NULL;
5664 NTSTATUS status = NT_STATUS_OK;
5665 int data_return_size = 0;
5667 if (!params) {
5668 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5671 ZERO_STRUCT(sbuf);
5673 if (tran_call == TRANSACT2_SETFILEINFO) {
5674 if (total_params < 4) {
5675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5678 fsp = file_fsp(params,0);
5679 info_level = SVAL(params,2);
5681 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5683 * This is actually a SETFILEINFO on a directory
5684 * handle (returned from an NT SMB). NT5.0 seems
5685 * to do this call. JRA.
5687 pstrcpy(fname, fsp->fsp_name);
5688 if (INFO_LEVEL_IS_UNIX(info_level)) {
5689 /* Always do lstat for UNIX calls. */
5690 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5691 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5692 return UNIXERROR(ERRDOS,ERRbadpath);
5694 } else {
5695 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5696 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5697 return UNIXERROR(ERRDOS,ERRbadpath);
5700 } else if (fsp && fsp->print_file) {
5702 * Doing a DELETE_ON_CLOSE should cancel a print job.
5704 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5705 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5707 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5709 SSVAL(params,0,0);
5710 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5711 return(-1);
5712 } else
5713 return (UNIXERROR(ERRDOS,ERRbadpath));
5714 } else {
5716 * Original code - this is an open file.
5718 CHECK_FSP(fsp,conn);
5720 pstrcpy(fname, fsp->fsp_name);
5722 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5723 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5724 return(UNIXERROR(ERRDOS,ERRbadfid));
5727 } else {
5728 /* set path info */
5729 if (total_params < 7) {
5730 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5733 info_level = SVAL(params,0);
5734 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 return ERROR_NT(status);
5739 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5742 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5744 return ERROR_NT(status);
5747 status = unix_convert(conn, fname, False, NULL, &sbuf);
5748 if (!NT_STATUS_IS_OK(status)) {
5749 return ERROR_NT(status);
5752 status = check_name(conn, fname);
5753 if (!NT_STATUS_IS_OK(status)) {
5754 return ERROR_NT(status);
5757 if (INFO_LEVEL_IS_UNIX(info_level)) {
5759 * For CIFS UNIX extensions the target name may not exist.
5762 /* Always do lstat for UNIX calls. */
5763 SMB_VFS_LSTAT(conn,fname,&sbuf);
5765 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5766 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5767 return UNIXERROR(ERRDOS,ERRbadpath);
5771 if (!CAN_WRITE(conn)) {
5772 return ERROR_DOS(ERRSRV,ERRaccess);
5775 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5776 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5779 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5780 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5782 /* Realloc the parameter size */
5783 *pparams = (char *)SMB_REALLOC(*pparams,2);
5784 if (*pparams == NULL) {
5785 return ERROR_NT(NT_STATUS_NO_MEMORY);
5787 params = *pparams;
5789 SSVAL(params,0,0);
5791 if (fsp && !null_timespec(fsp->pending_modtime)) {
5792 /* the pending modtime overrides the current modtime */
5793 set_mtimespec(&sbuf, fsp->pending_modtime);
5796 switch (info_level) {
5798 case SMB_INFO_STANDARD:
5800 status = smb_set_info_standard(conn,
5801 pdata,
5802 total_data,
5803 fsp,
5804 fname,
5805 &sbuf);
5806 break;
5809 case SMB_INFO_SET_EA:
5811 status = smb_info_set_ea(conn,
5812 pdata,
5813 total_data,
5814 fsp,
5815 fname);
5816 break;
5819 case SMB_SET_FILE_BASIC_INFO:
5820 case SMB_FILE_BASIC_INFORMATION:
5822 status = smb_set_file_basic_info(conn,
5823 pdata,
5824 total_data,
5825 fsp,
5826 fname,
5827 &sbuf);
5828 break;
5831 case SMB_FILE_ALLOCATION_INFORMATION:
5832 case SMB_SET_FILE_ALLOCATION_INFO:
5834 status = smb_set_file_allocation_info(conn,
5835 pdata,
5836 total_data,
5837 fsp,
5838 fname,
5839 &sbuf);
5840 break;
5843 case SMB_FILE_END_OF_FILE_INFORMATION:
5844 case SMB_SET_FILE_END_OF_FILE_INFO:
5846 status = smb_set_file_end_of_file_info(conn,
5847 pdata,
5848 total_data,
5849 fsp,
5850 fname,
5851 &sbuf);
5852 break;
5855 case SMB_FILE_DISPOSITION_INFORMATION:
5856 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5858 #if 0
5859 /* JRA - We used to just ignore this on a path ?
5860 * Shouldn't this be invalid level on a pathname
5861 * based call ?
5863 if (tran_call != TRANSACT2_SETFILEINFO) {
5864 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5866 #endif
5867 status = smb_set_file_disposition_info(conn,
5868 pdata,
5869 total_data,
5870 fsp,
5871 fname,
5872 &sbuf);
5873 break;
5876 case SMB_FILE_POSITION_INFORMATION:
5878 status = smb_file_position_information(conn,
5879 pdata,
5880 total_data,
5881 fsp);
5882 break;
5885 /* From tridge Samba4 :
5886 * MODE_INFORMATION in setfileinfo (I have no
5887 * idea what "mode information" on a file is - it takes a value of 0,
5888 * 2, 4 or 6. What could it be?).
5891 case SMB_FILE_MODE_INFORMATION:
5893 status = smb_file_mode_information(conn,
5894 pdata,
5895 total_data);
5896 break;
5900 * CIFS UNIX extensions.
5903 case SMB_SET_FILE_UNIX_BASIC:
5905 status = smb_set_file_unix_basic(conn,
5906 pdata,
5907 total_data,
5908 fsp,
5909 fname,
5910 &sbuf);
5911 break;
5914 case SMB_SET_FILE_UNIX_INFO2:
5916 status = smb_set_file_unix_info2(conn,
5917 pdata,
5918 total_data,
5919 fsp,
5920 fname,
5921 &sbuf);
5922 break;
5925 case SMB_SET_FILE_UNIX_LINK:
5927 if (tran_call != TRANSACT2_SETPATHINFO) {
5928 /* We must have a pathname for this. */
5929 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5931 status = smb_set_file_unix_link(conn,
5932 inbuf,
5933 pdata,
5934 total_data,
5935 fname);
5936 break;
5939 case SMB_SET_FILE_UNIX_HLINK:
5941 if (tran_call != TRANSACT2_SETPATHINFO) {
5942 /* We must have a pathname for this. */
5943 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5945 status = smb_set_file_unix_hlink(conn,
5946 inbuf,
5947 outbuf,
5948 pdata,
5949 total_data,
5950 fname);
5951 break;
5954 case SMB_FILE_RENAME_INFORMATION:
5956 status = smb_file_rename_information(conn,
5957 inbuf,
5958 outbuf,
5959 pdata,
5960 total_data,
5961 fsp,
5962 fname);
5963 break;
5966 #if defined(HAVE_POSIX_ACLS)
5967 case SMB_SET_POSIX_ACL:
5969 status = smb_set_posix_acl(conn,
5970 pdata,
5971 total_data,
5972 fsp,
5973 fname,
5974 &sbuf);
5975 break;
5977 #endif
5979 case SMB_SET_POSIX_LOCK:
5981 if (tran_call != TRANSACT2_SETFILEINFO) {
5982 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5984 status = smb_set_posix_lock(conn,
5985 inbuf,
5986 length,
5987 pdata,
5988 total_data,
5989 fsp);
5990 break;
5993 case SMB_POSIX_PATH_OPEN:
5995 if (tran_call != TRANSACT2_SETPATHINFO) {
5996 /* We must have a pathname for this. */
5997 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6000 status = smb_posix_open(conn,
6001 ppdata,
6002 total_data,
6003 fname,
6004 &sbuf,
6005 &data_return_size);
6006 break;
6009 case SMB_POSIX_PATH_UNLINK:
6011 if (tran_call != TRANSACT2_SETPATHINFO) {
6012 /* We must have a pathname for this. */
6013 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6016 status = smb_posix_unlink(conn,
6017 pdata,
6018 total_data,
6019 fname,
6020 &sbuf);
6021 break;
6024 default:
6025 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6029 if (!NT_STATUS_IS_OK(status)) {
6030 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6031 /* We have re-scheduled this call. */
6032 return -1;
6034 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6035 /* We have re-scheduled this call. */
6036 return -1;
6038 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6039 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6041 if (info_level == SMB_POSIX_PATH_OPEN) {
6042 return ERROR_OPEN(status);
6044 return ERROR_NT(status);
6047 SSVAL(params,0,0);
6048 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6050 return -1;
6053 /****************************************************************************
6054 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6055 ****************************************************************************/
6057 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6058 char **pparams, int total_params, char **ppdata, int total_data,
6059 unsigned int max_data_bytes)
6061 char *params = *pparams;
6062 char *pdata = *ppdata;
6063 pstring directory;
6064 SMB_STRUCT_STAT sbuf;
6065 NTSTATUS status = NT_STATUS_OK;
6066 struct ea_list *ea_list = NULL;
6068 if (!CAN_WRITE(conn))
6069 return ERROR_DOS(ERRSRV,ERRaccess);
6071 if (total_params < 5) {
6072 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6075 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 return ERROR_NT(status);
6080 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6082 status = unix_convert(conn, directory, False, NULL, &sbuf);
6083 if (!NT_STATUS_IS_OK(status)) {
6084 return ERROR_NT(status);
6087 status = check_name(conn, directory);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6090 return ERROR_NT(status);
6093 /* Any data in this call is an EA list. */
6094 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6095 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6099 * OS/2 workplace shell seems to send SET_EA requests of "null"
6100 * length (4 bytes containing IVAL 4).
6101 * They seem to have no effect. Bug #3212. JRA.
6104 if (total_data != 4) {
6105 if (total_data < 10) {
6106 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6109 if (IVAL(pdata,0) > total_data) {
6110 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6111 IVAL(pdata,0), (unsigned int)total_data));
6112 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6115 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6116 total_data - 4);
6117 if (!ea_list) {
6118 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6120 } else if (IVAL(pdata,0) != 4) {
6121 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6124 status = create_directory(conn, directory);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 return ERROR_NT(status);
6130 /* Try and set any given EA. */
6131 if (ea_list) {
6132 status = set_ea(conn, NULL, directory, ea_list);
6133 if (!NT_STATUS_IS_OK(status)) {
6134 return ERROR_NT(status);
6138 /* Realloc the parameter and data sizes */
6139 *pparams = (char *)SMB_REALLOC(*pparams,2);
6140 if(*pparams == NULL) {
6141 return ERROR_NT(NT_STATUS_NO_MEMORY);
6143 params = *pparams;
6145 SSVAL(params,0,0);
6147 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6149 return(-1);
6152 /****************************************************************************
6153 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6154 We don't actually do this - we just send a null response.
6155 ****************************************************************************/
6157 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6158 char **pparams, int total_params, char **ppdata, int total_data,
6159 unsigned int max_data_bytes)
6161 static uint16 fnf_handle = 257;
6162 char *params = *pparams;
6163 uint16 info_level;
6165 if (total_params < 6) {
6166 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6169 info_level = SVAL(params,4);
6170 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6172 switch (info_level) {
6173 case 1:
6174 case 2:
6175 break;
6176 default:
6177 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6180 /* Realloc the parameter and data sizes */
6181 *pparams = (char *)SMB_REALLOC(*pparams,6);
6182 if (*pparams == NULL) {
6183 return ERROR_NT(NT_STATUS_NO_MEMORY);
6185 params = *pparams;
6187 SSVAL(params,0,fnf_handle);
6188 SSVAL(params,2,0); /* No changes */
6189 SSVAL(params,4,0); /* No EA errors */
6191 fnf_handle++;
6193 if(fnf_handle == 0)
6194 fnf_handle = 257;
6196 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6198 return(-1);
6201 /****************************************************************************
6202 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6203 changes). Currently this does nothing.
6204 ****************************************************************************/
6206 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6207 char **pparams, int total_params, char **ppdata, int total_data,
6208 unsigned int max_data_bytes)
6210 char *params = *pparams;
6212 DEBUG(3,("call_trans2findnotifynext\n"));
6214 /* Realloc the parameter and data sizes */
6215 *pparams = (char *)SMB_REALLOC(*pparams,4);
6216 if (*pparams == NULL) {
6217 return ERROR_NT(NT_STATUS_NO_MEMORY);
6219 params = *pparams;
6221 SSVAL(params,0,0); /* No changes */
6222 SSVAL(params,2,0); /* No EA errors */
6224 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6226 return(-1);
6229 /****************************************************************************
6230 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6231 ****************************************************************************/
6233 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6234 char **pparams, int total_params, char **ppdata, int total_data,
6235 unsigned int max_data_bytes)
6237 char *params = *pparams;
6238 pstring pathname;
6239 int reply_size = 0;
6240 int max_referral_level;
6241 NTSTATUS status = NT_STATUS_OK;
6243 DEBUG(10,("call_trans2getdfsreferral\n"));
6245 if (total_params < 3) {
6246 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6249 max_referral_level = SVAL(params,0);
6251 if(!lp_host_msdfs())
6252 return ERROR_DOS(ERRDOS,ERRbadfunc);
6254 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6255 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6256 return ERROR_NT(status);
6258 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6259 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6261 return(-1);
6264 #define LMCAT_SPL 0x53
6265 #define LMFUNC_GETJOBID 0x60
6267 /****************************************************************************
6268 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6269 ****************************************************************************/
6271 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6272 char **pparams, int total_params, char **ppdata, int total_data,
6273 unsigned int max_data_bytes)
6275 char *pdata = *ppdata;
6276 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6278 /* check for an invalid fid before proceeding */
6280 if (!fsp)
6281 return(ERROR_DOS(ERRDOS,ERRbadfid));
6283 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6284 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6285 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6286 if (*ppdata == NULL) {
6287 return ERROR_NT(NT_STATUS_NO_MEMORY);
6289 pdata = *ppdata;
6291 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6292 CAN ACCEPT THIS IN UNICODE. JRA. */
6294 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6295 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6296 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6297 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6298 return(-1);
6299 } else {
6300 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6301 return ERROR_DOS(ERRSRV,ERRerror);
6305 /****************************************************************************
6306 Reply to a SMBfindclose (stop trans2 directory search).
6307 ****************************************************************************/
6309 int reply_findclose(connection_struct *conn,
6310 char *inbuf,char *outbuf,int length,int bufsize)
6312 int outsize = 0;
6313 int dptr_num=SVALS(inbuf,smb_vwv0);
6314 START_PROFILE(SMBfindclose);
6316 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6318 dptr_close(&dptr_num);
6320 outsize = set_message(outbuf,0,0,False);
6322 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6324 END_PROFILE(SMBfindclose);
6325 return(outsize);
6328 /****************************************************************************
6329 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6330 ****************************************************************************/
6332 int reply_findnclose(connection_struct *conn,
6333 char *inbuf,char *outbuf,int length,int bufsize)
6335 int outsize = 0;
6336 int dptr_num= -1;
6337 START_PROFILE(SMBfindnclose);
6339 dptr_num = SVAL(inbuf,smb_vwv0);
6341 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6343 /* We never give out valid handles for a
6344 findnotifyfirst - so any dptr_num is ok here.
6345 Just ignore it. */
6347 outsize = set_message(outbuf,0,0,False);
6349 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6351 END_PROFILE(SMBfindnclose);
6352 return(outsize);
6355 int handle_trans2(connection_struct *conn,
6356 struct trans_state *state,
6357 char *inbuf, char *outbuf, int size, int bufsize)
6359 int outsize;
6361 if (Protocol >= PROTOCOL_NT1) {
6362 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6365 /* Now we must call the relevant TRANS2 function */
6366 switch(state->call) {
6367 case TRANSACT2_OPEN:
6369 START_PROFILE(Trans2_open);
6370 outsize = call_trans2open(
6371 conn, inbuf, outbuf, bufsize,
6372 &state->param, state->total_param,
6373 &state->data, state->total_data,
6374 state->max_data_return);
6375 END_PROFILE(Trans2_open);
6376 break;
6379 case TRANSACT2_FINDFIRST:
6381 START_PROFILE(Trans2_findfirst);
6382 outsize = call_trans2findfirst(
6383 conn, inbuf, outbuf, bufsize,
6384 &state->param, state->total_param,
6385 &state->data, state->total_data,
6386 state->max_data_return);
6387 END_PROFILE(Trans2_findfirst);
6388 break;
6391 case TRANSACT2_FINDNEXT:
6393 START_PROFILE(Trans2_findnext);
6394 outsize = call_trans2findnext(
6395 conn, inbuf, outbuf, size, bufsize,
6396 &state->param, state->total_param,
6397 &state->data, state->total_data,
6398 state->max_data_return);
6399 END_PROFILE(Trans2_findnext);
6400 break;
6403 case TRANSACT2_QFSINFO:
6405 START_PROFILE(Trans2_qfsinfo);
6406 outsize = call_trans2qfsinfo(
6407 conn, inbuf, outbuf, size, bufsize,
6408 &state->param, state->total_param,
6409 &state->data, state->total_data,
6410 state->max_data_return);
6411 END_PROFILE(Trans2_qfsinfo);
6412 break;
6415 case TRANSACT2_SETFSINFO:
6417 START_PROFILE(Trans2_setfsinfo);
6418 outsize = call_trans2setfsinfo(
6419 conn, inbuf, outbuf, size, bufsize,
6420 &state->param, state->total_param,
6421 &state->data, state->total_data,
6422 state->max_data_return);
6423 END_PROFILE(Trans2_setfsinfo);
6424 break;
6427 case TRANSACT2_QPATHINFO:
6428 case TRANSACT2_QFILEINFO:
6430 START_PROFILE(Trans2_qpathinfo);
6431 outsize = call_trans2qfilepathinfo(
6432 conn, inbuf, outbuf, size, bufsize, state->call,
6433 &state->param, state->total_param,
6434 &state->data, state->total_data,
6435 state->max_data_return);
6436 END_PROFILE(Trans2_qpathinfo);
6437 break;
6440 case TRANSACT2_SETPATHINFO:
6441 case TRANSACT2_SETFILEINFO:
6443 START_PROFILE(Trans2_setpathinfo);
6444 outsize = call_trans2setfilepathinfo(
6445 conn, inbuf, outbuf, size, bufsize, state->call,
6446 &state->param, state->total_param,
6447 &state->data, state->total_data,
6448 state->max_data_return);
6449 END_PROFILE(Trans2_setpathinfo);
6450 break;
6453 case TRANSACT2_FINDNOTIFYFIRST:
6455 START_PROFILE(Trans2_findnotifyfirst);
6456 outsize = call_trans2findnotifyfirst(
6457 conn, inbuf, outbuf, size, bufsize,
6458 &state->param, state->total_param,
6459 &state->data, state->total_data,
6460 state->max_data_return);
6461 END_PROFILE(Trans2_findnotifyfirst);
6462 break;
6465 case TRANSACT2_FINDNOTIFYNEXT:
6467 START_PROFILE(Trans2_findnotifynext);
6468 outsize = call_trans2findnotifynext(
6469 conn, inbuf, outbuf, size, bufsize,
6470 &state->param, state->total_param,
6471 &state->data, state->total_data,
6472 state->max_data_return);
6473 END_PROFILE(Trans2_findnotifynext);
6474 break;
6477 case TRANSACT2_MKDIR:
6479 START_PROFILE(Trans2_mkdir);
6480 outsize = call_trans2mkdir(
6481 conn, inbuf, outbuf, size, bufsize,
6482 &state->param, state->total_param,
6483 &state->data, state->total_data,
6484 state->max_data_return);
6485 END_PROFILE(Trans2_mkdir);
6486 break;
6489 case TRANSACT2_GET_DFS_REFERRAL:
6491 START_PROFILE(Trans2_get_dfs_referral);
6492 outsize = call_trans2getdfsreferral(
6493 conn, inbuf, outbuf, size, bufsize,
6494 &state->param, state->total_param,
6495 &state->data, state->total_data,
6496 state->max_data_return);
6497 END_PROFILE(Trans2_get_dfs_referral);
6498 break;
6501 case TRANSACT2_IOCTL:
6503 START_PROFILE(Trans2_ioctl);
6504 outsize = call_trans2ioctl(
6505 conn, inbuf, outbuf, size, bufsize,
6506 &state->param, state->total_param,
6507 &state->data, state->total_data,
6508 state->max_data_return);
6509 END_PROFILE(Trans2_ioctl);
6510 break;
6513 default:
6514 /* Error in request */
6515 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6516 outsize = ERROR_DOS(ERRSRV,ERRerror);
6519 return outsize;
6522 /****************************************************************************
6523 Reply to a SMBtrans2.
6524 ****************************************************************************/
6526 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6527 int size, int bufsize)
6529 int outsize = 0;
6530 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6531 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6532 unsigned int psoff = SVAL(inbuf, smb_psoff);
6533 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6534 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6535 struct trans_state *state;
6536 NTSTATUS result;
6538 START_PROFILE(SMBtrans2);
6540 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6541 if (!NT_STATUS_IS_OK(result)) {
6542 DEBUG(2, ("Got invalid trans2 request: %s\n",
6543 nt_errstr(result)));
6544 END_PROFILE(SMBtrans2);
6545 return ERROR_NT(result);
6548 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6549 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6550 END_PROFILE(SMBtrans2);
6551 return ERROR_DOS(ERRSRV,ERRaccess);
6554 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6555 DEBUG(0, ("talloc failed\n"));
6556 END_PROFILE(SMBtrans2);
6557 return ERROR_NT(NT_STATUS_NO_MEMORY);
6560 state->cmd = SMBtrans2;
6562 state->mid = SVAL(inbuf, smb_mid);
6563 state->vuid = SVAL(inbuf, smb_uid);
6564 state->setup_count = SVAL(inbuf, smb_suwcnt);
6565 state->setup = NULL;
6566 state->total_param = SVAL(inbuf, smb_tpscnt);
6567 state->param = NULL;
6568 state->total_data = SVAL(inbuf, smb_tdscnt);
6569 state->data = NULL;
6570 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6571 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6572 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6573 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6574 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6576 state->call = tran_call;
6578 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6579 is so as a sanity check */
6580 if (state->setup_count != 1) {
6582 * Need to have rc=0 for ioctl to get job id for OS/2.
6583 * Network printing will fail if function is not successful.
6584 * Similar function in reply.c will be used if protocol
6585 * is LANMAN1.0 instead of LM1.2X002.
6586 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6587 * outbuf doesn't have to be set(only job id is used).
6589 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6590 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6591 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6592 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6593 } else {
6594 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6595 DEBUG(2,("Transaction is %d\n",tran_call));
6596 TALLOC_FREE(state);
6597 END_PROFILE(SMBtrans2);
6598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6602 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6603 goto bad_param;
6605 if (state->total_data) {
6606 /* Can't use talloc here, the core routines do realloc on the
6607 * params and data. */
6608 state->data = (char *)SMB_MALLOC(state->total_data);
6609 if (state->data == NULL) {
6610 DEBUG(0,("reply_trans2: data malloc fail for %u "
6611 "bytes !\n", (unsigned int)state->total_data));
6612 TALLOC_FREE(state);
6613 END_PROFILE(SMBtrans2);
6614 return(ERROR_DOS(ERRDOS,ERRnomem));
6616 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6617 goto bad_param;
6618 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6619 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6620 goto bad_param;
6622 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6625 if (state->total_param) {
6626 /* Can't use talloc here, the core routines do realloc on the
6627 * params and data. */
6628 state->param = (char *)SMB_MALLOC(state->total_param);
6629 if (state->param == NULL) {
6630 DEBUG(0,("reply_trans: param malloc fail for %u "
6631 "bytes !\n", (unsigned int)state->total_param));
6632 SAFE_FREE(state->data);
6633 TALLOC_FREE(state);
6634 END_PROFILE(SMBtrans2);
6635 return(ERROR_DOS(ERRDOS,ERRnomem));
6637 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6638 goto bad_param;
6639 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6640 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6641 goto bad_param;
6643 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6646 state->received_data = dscnt;
6647 state->received_param = pscnt;
6649 if ((state->received_param == state->total_param) &&
6650 (state->received_data == state->total_data)) {
6652 outsize = handle_trans2(conn, state, inbuf, outbuf,
6653 size, bufsize);
6654 SAFE_FREE(state->data);
6655 SAFE_FREE(state->param);
6656 TALLOC_FREE(state);
6657 END_PROFILE(SMBtrans2);
6658 return outsize;
6661 DLIST_ADD(conn->pending_trans, state);
6663 /* We need to send an interim response then receive the rest
6664 of the parameter/data bytes */
6665 outsize = set_message(outbuf,0,0,False);
6666 show_msg(outbuf);
6667 END_PROFILE(SMBtrans2);
6668 return outsize;
6670 bad_param:
6672 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6673 SAFE_FREE(state->data);
6674 SAFE_FREE(state->param);
6675 TALLOC_FREE(state);
6676 END_PROFILE(SMBtrans2);
6677 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6681 /****************************************************************************
6682 Reply to a SMBtranss2
6683 ****************************************************************************/
6685 int reply_transs2(connection_struct *conn,
6686 char *inbuf,char *outbuf,int size,int bufsize)
6688 int outsize = 0;
6689 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6690 struct trans_state *state;
6692 START_PROFILE(SMBtranss2);
6694 show_msg(inbuf);
6696 for (state = conn->pending_trans; state != NULL;
6697 state = state->next) {
6698 if (state->mid == SVAL(inbuf,smb_mid)) {
6699 break;
6703 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6704 END_PROFILE(SMBtranss2);
6705 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6708 /* Revise state->total_param and state->total_data in case they have
6709 changed downwards */
6711 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6712 state->total_param = SVAL(inbuf, smb_tpscnt);
6713 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6714 state->total_data = SVAL(inbuf, smb_tdscnt);
6716 pcnt = SVAL(inbuf, smb_spscnt);
6717 poff = SVAL(inbuf, smb_spsoff);
6718 pdisp = SVAL(inbuf, smb_spsdisp);
6720 dcnt = SVAL(inbuf, smb_sdscnt);
6721 doff = SVAL(inbuf, smb_sdsoff);
6722 ddisp = SVAL(inbuf, smb_sdsdisp);
6724 state->received_param += pcnt;
6725 state->received_data += dcnt;
6727 if ((state->received_data > state->total_data) ||
6728 (state->received_param > state->total_param))
6729 goto bad_param;
6731 if (pcnt) {
6732 if (pdisp+pcnt > state->total_param)
6733 goto bad_param;
6734 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6735 goto bad_param;
6736 if (pdisp > state->total_param)
6737 goto bad_param;
6738 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6739 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6740 goto bad_param;
6741 if (state->param + pdisp < state->param)
6742 goto bad_param;
6744 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6745 pcnt);
6748 if (dcnt) {
6749 if (ddisp+dcnt > state->total_data)
6750 goto bad_param;
6751 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6752 goto bad_param;
6753 if (ddisp > state->total_data)
6754 goto bad_param;
6755 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6756 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6757 goto bad_param;
6758 if (state->data + ddisp < state->data)
6759 goto bad_param;
6761 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6762 dcnt);
6765 if ((state->received_param < state->total_param) ||
6766 (state->received_data < state->total_data)) {
6767 END_PROFILE(SMBtranss2);
6768 return -1;
6771 /* construct_reply_common has done us the favor to pre-fill the
6772 * command field with SMBtranss2 which is wrong :-)
6774 SCVAL(outbuf,smb_com,SMBtrans2);
6776 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6778 DLIST_REMOVE(conn->pending_trans, state);
6779 SAFE_FREE(state->data);
6780 SAFE_FREE(state->param);
6781 TALLOC_FREE(state);
6783 if (outsize == 0) {
6784 END_PROFILE(SMBtranss2);
6785 return(ERROR_DOS(ERRSRV,ERRnosupport));
6788 END_PROFILE(SMBtranss2);
6789 return(outsize);
6791 bad_param:
6793 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6794 DLIST_REMOVE(conn->pending_trans, state);
6795 SAFE_FREE(state->data);
6796 SAFE_FREE(state->param);
6797 TALLOC_FREE(state);
6798 END_PROFILE(SMBtranss2);
6799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);