r21882: The server part of the code has to use an AUTH_NTLMSSP struct,
[Samba/bb.git] / source3 / smbd / trans2.c
blob25fd6621e9d6433b3ef2c9d77da74d34e35c7a5e
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_NT(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 } else {
1605 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1606 p = store_file_unix_basic_info2(conn, p,
1607 NULL, &sbuf);
1610 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1611 p += len;
1612 SIVAL(p,0,0); /* Ensure any padding is null. */
1614 len = PTR_DIFF(p, pdata);
1615 len = (len + 3) & ~3;
1616 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1617 p = pdata + len;
1618 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1620 break;
1622 default:
1623 return(False);
1627 if (PTR_DIFF(p,pdata) > space_remaining) {
1628 /* Move the dirptr back to prev_dirpos */
1629 dptr_SeekDir(conn->dirptr, prev_dirpos);
1630 *out_of_space = True;
1631 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1632 return False; /* Not finished - just out of space */
1635 /* Setup the last entry pointer, as an offset from base_data */
1636 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1637 /* Advance the data pointer to the next slot */
1638 *ppdata = p;
1640 return(found);
1643 /****************************************************************************
1644 Reply to a TRANS2_FINDFIRST.
1645 ****************************************************************************/
1647 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1648 char **pparams, int total_params, char **ppdata, int total_data,
1649 unsigned int max_data_bytes)
1651 /* We must be careful here that we don't return more than the
1652 allowed number of data bytes. If this means returning fewer than
1653 maxentries then so be it. We assume that the redirector has
1654 enough room for the fixed number of parameter bytes it has
1655 requested. */
1656 char *params = *pparams;
1657 char *pdata = *ppdata;
1658 uint32 dirtype;
1659 int maxentries;
1660 uint16 findfirst_flags;
1661 BOOL close_after_first;
1662 BOOL close_if_end;
1663 BOOL requires_resume_key;
1664 int info_level;
1665 pstring directory;
1666 pstring mask;
1667 char *p;
1668 int last_entry_off=0;
1669 int dptr_num = -1;
1670 int numentries = 0;
1671 int i;
1672 BOOL finished = False;
1673 BOOL dont_descend = False;
1674 BOOL out_of_space = False;
1675 int space_remaining;
1676 BOOL mask_contains_wcard = False;
1677 SMB_STRUCT_STAT sbuf;
1678 TALLOC_CTX *ea_ctx = NULL;
1679 struct ea_list *ea_list = NULL;
1680 NTSTATUS ntstatus = NT_STATUS_OK;
1682 if (total_params < 13) {
1683 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1686 dirtype = SVAL(params,0);
1687 maxentries = SVAL(params,2);
1688 findfirst_flags = SVAL(params,4);
1689 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1690 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1691 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1692 info_level = SVAL(params,6);
1694 *directory = *mask = 0;
1696 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1697 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1698 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1699 info_level, max_data_bytes));
1701 if (!maxentries) {
1702 /* W2K3 seems to treat zero as 1. */
1703 maxentries = 1;
1706 switch (info_level) {
1707 case SMB_FIND_INFO_STANDARD:
1708 case SMB_FIND_EA_SIZE:
1709 case SMB_FIND_EA_LIST:
1710 case SMB_FIND_FILE_DIRECTORY_INFO:
1711 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1712 case SMB_FIND_FILE_NAMES_INFO:
1713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1714 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1715 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1716 break;
1717 case SMB_FIND_FILE_UNIX:
1718 case SMB_FIND_FILE_UNIX_INFO2:
1719 if (!lp_unix_extensions()) {
1720 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1722 break;
1723 default:
1724 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1727 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1728 if (!NT_STATUS_IS_OK(ntstatus)) {
1729 return ERROR_NT(ntstatus);
1732 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1733 if (!NT_STATUS_IS_OK(ntstatus)) {
1734 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1735 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1737 return ERROR_NT(ntstatus);
1740 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1741 if (!NT_STATUS_IS_OK(ntstatus)) {
1742 return ERROR_NT(ntstatus);
1744 ntstatus = check_name(conn, directory);
1745 if (!NT_STATUS_IS_OK(ntstatus)) {
1746 return ERROR_NT(ntstatus);
1749 p = strrchr_m(directory,'/');
1750 if(p == NULL) {
1751 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1752 if((directory[0] == '.') && (directory[1] == '\0')) {
1753 pstrcpy(mask,"*");
1754 mask_contains_wcard = True;
1755 } else {
1756 pstrcpy(mask,directory);
1758 pstrcpy(directory,"./");
1759 } else {
1760 pstrcpy(mask,p+1);
1761 *p = 0;
1764 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1766 if (info_level == SMB_FIND_EA_LIST) {
1767 uint32 ea_size;
1769 if (total_data < 4) {
1770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1773 ea_size = IVAL(pdata,0);
1774 if (ea_size != total_data) {
1775 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1776 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1780 if (!lp_ea_support(SNUM(conn))) {
1781 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1784 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1785 return ERROR_NT(NT_STATUS_NO_MEMORY);
1788 /* Pull out the list of names. */
1789 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1790 if (!ea_list) {
1791 talloc_destroy(ea_ctx);
1792 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1796 *ppdata = (char *)SMB_REALLOC(
1797 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1798 if(*ppdata == NULL ) {
1799 talloc_destroy(ea_ctx);
1800 return ERROR_NT(NT_STATUS_NO_MEMORY);
1802 pdata = *ppdata;
1804 /* Realloc the params space */
1805 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1806 if (*pparams == NULL) {
1807 talloc_destroy(ea_ctx);
1808 return ERROR_NT(NT_STATUS_NO_MEMORY);
1810 params = *pparams;
1812 /* Save the wildcard match and attribs we are using on this directory -
1813 needed as lanman2 assumes these are being saved between calls */
1815 ntstatus = dptr_create(conn,
1816 directory,
1817 False,
1818 True,
1819 SVAL(inbuf,smb_pid),
1820 mask,
1821 mask_contains_wcard,
1822 dirtype,
1823 &conn->dirptr);
1825 if (!NT_STATUS_IS_OK(ntstatus)) {
1826 talloc_destroy(ea_ctx);
1827 return ERROR_NT(ntstatus);
1830 dptr_num = dptr_dnum(conn->dirptr);
1831 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1833 /* We don't need to check for VOL here as this is returned by
1834 a different TRANS2 call. */
1836 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1837 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1838 dont_descend = True;
1840 p = pdata;
1841 space_remaining = max_data_bytes;
1842 out_of_space = False;
1844 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1845 BOOL got_exact_match = False;
1847 /* this is a heuristic to avoid seeking the dirptr except when
1848 absolutely necessary. It allows for a filename of about 40 chars */
1849 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1850 out_of_space = True;
1851 finished = False;
1852 } else {
1853 finished = !get_lanman2_dir_entry(conn,
1854 inbuf, outbuf,
1855 mask,dirtype,info_level,
1856 requires_resume_key,dont_descend,
1857 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1858 &last_entry_off, ea_list, ea_ctx);
1861 if (finished && out_of_space)
1862 finished = False;
1864 if (!finished && !out_of_space)
1865 numentries++;
1868 * As an optimisation if we know we aren't looking
1869 * for a wildcard name (ie. the name matches the wildcard exactly)
1870 * then we can finish on any (first) match.
1871 * This speeds up large directory searches. JRA.
1874 if(got_exact_match)
1875 finished = True;
1877 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1880 talloc_destroy(ea_ctx);
1882 /* Check if we can close the dirptr */
1883 if(close_after_first || (finished && close_if_end)) {
1884 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1885 dptr_close(&dptr_num);
1889 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1890 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1891 * the protocol level is less than NT1. Tested with smbclient. JRA.
1892 * This should fix the OS/2 client bug #2335.
1895 if(numentries == 0) {
1896 dptr_close(&dptr_num);
1897 if (Protocol < PROTOCOL_NT1) {
1898 return ERROR_DOS(ERRDOS,ERRnofiles);
1899 } else {
1900 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1904 /* At this point pdata points to numentries directory entries. */
1906 /* Set up the return parameter block */
1907 SSVAL(params,0,dptr_num);
1908 SSVAL(params,2,numentries);
1909 SSVAL(params,4,finished);
1910 SSVAL(params,6,0); /* Never an EA error */
1911 SSVAL(params,8,last_entry_off);
1913 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1915 if ((! *directory) && dptr_path(dptr_num))
1916 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1918 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1919 smb_fn_name(CVAL(inbuf,smb_com)),
1920 mask, directory, dirtype, numentries ) );
1923 * Force a name mangle here to ensure that the
1924 * mask as an 8.3 name is top of the mangled cache.
1925 * The reasons for this are subtle. Don't remove
1926 * this code unless you know what you are doing
1927 * (see PR#13758). JRA.
1930 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1931 mangle_map(mask, True, True, conn->params);
1933 return(-1);
1936 /****************************************************************************
1937 Reply to a TRANS2_FINDNEXT.
1938 ****************************************************************************/
1940 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1941 char **pparams, int total_params, char **ppdata, int total_data,
1942 unsigned int max_data_bytes)
1944 /* We must be careful here that we don't return more than the
1945 allowed number of data bytes. If this means returning fewer than
1946 maxentries then so be it. We assume that the redirector has
1947 enough room for the fixed number of parameter bytes it has
1948 requested. */
1949 char *params = *pparams;
1950 char *pdata = *ppdata;
1951 int dptr_num;
1952 int maxentries;
1953 uint16 info_level;
1954 uint32 resume_key;
1955 uint16 findnext_flags;
1956 BOOL close_after_request;
1957 BOOL close_if_end;
1958 BOOL requires_resume_key;
1959 BOOL continue_bit;
1960 BOOL mask_contains_wcard = False;
1961 pstring resume_name;
1962 pstring mask;
1963 pstring directory;
1964 char *p;
1965 uint16 dirtype;
1966 int numentries = 0;
1967 int i, last_entry_off=0;
1968 BOOL finished = False;
1969 BOOL dont_descend = False;
1970 BOOL out_of_space = False;
1971 int space_remaining;
1972 TALLOC_CTX *ea_ctx = NULL;
1973 struct ea_list *ea_list = NULL;
1974 NTSTATUS ntstatus = NT_STATUS_OK;
1976 if (total_params < 13) {
1977 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1980 dptr_num = SVAL(params,0);
1981 maxentries = SVAL(params,2);
1982 info_level = SVAL(params,4);
1983 resume_key = IVAL(params,6);
1984 findnext_flags = SVAL(params,10);
1985 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1986 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1987 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1988 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1990 *mask = *directory = *resume_name = 0;
1992 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1993 if (!NT_STATUS_IS_OK(ntstatus)) {
1994 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1995 complain (it thinks we're asking for the directory above the shared
1996 path or an invalid name). Catch this as the resume name is only compared, never used in
1997 a file access. JRA. */
1998 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1999 pstrcpy(resume_name, "..");
2000 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2001 pstrcpy(resume_name, ".");
2002 } else {
2003 return ERROR_NT(ntstatus);
2007 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2008 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2009 resume_key = %d resume name = %s continue=%d level = %d\n",
2010 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2011 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2013 if (!maxentries) {
2014 /* W2K3 seems to treat zero as 1. */
2015 maxentries = 1;
2018 switch (info_level) {
2019 case SMB_FIND_INFO_STANDARD:
2020 case SMB_FIND_EA_SIZE:
2021 case SMB_FIND_EA_LIST:
2022 case SMB_FIND_FILE_DIRECTORY_INFO:
2023 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2024 case SMB_FIND_FILE_NAMES_INFO:
2025 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2026 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2027 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2028 break;
2029 case SMB_FIND_FILE_UNIX:
2030 case SMB_FIND_FILE_UNIX_INFO2:
2031 if (!lp_unix_extensions()) {
2032 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2034 break;
2035 default:
2036 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2039 if (info_level == SMB_FIND_EA_LIST) {
2040 uint32 ea_size;
2042 if (total_data < 4) {
2043 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2046 ea_size = IVAL(pdata,0);
2047 if (ea_size != total_data) {
2048 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2049 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2050 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2053 if (!lp_ea_support(SNUM(conn))) {
2054 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2057 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2058 return ERROR_NT(NT_STATUS_NO_MEMORY);
2061 /* Pull out the list of names. */
2062 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2063 if (!ea_list) {
2064 talloc_destroy(ea_ctx);
2065 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2069 *ppdata = (char *)SMB_REALLOC(
2070 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2071 if(*ppdata == NULL) {
2072 talloc_destroy(ea_ctx);
2073 return ERROR_NT(NT_STATUS_NO_MEMORY);
2076 pdata = *ppdata;
2078 /* Realloc the params space */
2079 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2080 if(*pparams == NULL ) {
2081 talloc_destroy(ea_ctx);
2082 return ERROR_NT(NT_STATUS_NO_MEMORY);
2085 params = *pparams;
2087 /* Check that the dptr is valid */
2088 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2089 talloc_destroy(ea_ctx);
2090 return ERROR_DOS(ERRDOS,ERRnofiles);
2093 string_set(&conn->dirpath,dptr_path(dptr_num));
2095 /* Get the wildcard mask from the dptr */
2096 if((p = dptr_wcard(dptr_num))== NULL) {
2097 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2098 talloc_destroy(ea_ctx);
2099 return ERROR_DOS(ERRDOS,ERRnofiles);
2102 pstrcpy(mask, p);
2103 pstrcpy(directory,conn->dirpath);
2105 /* Get the attr mask from the dptr */
2106 dirtype = dptr_attr(dptr_num);
2108 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2109 dptr_num, mask, dirtype,
2110 (long)conn->dirptr,
2111 dptr_TellDir(conn->dirptr)));
2113 /* We don't need to check for VOL here as this is returned by
2114 a different TRANS2 call. */
2116 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2117 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2118 dont_descend = True;
2120 p = pdata;
2121 space_remaining = max_data_bytes;
2122 out_of_space = False;
2125 * Seek to the correct position. We no longer use the resume key but
2126 * depend on the last file name instead.
2129 if(*resume_name && !continue_bit) {
2130 SMB_STRUCT_STAT st;
2132 long current_pos = 0;
2134 * Remember, mangle_map is called by
2135 * get_lanman2_dir_entry(), so the resume name
2136 * could be mangled. Ensure we check the unmangled name.
2139 if (mangle_is_mangled(resume_name, conn->params)) {
2140 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2141 conn->params);
2145 * Fix for NT redirector problem triggered by resume key indexes
2146 * changing between directory scans. We now return a resume key of 0
2147 * and instead look for the filename to continue from (also given
2148 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2149 * findfirst/findnext (as is usual) then the directory pointer
2150 * should already be at the correct place.
2153 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2154 } /* end if resume_name && !continue_bit */
2156 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2157 BOOL got_exact_match = False;
2159 /* this is a heuristic to avoid seeking the dirptr except when
2160 absolutely necessary. It allows for a filename of about 40 chars */
2161 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2162 out_of_space = True;
2163 finished = False;
2164 } else {
2165 finished = !get_lanman2_dir_entry(conn,
2166 inbuf, outbuf,
2167 mask,dirtype,info_level,
2168 requires_resume_key,dont_descend,
2169 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2170 &last_entry_off, ea_list, ea_ctx);
2173 if (finished && out_of_space)
2174 finished = False;
2176 if (!finished && !out_of_space)
2177 numentries++;
2180 * As an optimisation if we know we aren't looking
2181 * for a wildcard name (ie. the name matches the wildcard exactly)
2182 * then we can finish on any (first) match.
2183 * This speeds up large directory searches. JRA.
2186 if(got_exact_match)
2187 finished = True;
2189 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2192 talloc_destroy(ea_ctx);
2194 /* Check if we can close the dirptr */
2195 if(close_after_request || (finished && close_if_end)) {
2196 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2197 dptr_close(&dptr_num); /* This frees up the saved mask */
2200 /* Set up the return parameter block */
2201 SSVAL(params,0,numentries);
2202 SSVAL(params,2,finished);
2203 SSVAL(params,4,0); /* Never an EA error */
2204 SSVAL(params,6,last_entry_off);
2206 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2208 if ((! *directory) && dptr_path(dptr_num))
2209 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2211 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2212 smb_fn_name(CVAL(inbuf,smb_com)),
2213 mask, directory, dirtype, numentries ) );
2215 return(-1);
2218 /****************************************************************************
2219 Reply to a TRANS2_QFSINFO (query filesystem info).
2220 ****************************************************************************/
2222 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2223 char **pparams, int total_params, char **ppdata, int total_data,
2224 unsigned int max_data_bytes)
2226 char *pdata;
2227 char *params = *pparams;
2228 uint16 info_level;
2229 int data_len, len;
2230 SMB_STRUCT_STAT st;
2231 char *vname = volume_label(SNUM(conn));
2232 int snum = SNUM(conn);
2233 char *fstype = lp_fstype(SNUM(conn));
2234 int quota_flag = 0;
2236 if (total_params < 2) {
2237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2240 info_level = SVAL(params,0);
2242 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2244 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2245 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2246 return ERROR_DOS(ERRSRV,ERRinvdevice);
2249 *ppdata = (char *)SMB_REALLOC(
2250 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2251 if (*ppdata == NULL ) {
2252 return ERROR_NT(NT_STATUS_NO_MEMORY);
2255 pdata = *ppdata;
2256 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2258 switch (info_level) {
2259 case SMB_INFO_ALLOCATION:
2261 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2262 data_len = 18;
2263 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2264 return(UNIXERROR(ERRHRD,ERRgeneral));
2267 block_size = lp_block_size(snum);
2268 if (bsize < block_size) {
2269 SMB_BIG_UINT factor = block_size/bsize;
2270 bsize = block_size;
2271 dsize /= factor;
2272 dfree /= factor;
2274 if (bsize > block_size) {
2275 SMB_BIG_UINT factor = bsize/block_size;
2276 bsize = block_size;
2277 dsize *= factor;
2278 dfree *= factor;
2280 bytes_per_sector = 512;
2281 sectors_per_unit = bsize/bytes_per_sector;
2283 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2284 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2285 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2287 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2288 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2289 SIVAL(pdata,l1_cUnit,dsize);
2290 SIVAL(pdata,l1_cUnitAvail,dfree);
2291 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2292 break;
2295 case SMB_INFO_VOLUME:
2296 /* Return volume name */
2298 * Add volume serial number - hash of a combination of
2299 * the called hostname and the service name.
2301 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2303 * Win2k3 and previous mess this up by sending a name length
2304 * one byte short. I believe only older clients (OS/2 Win9x) use
2305 * this call so try fixing this by adding a terminating null to
2306 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2308 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2309 SCVAL(pdata,l2_vol_cch,len);
2310 data_len = l2_vol_szVolLabel + len;
2311 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2312 (unsigned)st.st_ctime, len, vname));
2313 break;
2315 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2316 case SMB_FS_ATTRIBUTE_INFORMATION:
2319 #if defined(HAVE_SYS_QUOTAS)
2320 quota_flag = FILE_VOLUME_QUOTAS;
2321 #endif
2323 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2324 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2325 quota_flag); /* FS ATTRIBUTES */
2327 SIVAL(pdata,4,255); /* Max filename component length */
2328 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2329 and will think we can't do long filenames */
2330 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2331 SIVAL(pdata,8,len);
2332 data_len = 12 + len;
2333 break;
2335 case SMB_QUERY_FS_LABEL_INFO:
2336 case SMB_FS_LABEL_INFORMATION:
2337 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2338 data_len = 4 + len;
2339 SIVAL(pdata,0,len);
2340 break;
2342 case SMB_QUERY_FS_VOLUME_INFO:
2343 case SMB_FS_VOLUME_INFORMATION:
2346 * Add volume serial number - hash of a combination of
2347 * the called hostname and the service name.
2349 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2350 (str_checksum(get_local_machine_name())<<16));
2352 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2353 SIVAL(pdata,12,len);
2354 data_len = 18+len;
2355 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2356 (int)strlen(vname),vname, lp_servicename(snum)));
2357 break;
2359 case SMB_QUERY_FS_SIZE_INFO:
2360 case SMB_FS_SIZE_INFORMATION:
2362 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2363 data_len = 24;
2364 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2365 return(UNIXERROR(ERRHRD,ERRgeneral));
2367 block_size = lp_block_size(snum);
2368 if (bsize < block_size) {
2369 SMB_BIG_UINT factor = block_size/bsize;
2370 bsize = block_size;
2371 dsize /= factor;
2372 dfree /= factor;
2374 if (bsize > block_size) {
2375 SMB_BIG_UINT factor = bsize/block_size;
2376 bsize = block_size;
2377 dsize *= factor;
2378 dfree *= factor;
2380 bytes_per_sector = 512;
2381 sectors_per_unit = bsize/bytes_per_sector;
2382 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2383 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2384 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2385 SBIG_UINT(pdata,0,dsize);
2386 SBIG_UINT(pdata,8,dfree);
2387 SIVAL(pdata,16,sectors_per_unit);
2388 SIVAL(pdata,20,bytes_per_sector);
2389 break;
2392 case SMB_FS_FULL_SIZE_INFORMATION:
2394 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2395 data_len = 32;
2396 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2397 return(UNIXERROR(ERRHRD,ERRgeneral));
2399 block_size = lp_block_size(snum);
2400 if (bsize < block_size) {
2401 SMB_BIG_UINT factor = block_size/bsize;
2402 bsize = block_size;
2403 dsize /= factor;
2404 dfree /= factor;
2406 if (bsize > block_size) {
2407 SMB_BIG_UINT factor = bsize/block_size;
2408 bsize = block_size;
2409 dsize *= factor;
2410 dfree *= factor;
2412 bytes_per_sector = 512;
2413 sectors_per_unit = bsize/bytes_per_sector;
2414 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2415 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2416 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2417 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2418 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2419 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2420 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2421 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2422 break;
2425 case SMB_QUERY_FS_DEVICE_INFO:
2426 case SMB_FS_DEVICE_INFORMATION:
2427 data_len = 8;
2428 SIVAL(pdata,0,0); /* dev type */
2429 SIVAL(pdata,4,0); /* characteristics */
2430 break;
2432 #ifdef HAVE_SYS_QUOTAS
2433 case SMB_FS_QUOTA_INFORMATION:
2435 * what we have to send --metze:
2437 * Unknown1: 24 NULL bytes
2438 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2439 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2440 * Quota Flags: 2 byte :
2441 * Unknown3: 6 NULL bytes
2443 * 48 bytes total
2445 * details for Quota Flags:
2447 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2448 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2449 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2450 * 0x0001 Enable Quotas: enable quota for this fs
2454 /* we need to fake up a fsp here,
2455 * because its not send in this call
2457 files_struct fsp;
2458 SMB_NTQUOTA_STRUCT quotas;
2460 ZERO_STRUCT(fsp);
2461 ZERO_STRUCT(quotas);
2463 fsp.conn = conn;
2464 fsp.fnum = -1;
2466 /* access check */
2467 if (current_user.ut.uid != 0) {
2468 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2469 lp_servicename(SNUM(conn)),conn->user));
2470 return ERROR_DOS(ERRDOS,ERRnoaccess);
2473 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2474 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2475 return ERROR_DOS(ERRSRV,ERRerror);
2478 data_len = 48;
2480 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2482 /* Unknown1 24 NULL bytes*/
2483 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2484 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2485 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2487 /* Default Soft Quota 8 bytes */
2488 SBIG_UINT(pdata,24,quotas.softlim);
2490 /* Default Hard Quota 8 bytes */
2491 SBIG_UINT(pdata,32,quotas.hardlim);
2493 /* Quota flag 2 bytes */
2494 SSVAL(pdata,40,quotas.qflags);
2496 /* Unknown3 6 NULL bytes */
2497 SSVAL(pdata,42,0);
2498 SIVAL(pdata,44,0);
2500 break;
2502 #endif /* HAVE_SYS_QUOTAS */
2503 case SMB_FS_OBJECTID_INFORMATION:
2504 data_len = 64;
2505 break;
2508 * Query the version and capabilities of the CIFS UNIX extensions
2509 * in use.
2512 case SMB_QUERY_CIFS_UNIX_INFO:
2513 if (!lp_unix_extensions()) {
2514 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2516 data_len = 12;
2517 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2518 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2519 /* We have POSIX ACLs, pathname and locking capability. */
2520 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2521 CIFS_UNIX_POSIX_ACLS_CAP|
2522 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2523 CIFS_UNIX_FCNTL_LOCKS_CAP|
2524 CIFS_UNIX_EXTATTR_CAP|
2525 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2526 break;
2528 case SMB_QUERY_POSIX_FS_INFO:
2530 int rc;
2531 vfs_statvfs_struct svfs;
2533 if (!lp_unix_extensions()) {
2534 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2537 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2539 if (!rc) {
2540 data_len = 56;
2541 SIVAL(pdata,0,svfs.OptimalTransferSize);
2542 SIVAL(pdata,4,svfs.BlockSize);
2543 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2544 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2545 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2546 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2547 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2548 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2549 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2550 #ifdef EOPNOTSUPP
2551 } else if (rc == EOPNOTSUPP) {
2552 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2553 #endif /* EOPNOTSUPP */
2554 } else {
2555 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2556 return ERROR_DOS(ERRSRV,ERRerror);
2558 break;
2561 case SMB_QUERY_POSIX_WHOAMI:
2563 uint32_t flags = 0;
2564 uint32_t sid_bytes;
2565 int i;
2567 if (!lp_unix_extensions()) {
2568 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2571 if (max_data_bytes < 40) {
2572 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2575 /* We ARE guest if global_sid_Builtin_Guests is
2576 * in our list of SIDs.
2578 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2579 current_user.nt_user_token)) {
2580 flags |= SMB_WHOAMI_GUEST;
2583 /* We are NOT guest if global_sid_Authenticated_Users
2584 * is in our list of SIDs.
2586 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2587 current_user.nt_user_token)) {
2588 flags &= ~SMB_WHOAMI_GUEST;
2591 /* NOTE: 8 bytes for UID/GID, irrespective of native
2592 * platform size. This matches
2593 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2595 data_len = 4 /* flags */
2596 + 4 /* flag mask */
2597 + 8 /* uid */
2598 + 8 /* gid */
2599 + 4 /* ngroups */
2600 + 4 /* num_sids */
2601 + 4 /* SID bytes */
2602 + 4 /* pad/reserved */
2603 + (current_user.ut.ngroups * 8)
2604 /* groups list */
2605 + (current_user.nt_user_token->num_sids *
2606 SID_MAX_SIZE)
2607 /* SID list */;
2609 SIVAL(pdata, 0, flags);
2610 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2611 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2612 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2615 if (data_len >= max_data_bytes) {
2616 /* Potential overflow, skip the GIDs and SIDs. */
2618 SIVAL(pdata, 24, 0); /* num_groups */
2619 SIVAL(pdata, 28, 0); /* num_sids */
2620 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2621 SIVAL(pdata, 36, 0); /* reserved */
2623 data_len = 40;
2624 break;
2627 SIVAL(pdata, 24, current_user.ut.ngroups);
2628 SIVAL(pdata, 28,
2629 current_user.nt_user_token->num_sids);
2631 /* We walk the SID list twice, but this call is fairly
2632 * infrequent, and I don't expect that it's performance
2633 * sensitive -- jpeach
2635 for (i = 0, sid_bytes = 0;
2636 i < current_user.nt_user_token->num_sids; ++i) {
2637 sid_bytes +=
2638 sid_size(&current_user.nt_user_token->user_sids[i]);
2641 /* SID list byte count */
2642 SIVAL(pdata, 32, sid_bytes);
2644 /* 4 bytes pad/reserved - must be zero */
2645 SIVAL(pdata, 36, 0);
2646 data_len = 40;
2648 /* GID list */
2649 for (i = 0; i < current_user.ut.ngroups; ++i) {
2650 SBIG_UINT(pdata, data_len,
2651 (SMB_BIG_UINT)current_user.ut.groups[i]);
2652 data_len += 8;
2655 /* SID list */
2656 for (i = 0;
2657 i < current_user.nt_user_token->num_sids; ++i) {
2658 int sid_len =
2659 sid_size(&current_user.nt_user_token->user_sids[i]);
2661 sid_linearize(pdata + data_len, sid_len,
2662 &current_user.nt_user_token->user_sids[i]);
2663 data_len += sid_len;
2666 break;
2669 case SMB_MAC_QUERY_FS_INFO:
2671 * Thursby MAC extension... ONLY on NTFS filesystems
2672 * once we do streams then we don't need this
2674 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2675 data_len = 88;
2676 SIVAL(pdata,84,0x100); /* Don't support mac... */
2677 break;
2679 /* drop through */
2680 default:
2681 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2685 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2687 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2689 return -1;
2692 /****************************************************************************
2693 Reply to a TRANS2_SETFSINFO (set filesystem info).
2694 ****************************************************************************/
2696 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2697 char **pparams, int total_params, char **ppdata, int total_data,
2698 unsigned int max_data_bytes)
2700 char *pdata = *ppdata;
2701 char *params = *pparams;
2702 uint16 info_level;
2703 int outsize;
2705 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2707 /* */
2708 if (total_params < 4) {
2709 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2710 total_params));
2711 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2714 info_level = SVAL(params,2);
2716 switch(info_level) {
2717 case SMB_SET_CIFS_UNIX_INFO:
2719 uint16 client_unix_major;
2720 uint16 client_unix_minor;
2721 uint32 client_unix_cap_low;
2722 uint32 client_unix_cap_high;
2724 if (!lp_unix_extensions()) {
2725 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2728 /* There should be 12 bytes of capabilities set. */
2729 if (total_data < 8) {
2730 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2732 client_unix_major = SVAL(pdata,0);
2733 client_unix_minor = SVAL(pdata,2);
2734 client_unix_cap_low = IVAL(pdata,4);
2735 client_unix_cap_high = IVAL(pdata,8);
2736 /* Just print these values for now. */
2737 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2738 cap_low = 0x%x, cap_high = 0x%x\n",
2739 (unsigned int)client_unix_major,
2740 (unsigned int)client_unix_minor,
2741 (unsigned int)client_unix_cap_low,
2742 (unsigned int)client_unix_cap_high ));
2744 /* Here is where we must switch to posix pathname processing... */
2745 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2746 lp_set_posix_pathnames();
2747 mangle_change_to_posix();
2750 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2751 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2752 /* Client that knows how to do posix locks,
2753 * but not posix open/mkdir operations. Set a
2754 * default type for read/write checks. */
2756 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2759 break;
2761 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2763 NTSTATUS status;
2764 size_t data_len = total_data;
2766 if (!lp_unix_extensions()) {
2767 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2770 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2772 status = srv_request_encryption_setup((unsigned char **)&pdata, &data_len);
2774 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2775 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2776 } else if (!NT_STATUS_IS_OK(status)) {
2777 return ERROR_NT(status);
2780 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2782 if (NT_STATUS_IS_OK(status)) {
2783 /* Server-side transport encryption is now *on*. */
2784 srv_encryption_start();
2786 return -1;
2788 case SMB_FS_QUOTA_INFORMATION:
2790 files_struct *fsp = NULL;
2791 SMB_NTQUOTA_STRUCT quotas;
2793 ZERO_STRUCT(quotas);
2795 /* access check */
2796 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2797 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2798 lp_servicename(SNUM(conn)),conn->user));
2799 return ERROR_DOS(ERRSRV,ERRaccess);
2802 /* note: normaly there're 48 bytes,
2803 * but we didn't use the last 6 bytes for now
2804 * --metze
2806 fsp = file_fsp(params,0);
2807 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2808 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2809 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2812 if (total_data < 42) {
2813 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2814 total_data));
2815 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2818 /* unknown_1 24 NULL bytes in pdata*/
2820 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2821 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2822 #ifdef LARGE_SMB_OFF_T
2823 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2824 #else /* LARGE_SMB_OFF_T */
2825 if ((IVAL(pdata,28) != 0)&&
2826 ((quotas.softlim != 0xFFFFFFFF)||
2827 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2828 /* more than 32 bits? */
2829 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2831 #endif /* LARGE_SMB_OFF_T */
2833 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2834 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2835 #ifdef LARGE_SMB_OFF_T
2836 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2837 #else /* LARGE_SMB_OFF_T */
2838 if ((IVAL(pdata,36) != 0)&&
2839 ((quotas.hardlim != 0xFFFFFFFF)||
2840 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2841 /* more than 32 bits? */
2842 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2844 #endif /* LARGE_SMB_OFF_T */
2846 /* quota_flags 2 bytes **/
2847 quotas.qflags = SVAL(pdata,40);
2849 /* unknown_2 6 NULL bytes follow*/
2851 /* now set the quotas */
2852 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2853 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2854 return ERROR_DOS(ERRSRV,ERRerror);
2857 break;
2859 default:
2860 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2861 info_level));
2862 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2863 break;
2867 * sending this reply works fine,
2868 * but I'm not sure it's the same
2869 * like windows do...
2870 * --metze
2872 outsize = set_message(outbuf,10,0,True);
2874 return outsize;
2877 #if defined(HAVE_POSIX_ACLS)
2878 /****************************************************************************
2879 Utility function to count the number of entries in a POSIX acl.
2880 ****************************************************************************/
2882 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2884 unsigned int ace_count = 0;
2885 int entry_id = SMB_ACL_FIRST_ENTRY;
2886 SMB_ACL_ENTRY_T entry;
2888 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2889 /* get_next... */
2890 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2891 entry_id = SMB_ACL_NEXT_ENTRY;
2893 ace_count++;
2895 return ace_count;
2898 /****************************************************************************
2899 Utility function to marshall a POSIX acl into wire format.
2900 ****************************************************************************/
2902 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2904 int entry_id = SMB_ACL_FIRST_ENTRY;
2905 SMB_ACL_ENTRY_T entry;
2907 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2908 SMB_ACL_TAG_T tagtype;
2909 SMB_ACL_PERMSET_T permset;
2910 unsigned char perms = 0;
2911 unsigned int own_grp;
2913 /* get_next... */
2914 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2915 entry_id = SMB_ACL_NEXT_ENTRY;
2918 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2919 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2920 return False;
2923 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2924 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2925 return False;
2928 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2929 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2930 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2932 SCVAL(pdata,1,perms);
2934 switch (tagtype) {
2935 case SMB_ACL_USER_OBJ:
2936 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2937 own_grp = (unsigned int)pst->st_uid;
2938 SIVAL(pdata,2,own_grp);
2939 SIVAL(pdata,6,0);
2940 break;
2941 case SMB_ACL_USER:
2943 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2944 if (!puid) {
2945 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2947 own_grp = (unsigned int)*puid;
2948 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2949 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2950 SIVAL(pdata,2,own_grp);
2951 SIVAL(pdata,6,0);
2952 break;
2954 case SMB_ACL_GROUP_OBJ:
2955 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2956 own_grp = (unsigned int)pst->st_gid;
2957 SIVAL(pdata,2,own_grp);
2958 SIVAL(pdata,6,0);
2959 break;
2960 case SMB_ACL_GROUP:
2962 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2963 if (!pgid) {
2964 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2966 own_grp = (unsigned int)*pgid;
2967 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2968 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2969 SIVAL(pdata,2,own_grp);
2970 SIVAL(pdata,6,0);
2971 break;
2973 case SMB_ACL_MASK:
2974 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2975 SIVAL(pdata,2,0xFFFFFFFF);
2976 SIVAL(pdata,6,0xFFFFFFFF);
2977 break;
2978 case SMB_ACL_OTHER:
2979 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2980 SIVAL(pdata,2,0xFFFFFFFF);
2981 SIVAL(pdata,6,0xFFFFFFFF);
2982 break;
2983 default:
2984 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2985 return False;
2987 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2990 return True;
2992 #endif
2994 /****************************************************************************
2995 Store the FILE_UNIX_BASIC info.
2996 ****************************************************************************/
2998 static char *store_file_unix_basic(connection_struct *conn,
2999 char *pdata,
3000 files_struct *fsp,
3001 const SMB_STRUCT_STAT *psbuf)
3003 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3004 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3006 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3007 pdata += 8;
3009 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3010 pdata += 8;
3012 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3013 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3014 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3015 pdata += 24;
3017 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3018 SIVAL(pdata,4,0);
3019 pdata += 8;
3021 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3022 SIVAL(pdata,4,0);
3023 pdata += 8;
3025 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3026 pdata += 4;
3028 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3029 SIVAL(pdata,4,0);
3030 pdata += 8;
3032 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3033 SIVAL(pdata,4,0);
3034 pdata += 8;
3036 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3037 pdata += 8;
3039 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3040 SIVAL(pdata,4,0);
3041 pdata += 8;
3043 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3044 SIVAL(pdata,4,0);
3045 pdata += 8;
3047 return pdata;
3050 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3051 * the chflags(2) (or equivalent) flags.
3053 * XXX: this really should be behind the VFS interface. To do this, we would
3054 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3055 * Each VFS module could then implement it's own mapping as appropriate for the
3056 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3058 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3059 info2_flags_map[] =
3061 #ifdef UF_NODUMP
3062 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3063 #endif
3065 #ifdef UF_IMMUTABLE
3066 { UF_IMMUTABLE, EXT_IMMUTABLE },
3067 #endif
3069 #ifdef UF_APPEND
3070 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3071 #endif
3073 #ifdef UF_HIDDEN
3074 { UF_HIDDEN, EXT_HIDDEN },
3075 #endif
3077 /* Do not remove. We need to guarantee that this array has at least one
3078 * entry to build on HP-UX.
3080 { 0, 0 }
3084 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3085 uint32 *smb_fflags, uint32 *smb_fmask)
3087 #ifdef HAVE_STAT_ST_FLAGS
3088 int i;
3090 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3091 *smb_fmask |= info2_flags_map[i].smb_fflag;
3092 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3093 *smb_fflags |= info2_flags_map[i].smb_fflag;
3096 #endif /* HAVE_STAT_ST_FLAGS */
3099 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3100 const uint32 smb_fflags,
3101 const uint32 smb_fmask,
3102 int *stat_fflags)
3104 #ifdef HAVE_STAT_ST_FLAGS
3105 uint32 max_fmask = 0;
3106 int i;
3108 *stat_fflags = psbuf->st_flags;
3110 /* For each flags requested in smb_fmask, check the state of the
3111 * corresponding flag in smb_fflags and set or clear the matching
3112 * stat flag.
3115 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3116 max_fmask |= info2_flags_map[i].smb_fflag;
3117 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3118 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3119 *stat_fflags |= info2_flags_map[i].stat_fflag;
3120 } else {
3121 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3126 /* If smb_fmask is asking to set any bits that are not supported by
3127 * our flag mappings, we should fail.
3129 if ((smb_fmask & max_fmask) != smb_fmask) {
3130 return False;
3133 return True;
3134 #else
3135 return False;
3136 #endif /* HAVE_STAT_ST_FLAGS */
3140 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3141 * of file flags and birth (create) time.
3143 static char *store_file_unix_basic_info2(connection_struct *conn,
3144 char *pdata,
3145 files_struct *fsp,
3146 const SMB_STRUCT_STAT *psbuf)
3148 uint32 file_flags = 0;
3149 uint32 flags_mask = 0;
3151 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3153 /* Create (birth) time 64 bit */
3154 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3155 pdata += 8;
3157 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3158 SIVAL(pdata, 0, file_flags); /* flags */
3159 SIVAL(pdata, 4, flags_mask); /* mask */
3160 pdata += 8;
3162 return pdata;
3165 /****************************************************************************
3166 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3167 file name or file id).
3168 ****************************************************************************/
3170 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3171 unsigned int tran_call,
3172 char **pparams, int total_params, char **ppdata, int total_data,
3173 unsigned int max_data_bytes)
3175 char *params = *pparams;
3176 char *pdata = *ppdata;
3177 uint16 info_level;
3178 int mode=0;
3179 int nlink;
3180 SMB_OFF_T file_size=0;
3181 SMB_BIG_UINT allocation_size=0;
3182 unsigned int data_size = 0;
3183 unsigned int param_size = 2;
3184 SMB_STRUCT_STAT sbuf;
3185 pstring fname, dos_fname;
3186 char *fullpathname;
3187 char *base_name;
3188 char *p;
3189 SMB_OFF_T pos = 0;
3190 BOOL delete_pending = False;
3191 int len;
3192 time_t create_time, mtime, atime;
3193 struct timespec create_time_ts, mtime_ts, atime_ts;
3194 files_struct *fsp = NULL;
3195 TALLOC_CTX *data_ctx = NULL;
3196 struct ea_list *ea_list = NULL;
3197 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3198 char *lock_data = NULL;
3200 if (!params)
3201 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3203 ZERO_STRUCT(sbuf);
3205 if (tran_call == TRANSACT2_QFILEINFO) {
3206 if (total_params < 4) {
3207 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3210 fsp = file_fsp(params,0);
3211 info_level = SVAL(params,2);
3213 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3215 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3216 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3219 if(fsp && (fsp->fake_file_handle)) {
3221 * This is actually for the QUOTA_FAKE_FILE --metze
3224 pstrcpy(fname, fsp->fsp_name);
3225 /* We know this name is ok, it's already passed the checks. */
3227 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3229 * This is actually a QFILEINFO on a directory
3230 * handle (returned from an NT SMB). NT5.0 seems
3231 * to do this call. JRA.
3233 /* We know this name is ok, it's already passed the checks. */
3234 pstrcpy(fname, fsp->fsp_name);
3236 if (INFO_LEVEL_IS_UNIX(info_level)) {
3237 /* Always do lstat for UNIX calls. */
3238 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3239 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3240 return UNIXERROR(ERRDOS,ERRbadpath);
3242 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3243 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3244 return UNIXERROR(ERRDOS,ERRbadpath);
3247 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3248 } else {
3250 * Original code - this is an open file.
3252 CHECK_FSP(fsp,conn);
3254 pstrcpy(fname, fsp->fsp_name);
3255 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3256 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3257 return(UNIXERROR(ERRDOS,ERRbadfid));
3259 pos = fsp->fh->position_information;
3260 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3261 access_mask = fsp->access_mask;
3263 } else {
3264 NTSTATUS status = NT_STATUS_OK;
3266 /* qpathinfo */
3267 if (total_params < 7) {
3268 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3271 info_level = SVAL(params,0);
3273 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3275 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3276 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3279 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3280 if (!NT_STATUS_IS_OK(status)) {
3281 return ERROR_NT(status);
3284 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3285 if (!NT_STATUS_IS_OK(status)) {
3286 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3287 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3289 return ERROR_NT(status);
3292 status = unix_convert(conn, fname, False, NULL, &sbuf);
3293 if (!NT_STATUS_IS_OK(status)) {
3294 return ERROR_NT(status);
3296 status = check_name(conn, fname);
3297 if (!NT_STATUS_IS_OK(status)) {
3298 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3299 return ERROR_NT(status);
3302 if (INFO_LEVEL_IS_UNIX(info_level)) {
3303 /* Always do lstat for UNIX calls. */
3304 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3305 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3306 return UNIXERROR(ERRDOS,ERRbadpath);
3308 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3309 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3310 return UNIXERROR(ERRDOS,ERRbadpath);
3313 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3314 if (delete_pending) {
3315 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3319 nlink = sbuf.st_nlink;
3321 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3322 /* NTFS does not seem to count ".." */
3323 nlink -= 1;
3326 if ((nlink > 0) && delete_pending) {
3327 nlink -= 1;
3330 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3331 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3334 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3335 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3337 p = strrchr_m(fname,'/');
3338 if (!p)
3339 base_name = fname;
3340 else
3341 base_name = p+1;
3343 mode = dos_mode(conn,fname,&sbuf);
3344 if (!mode)
3345 mode = FILE_ATTRIBUTE_NORMAL;
3347 fullpathname = fname;
3348 if (!(mode & aDIR))
3349 file_size = get_file_size(sbuf);
3351 /* Pull out any data sent here before we realloc. */
3352 switch (info_level) {
3353 case SMB_INFO_QUERY_EAS_FROM_LIST:
3355 /* Pull any EA list from the data portion. */
3356 uint32 ea_size;
3358 if (total_data < 4) {
3359 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3361 ea_size = IVAL(pdata,0);
3363 if (total_data > 0 && ea_size != total_data) {
3364 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3365 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3366 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3369 if (!lp_ea_support(SNUM(conn))) {
3370 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3373 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3374 return ERROR_NT(NT_STATUS_NO_MEMORY);
3377 /* Pull out the list of names. */
3378 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3379 if (!ea_list) {
3380 talloc_destroy(data_ctx);
3381 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3383 break;
3386 case SMB_QUERY_POSIX_LOCK:
3388 if (fsp == NULL || fsp->fh->fd == -1) {
3389 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3392 if (total_data != POSIX_LOCK_DATA_SIZE) {
3393 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3396 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3397 return ERROR_NT(NT_STATUS_NO_MEMORY);
3400 /* Copy the lock range data. */
3401 lock_data = (char *)talloc_memdup(
3402 data_ctx, pdata, total_data);
3403 if (!lock_data) {
3404 talloc_destroy(data_ctx);
3405 return ERROR_NT(NT_STATUS_NO_MEMORY);
3408 default:
3409 break;
3412 *pparams = (char *)SMB_REALLOC(*pparams,2);
3413 if (*pparams == NULL) {
3414 talloc_destroy(data_ctx);
3415 return ERROR_NT(NT_STATUS_NO_MEMORY);
3417 params = *pparams;
3418 SSVAL(params,0,0);
3419 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3420 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3421 if (*ppdata == NULL ) {
3422 talloc_destroy(data_ctx);
3423 return ERROR_NT(NT_STATUS_NO_MEMORY);
3425 pdata = *ppdata;
3427 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3428 mtime_ts = get_mtimespec(&sbuf);
3429 atime_ts = get_atimespec(&sbuf);
3431 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3433 if (fsp) {
3434 if (!null_timespec(fsp->pending_modtime)) {
3435 /* the pending modtime overrides the current modtime */
3436 mtime_ts = fsp->pending_modtime;
3438 } else {
3439 /* Do we have this path open ? */
3440 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3441 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3442 /* the pending modtime overrides the current modtime */
3443 mtime_ts = fsp1->pending_modtime;
3445 if (fsp1 && fsp1->initial_allocation_size) {
3446 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3450 if (lp_dos_filetime_resolution(SNUM(conn))) {
3451 dos_filetime_timespec(&create_time_ts);
3452 dos_filetime_timespec(&mtime_ts);
3453 dos_filetime_timespec(&atime_ts);
3456 create_time = convert_timespec_to_time_t(create_time_ts);
3457 mtime = convert_timespec_to_time_t(mtime_ts);
3458 atime = convert_timespec_to_time_t(atime_ts);
3460 /* NT expects the name to be in an exact form of the *full*
3461 filename. See the trans2 torture test */
3462 if (strequal(base_name,".")) {
3463 pstrcpy(dos_fname, "\\");
3464 } else {
3465 pstr_sprintf(dos_fname, "\\%s", fname);
3466 string_replace(dos_fname, '/', '\\');
3469 switch (info_level) {
3470 case SMB_INFO_STANDARD:
3471 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3472 data_size = 22;
3473 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3474 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3475 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3476 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3477 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3478 SSVAL(pdata,l1_attrFile,mode);
3479 break;
3481 case SMB_INFO_QUERY_EA_SIZE:
3483 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3484 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3485 data_size = 26;
3486 srv_put_dos_date2(pdata,0,create_time);
3487 srv_put_dos_date2(pdata,4,atime);
3488 srv_put_dos_date2(pdata,8,mtime); /* write time */
3489 SIVAL(pdata,12,(uint32)file_size);
3490 SIVAL(pdata,16,(uint32)allocation_size);
3491 SSVAL(pdata,20,mode);
3492 SIVAL(pdata,22,ea_size);
3493 break;
3496 case SMB_INFO_IS_NAME_VALID:
3497 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3498 if (tran_call == TRANSACT2_QFILEINFO) {
3499 /* os/2 needs this ? really ?*/
3500 return ERROR_DOS(ERRDOS,ERRbadfunc);
3502 data_size = 0;
3503 param_size = 0;
3504 break;
3506 case SMB_INFO_QUERY_EAS_FROM_LIST:
3508 size_t total_ea_len = 0;
3509 struct ea_list *ea_file_list = NULL;
3511 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3513 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3514 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3516 if (!ea_list || (total_ea_len > data_size)) {
3517 talloc_destroy(data_ctx);
3518 data_size = 4;
3519 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3520 break;
3523 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3524 talloc_destroy(data_ctx);
3525 break;
3528 case SMB_INFO_QUERY_ALL_EAS:
3530 /* We have data_size bytes to put EA's into. */
3531 size_t total_ea_len = 0;
3533 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3535 data_ctx = talloc_init("ea_ctx");
3536 if (!data_ctx) {
3537 return ERROR_NT(NT_STATUS_NO_MEMORY);
3540 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3541 if (!ea_list || (total_ea_len > data_size)) {
3542 talloc_destroy(data_ctx);
3543 data_size = 4;
3544 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3545 break;
3548 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3549 talloc_destroy(data_ctx);
3550 break;
3553 case SMB_FILE_BASIC_INFORMATION:
3554 case SMB_QUERY_FILE_BASIC_INFO:
3556 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3557 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3558 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3559 } else {
3560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3561 data_size = 40;
3562 SIVAL(pdata,36,0);
3564 put_long_date_timespec(pdata,create_time_ts);
3565 put_long_date_timespec(pdata+8,atime_ts);
3566 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3567 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3568 SIVAL(pdata,32,mode);
3570 DEBUG(5,("SMB_QFBI - "));
3571 DEBUG(5,("create: %s ", ctime(&create_time)));
3572 DEBUG(5,("access: %s ", ctime(&atime)));
3573 DEBUG(5,("write: %s ", ctime(&mtime)));
3574 DEBUG(5,("change: %s ", ctime(&mtime)));
3575 DEBUG(5,("mode: %x\n", mode));
3576 break;
3578 case SMB_FILE_STANDARD_INFORMATION:
3579 case SMB_QUERY_FILE_STANDARD_INFO:
3581 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3582 data_size = 24;
3583 SOFF_T(pdata,0,allocation_size);
3584 SOFF_T(pdata,8,file_size);
3585 SIVAL(pdata,16,nlink);
3586 SCVAL(pdata,20,delete_pending?1:0);
3587 SCVAL(pdata,21,(mode&aDIR)?1:0);
3588 SSVAL(pdata,22,0); /* Padding. */
3589 break;
3591 case SMB_FILE_EA_INFORMATION:
3592 case SMB_QUERY_FILE_EA_INFO:
3594 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3595 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3596 data_size = 4;
3597 SIVAL(pdata,0,ea_size);
3598 break;
3601 /* Get the 8.3 name - used if NT SMB was negotiated. */
3602 case SMB_QUERY_FILE_ALT_NAME_INFO:
3603 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3605 pstring short_name;
3607 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3608 pstrcpy(short_name,base_name);
3609 /* Mangle if not already 8.3 */
3610 if(!mangle_is_8_3(short_name, True, conn->params)) {
3611 mangle_map(short_name,True,True,conn->params);
3613 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3614 data_size = 4 + len;
3615 SIVAL(pdata,0,len);
3616 break;
3619 case SMB_QUERY_FILE_NAME_INFO:
3621 this must be *exactly* right for ACLs on mapped drives to work
3623 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3624 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3625 data_size = 4 + len;
3626 SIVAL(pdata,0,len);
3627 break;
3629 case SMB_FILE_ALLOCATION_INFORMATION:
3630 case SMB_QUERY_FILE_ALLOCATION_INFO:
3631 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3632 data_size = 8;
3633 SOFF_T(pdata,0,allocation_size);
3634 break;
3636 case SMB_FILE_END_OF_FILE_INFORMATION:
3637 case SMB_QUERY_FILE_END_OF_FILEINFO:
3638 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3639 data_size = 8;
3640 SOFF_T(pdata,0,file_size);
3641 break;
3643 case SMB_QUERY_FILE_ALL_INFO:
3644 case SMB_FILE_ALL_INFORMATION:
3646 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3647 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3648 put_long_date_timespec(pdata,create_time_ts);
3649 put_long_date_timespec(pdata+8,atime_ts);
3650 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3651 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3652 SIVAL(pdata,32,mode);
3653 SIVAL(pdata,36,0); /* padding. */
3654 pdata += 40;
3655 SOFF_T(pdata,0,allocation_size);
3656 SOFF_T(pdata,8,file_size);
3657 SIVAL(pdata,16,nlink);
3658 SCVAL(pdata,20,delete_pending);
3659 SCVAL(pdata,21,(mode&aDIR)?1:0);
3660 SSVAL(pdata,22,0);
3661 pdata += 24;
3662 SIVAL(pdata,0,ea_size);
3663 pdata += 4; /* EA info */
3664 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3665 SIVAL(pdata,0,len);
3666 pdata += 4 + len;
3667 data_size = PTR_DIFF(pdata,(*ppdata));
3668 break;
3670 case SMB_FILE_INTERNAL_INFORMATION:
3671 /* This should be an index number - looks like
3672 dev/ino to me :-)
3674 I think this causes us to fail the IFSKIT
3675 BasicFileInformationTest. -tpot */
3677 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3678 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3679 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3680 data_size = 8;
3681 break;
3683 case SMB_FILE_ACCESS_INFORMATION:
3684 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3685 SIVAL(pdata,0,access_mask);
3686 data_size = 4;
3687 break;
3689 case SMB_FILE_NAME_INFORMATION:
3690 /* Pathname with leading '\'. */
3692 size_t byte_len;
3693 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3694 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3695 SIVAL(pdata,0,byte_len);
3696 data_size = 4 + byte_len;
3697 break;
3700 case SMB_FILE_DISPOSITION_INFORMATION:
3701 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3702 data_size = 1;
3703 SCVAL(pdata,0,delete_pending);
3704 break;
3706 case SMB_FILE_POSITION_INFORMATION:
3707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3708 data_size = 8;
3709 SOFF_T(pdata,0,pos);
3710 break;
3712 case SMB_FILE_MODE_INFORMATION:
3713 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3714 SIVAL(pdata,0,mode);
3715 data_size = 4;
3716 break;
3718 case SMB_FILE_ALIGNMENT_INFORMATION:
3719 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3720 SIVAL(pdata,0,0); /* No alignment needed. */
3721 data_size = 4;
3722 break;
3724 #if 0
3726 * NT4 server just returns "invalid query" to this - if we try to answer
3727 * it then NTws gets a BSOD! (tridge).
3728 * W2K seems to want this. JRA.
3730 case SMB_QUERY_FILE_STREAM_INFO:
3731 #endif
3732 case SMB_FILE_STREAM_INFORMATION:
3733 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3734 if (mode & aDIR) {
3735 data_size = 0;
3736 } else {
3737 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3738 SIVAL(pdata,0,0); /* ??? */
3739 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3740 SOFF_T(pdata,8,file_size);
3741 SIVAL(pdata,16,allocation_size);
3742 SIVAL(pdata,20,0); /* ??? */
3743 data_size = 24 + byte_len;
3745 break;
3747 case SMB_QUERY_COMPRESSION_INFO:
3748 case SMB_FILE_COMPRESSION_INFORMATION:
3749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3750 SOFF_T(pdata,0,file_size);
3751 SIVAL(pdata,8,0); /* ??? */
3752 SIVAL(pdata,12,0); /* ??? */
3753 data_size = 16;
3754 break;
3756 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3757 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3758 put_long_date_timespec(pdata,create_time_ts);
3759 put_long_date_timespec(pdata+8,atime_ts);
3760 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3761 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3762 SIVAL(pdata,32,allocation_size);
3763 SOFF_T(pdata,40,file_size);
3764 SIVAL(pdata,48,mode);
3765 SIVAL(pdata,52,0); /* ??? */
3766 data_size = 56;
3767 break;
3769 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3770 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3771 SIVAL(pdata,0,mode);
3772 SIVAL(pdata,4,0);
3773 data_size = 8;
3774 break;
3777 * CIFS UNIX Extensions.
3780 case SMB_QUERY_FILE_UNIX_BASIC:
3782 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3783 data_size = PTR_DIFF(pdata,(*ppdata));
3786 int i;
3787 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3789 for (i=0; i<100; i++)
3790 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3791 DEBUG(4,("\n"));
3794 break;
3796 case SMB_QUERY_FILE_UNIX_INFO2:
3798 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3799 data_size = PTR_DIFF(pdata,(*ppdata));
3802 int i;
3803 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3805 for (i=0; i<100; i++)
3806 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3807 DEBUG(4,("\n"));
3810 break;
3812 case SMB_QUERY_FILE_UNIX_LINK:
3814 pstring buffer;
3816 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3817 #ifdef S_ISLNK
3818 if(!S_ISLNK(sbuf.st_mode))
3819 return(UNIXERROR(ERRSRV,ERRbadlink));
3820 #else
3821 return(UNIXERROR(ERRDOS,ERRbadlink));
3822 #endif
3823 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3824 if (len == -1)
3825 return(UNIXERROR(ERRDOS,ERRnoaccess));
3826 buffer[len] = 0;
3827 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3828 pdata += len;
3829 data_size = PTR_DIFF(pdata,(*ppdata));
3831 break;
3834 #if defined(HAVE_POSIX_ACLS)
3835 case SMB_QUERY_POSIX_ACL:
3837 SMB_ACL_T file_acl = NULL;
3838 SMB_ACL_T def_acl = NULL;
3839 uint16 num_file_acls = 0;
3840 uint16 num_def_acls = 0;
3842 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3843 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3844 } else {
3845 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3848 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3849 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3850 fname ));
3851 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3854 if (S_ISDIR(sbuf.st_mode)) {
3855 if (fsp && fsp->is_directory) {
3856 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3857 } else {
3858 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3860 def_acl = free_empty_sys_acl(conn, def_acl);
3863 num_file_acls = count_acl_entries(conn, file_acl);
3864 num_def_acls = count_acl_entries(conn, def_acl);
3866 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3867 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3868 data_size,
3869 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3870 SMB_POSIX_ACL_HEADER_SIZE) ));
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_BUFFER_TOO_SMALL);
3880 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3881 SSVAL(pdata,2,num_file_acls);
3882 SSVAL(pdata,4,num_def_acls);
3883 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3884 if (file_acl) {
3885 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3887 if (def_acl) {
3888 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3890 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3892 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3893 if (file_acl) {
3894 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3896 if (def_acl) {
3897 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3899 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3902 if (file_acl) {
3903 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3905 if (def_acl) {
3906 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3908 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3909 break;
3911 #endif
3914 case SMB_QUERY_POSIX_LOCK:
3916 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3917 SMB_BIG_UINT count;
3918 SMB_BIG_UINT offset;
3919 uint32 lock_pid;
3920 enum brl_type lock_type;
3922 if (total_data != POSIX_LOCK_DATA_SIZE) {
3923 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3926 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3927 case POSIX_LOCK_TYPE_READ:
3928 lock_type = READ_LOCK;
3929 break;
3930 case POSIX_LOCK_TYPE_WRITE:
3931 lock_type = WRITE_LOCK;
3932 break;
3933 case POSIX_LOCK_TYPE_UNLOCK:
3934 default:
3935 /* There's no point in asking for an unlock... */
3936 talloc_destroy(data_ctx);
3937 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3940 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3941 #if defined(HAVE_LONGLONG)
3942 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3943 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3944 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3945 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3946 #else /* HAVE_LONGLONG */
3947 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3948 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3949 #endif /* HAVE_LONGLONG */
3951 status = query_lock(fsp,
3952 &lock_pid,
3953 &count,
3954 &offset,
3955 &lock_type,
3956 POSIX_LOCK);
3958 if (ERROR_WAS_LOCK_DENIED(status)) {
3959 /* Here we need to report who has it locked... */
3960 data_size = POSIX_LOCK_DATA_SIZE;
3962 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3963 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3964 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3965 #if defined(HAVE_LONGLONG)
3966 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3967 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3968 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3969 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3970 #else /* HAVE_LONGLONG */
3971 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3972 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3973 #endif /* HAVE_LONGLONG */
3975 } else if (NT_STATUS_IS_OK(status)) {
3976 /* For success we just return a copy of what we sent
3977 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3978 data_size = POSIX_LOCK_DATA_SIZE;
3979 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3980 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3981 } else {
3982 return ERROR_NT(status);
3984 break;
3987 default:
3988 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3991 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3993 return(-1);
3996 /****************************************************************************
3997 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3998 code.
3999 ****************************************************************************/
4001 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4003 SMB_STRUCT_STAT sbuf1, sbuf2;
4004 pstring last_component_oldname;
4005 pstring last_component_newname;
4006 NTSTATUS status = NT_STATUS_OK;
4008 ZERO_STRUCT(sbuf1);
4009 ZERO_STRUCT(sbuf2);
4011 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 return status;
4016 status = check_name(conn, oldname);
4017 if (!NT_STATUS_IS_OK(status)) {
4018 return status;
4021 /* source must already exist. */
4022 if (!VALID_STAT(sbuf1)) {
4023 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4026 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4027 if (!NT_STATUS_IS_OK(status)) {
4028 return status;
4031 status = check_name(conn, newname);
4032 if (!NT_STATUS_IS_OK(status)) {
4033 return status;
4036 /* Disallow if newname already exists. */
4037 if (VALID_STAT(sbuf2)) {
4038 return NT_STATUS_OBJECT_NAME_COLLISION;
4041 /* No links from a directory. */
4042 if (S_ISDIR(sbuf1.st_mode)) {
4043 return NT_STATUS_FILE_IS_A_DIRECTORY;
4046 /* Ensure this is within the share. */
4047 status = reduce_name(conn, oldname);
4048 if (!NT_STATUS_IS_OK(status)) {
4049 return status;
4052 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4054 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4055 status = map_nt_error_from_unix(errno);
4056 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4057 nt_errstr(status), newname, oldname));
4060 return status;
4063 /****************************************************************************
4064 Deal with setting the time from any of the setfilepathinfo functions.
4065 ****************************************************************************/
4067 static NTSTATUS smb_set_file_time(connection_struct *conn,
4068 files_struct *fsp,
4069 const char *fname,
4070 const SMB_STRUCT_STAT *psbuf,
4071 struct timespec ts[2])
4073 uint32 action =
4074 FILE_NOTIFY_CHANGE_LAST_ACCESS
4075 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4078 if (!VALID_STAT(*psbuf)) {
4079 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4082 /* get some defaults (no modifications) if any info is zero or -1. */
4083 if (null_timespec(ts[0])) {
4084 ts[0] = get_atimespec(psbuf);
4085 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4088 if (null_timespec(ts[1])) {
4089 ts[1] = get_mtimespec(psbuf);
4090 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4093 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4094 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4097 * Try and set the times of this file if
4098 * they are different from the current values.
4102 struct timespec mts = get_mtimespec(psbuf);
4103 struct timespec ats = get_atimespec(psbuf);
4104 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4105 return NT_STATUS_OK;
4109 if(fsp != NULL) {
4111 * This was a setfileinfo on an open file.
4112 * NT does this a lot. We also need to
4113 * set the time here, as it can be read by
4114 * FindFirst/FindNext and with the patch for bug #2045
4115 * in smbd/fileio.c it ensures that this timestamp is
4116 * kept sticky even after a write. We save the request
4117 * away and will set it on file close and after a write. JRA.
4120 if (!null_timespec(ts[1])) {
4121 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4122 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4123 fsp_set_pending_modtime(fsp, ts[1]);
4127 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4129 if(file_ntimes(conn, fname, ts)!=0) {
4130 return map_nt_error_from_unix(errno);
4132 if (action != 0) {
4133 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4135 return NT_STATUS_OK;
4138 /****************************************************************************
4139 Deal with setting the dosmode from any of the setfilepathinfo functions.
4140 ****************************************************************************/
4142 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4143 const char *fname,
4144 SMB_STRUCT_STAT *psbuf,
4145 uint32 dosmode)
4147 if (!VALID_STAT(*psbuf)) {
4148 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4151 if (dosmode) {
4152 if (S_ISDIR(psbuf->st_mode)) {
4153 dosmode |= aDIR;
4154 } else {
4155 dosmode &= ~aDIR;
4159 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4161 /* check the mode isn't different, before changing it */
4162 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4164 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4165 fname, (unsigned int)dosmode ));
4167 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4168 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4169 fname, strerror(errno)));
4170 return map_nt_error_from_unix(errno);
4173 return NT_STATUS_OK;
4176 /****************************************************************************
4177 Deal with setting the size from any of the setfilepathinfo functions.
4178 ****************************************************************************/
4180 static NTSTATUS smb_set_file_size(connection_struct *conn,
4181 files_struct *fsp,
4182 const char *fname,
4183 SMB_STRUCT_STAT *psbuf,
4184 SMB_OFF_T size)
4186 NTSTATUS status = NT_STATUS_OK;
4187 files_struct *new_fsp = NULL;
4189 if (!VALID_STAT(*psbuf)) {
4190 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4193 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4195 if (size == get_file_size(*psbuf)) {
4196 return NT_STATUS_OK;
4199 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4200 fname, (double)size ));
4202 if (fsp && fsp->fh->fd != -1) {
4203 /* Handle based call. */
4204 if (vfs_set_filelen(fsp, size) == -1) {
4205 return map_nt_error_from_unix(errno);
4207 return NT_STATUS_OK;
4210 status = open_file_ntcreate(conn, fname, psbuf,
4211 FILE_WRITE_DATA,
4212 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4213 FILE_OPEN,
4215 FILE_ATTRIBUTE_NORMAL,
4216 FORCE_OPLOCK_BREAK_TO_NONE,
4217 NULL, &new_fsp);
4219 if (!NT_STATUS_IS_OK(status)) {
4220 /* NB. We check for open_was_deferred in the caller. */
4221 return status;
4224 if (vfs_set_filelen(new_fsp, size) == -1) {
4225 status = map_nt_error_from_unix(errno);
4226 close_file(new_fsp,NORMAL_CLOSE);
4227 return status;
4230 close_file(new_fsp,NORMAL_CLOSE);
4231 return NT_STATUS_OK;
4234 /****************************************************************************
4235 Deal with SMB_INFO_SET_EA.
4236 ****************************************************************************/
4238 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4239 const char *pdata,
4240 int total_data,
4241 files_struct *fsp,
4242 const char *fname)
4244 struct ea_list *ea_list = NULL;
4245 TALLOC_CTX *ctx = NULL;
4246 NTSTATUS status = NT_STATUS_OK;
4248 if (total_data < 10) {
4250 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4251 length. They seem to have no effect. Bug #3212. JRA */
4253 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4254 /* We're done. We only get EA info in this call. */
4255 return NT_STATUS_OK;
4258 return NT_STATUS_INVALID_PARAMETER;
4261 if (IVAL(pdata,0) > total_data) {
4262 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4263 IVAL(pdata,0), (unsigned int)total_data));
4264 return NT_STATUS_INVALID_PARAMETER;
4267 ctx = talloc_init("SMB_INFO_SET_EA");
4268 if (!ctx) {
4269 return NT_STATUS_NO_MEMORY;
4271 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4272 if (!ea_list) {
4273 talloc_destroy(ctx);
4274 return NT_STATUS_INVALID_PARAMETER;
4276 status = set_ea(conn, fsp, fname, ea_list);
4277 talloc_destroy(ctx);
4279 return status;
4282 /****************************************************************************
4283 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4284 ****************************************************************************/
4286 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4287 const char *pdata,
4288 int total_data,
4289 files_struct *fsp,
4290 const char *fname,
4291 SMB_STRUCT_STAT *psbuf)
4293 NTSTATUS status = NT_STATUS_OK;
4294 BOOL delete_on_close;
4295 uint32 dosmode = 0;
4297 if (total_data < 1) {
4298 return NT_STATUS_INVALID_PARAMETER;
4301 if (fsp == NULL) {
4302 return NT_STATUS_INVALID_HANDLE;
4305 delete_on_close = (CVAL(pdata,0) ? True : False);
4306 dosmode = dos_mode(conn, fname, psbuf);
4308 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4309 "delete_on_close = %u\n",
4310 fsp->fsp_name,
4311 (unsigned int)dosmode,
4312 (unsigned int)delete_on_close ));
4314 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4316 if (!NT_STATUS_IS_OK(status)) {
4317 return status;
4320 /* The set is across all open files on this dev/inode pair. */
4321 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4322 return NT_STATUS_ACCESS_DENIED;
4324 return NT_STATUS_OK;
4327 /****************************************************************************
4328 Deal with SMB_FILE_POSITION_INFORMATION.
4329 ****************************************************************************/
4331 static NTSTATUS smb_file_position_information(connection_struct *conn,
4332 const char *pdata,
4333 int total_data,
4334 files_struct *fsp)
4336 SMB_BIG_UINT position_information;
4338 if (total_data < 8) {
4339 return NT_STATUS_INVALID_PARAMETER;
4342 if (fsp == NULL) {
4343 /* Ignore on pathname based set. */
4344 return NT_STATUS_OK;
4347 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4348 #ifdef LARGE_SMB_OFF_T
4349 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4350 #else /* LARGE_SMB_OFF_T */
4351 if (IVAL(pdata,4) != 0) {
4352 /* more than 32 bits? */
4353 return NT_STATUS_INVALID_PARAMETER;
4355 #endif /* LARGE_SMB_OFF_T */
4357 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4358 fsp->fsp_name, (double)position_information ));
4359 fsp->fh->position_information = position_information;
4360 return NT_STATUS_OK;
4363 /****************************************************************************
4364 Deal with SMB_FILE_MODE_INFORMATION.
4365 ****************************************************************************/
4367 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4368 const char *pdata,
4369 int total_data)
4371 uint32 mode;
4373 if (total_data < 4) {
4374 return NT_STATUS_INVALID_PARAMETER;
4376 mode = IVAL(pdata,0);
4377 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4378 return NT_STATUS_INVALID_PARAMETER;
4380 return NT_STATUS_OK;
4383 /****************************************************************************
4384 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4385 ****************************************************************************/
4387 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4388 char *inbuf,
4389 const char *pdata,
4390 int total_data,
4391 const char *fname)
4393 pstring link_target;
4394 const char *newname = fname;
4395 NTSTATUS status = NT_STATUS_OK;
4397 /* Set a symbolic link. */
4398 /* Don't allow this if follow links is false. */
4400 if (total_data == 0) {
4401 return NT_STATUS_INVALID_PARAMETER;
4404 if (!lp_symlinks(SNUM(conn))) {
4405 return NT_STATUS_ACCESS_DENIED;
4408 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4410 /* !widelinks forces the target path to be within the share. */
4411 /* This means we can interpret the target as a pathname. */
4412 if (!lp_widelinks(SNUM(conn))) {
4413 pstring rel_name;
4414 char *last_dirp = NULL;
4416 if (*link_target == '/') {
4417 /* No absolute paths allowed. */
4418 return NT_STATUS_ACCESS_DENIED;
4420 pstrcpy(rel_name, newname);
4421 last_dirp = strrchr_m(rel_name, '/');
4422 if (last_dirp) {
4423 last_dirp[1] = '\0';
4424 } else {
4425 pstrcpy(rel_name, "./");
4427 pstrcat(rel_name, link_target);
4429 status = check_name(conn, rel_name);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 return status;
4435 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4436 newname, link_target ));
4438 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4439 return map_nt_error_from_unix(errno);
4442 return NT_STATUS_OK;
4445 /****************************************************************************
4446 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4447 ****************************************************************************/
4449 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4450 char *inbuf,
4451 char *outbuf,
4452 const char *pdata,
4453 int total_data,
4454 pstring fname)
4456 pstring oldname;
4457 NTSTATUS status = NT_STATUS_OK;
4459 /* Set a hard link. */
4460 if (total_data == 0) {
4461 return NT_STATUS_INVALID_PARAMETER;
4464 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4465 if (!NT_STATUS_IS_OK(status)) {
4466 return status;
4469 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4470 if (!NT_STATUS_IS_OK(status)) {
4471 return status;
4474 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4475 fname, oldname));
4477 return hardlink_internals(conn, oldname, fname);
4480 /****************************************************************************
4481 Deal with SMB_FILE_RENAME_INFORMATION.
4482 ****************************************************************************/
4484 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4485 char *inbuf,
4486 char *outbuf,
4487 const char *pdata,
4488 int total_data,
4489 files_struct *fsp,
4490 pstring fname)
4492 BOOL overwrite;
4493 /* uint32 root_fid; */ /* Not used */
4494 uint32 len;
4495 pstring newname;
4496 pstring base_name;
4497 BOOL dest_has_wcard = False;
4498 NTSTATUS status = NT_STATUS_OK;
4499 char *p;
4501 if (total_data < 13) {
4502 return NT_STATUS_INVALID_PARAMETER;
4505 overwrite = (CVAL(pdata,0) ? True : False);
4506 /* root_fid = IVAL(pdata,4); */
4507 len = IVAL(pdata,8);
4509 if (len > (total_data - 12) || (len == 0)) {
4510 return NT_STATUS_INVALID_PARAMETER;
4513 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4514 if (!NT_STATUS_IS_OK(status)) {
4515 return status;
4518 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4519 if (!NT_STATUS_IS_OK(status)) {
4520 return status;
4523 /* Check the new name has no '/' characters. */
4524 if (strchr_m(newname, '/')) {
4525 return NT_STATUS_NOT_SUPPORTED;
4528 /* Create the base directory. */
4529 pstrcpy(base_name, fname);
4530 p = strrchr_m(base_name, '/');
4531 if (p) {
4532 *p = '\0';
4534 /* Append the new name. */
4535 pstrcat(base_name, "/");
4536 pstrcat(base_name, newname);
4538 if (fsp) {
4539 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4540 fsp->fnum, fsp->fsp_name, base_name ));
4541 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4542 } else {
4543 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4544 fname, newname ));
4545 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4548 return status;
4551 /****************************************************************************
4552 Deal with SMB_SET_POSIX_ACL.
4553 ****************************************************************************/
4555 #if defined(HAVE_POSIX_ACLS)
4556 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4557 const char *pdata,
4558 int total_data,
4559 files_struct *fsp,
4560 const char *fname,
4561 SMB_STRUCT_STAT *psbuf)
4563 uint16 posix_acl_version;
4564 uint16 num_file_acls;
4565 uint16 num_def_acls;
4566 BOOL valid_file_acls = True;
4567 BOOL valid_def_acls = True;
4569 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4570 return NT_STATUS_INVALID_PARAMETER;
4572 posix_acl_version = SVAL(pdata,0);
4573 num_file_acls = SVAL(pdata,2);
4574 num_def_acls = SVAL(pdata,4);
4576 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4577 valid_file_acls = False;
4578 num_file_acls = 0;
4581 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4582 valid_def_acls = False;
4583 num_def_acls = 0;
4586 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4587 return NT_STATUS_INVALID_PARAMETER;
4590 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4591 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4592 return NT_STATUS_INVALID_PARAMETER;
4595 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4596 fname ? fname : fsp->fsp_name,
4597 (unsigned int)num_file_acls,
4598 (unsigned int)num_def_acls));
4600 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4601 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4602 return map_nt_error_from_unix(errno);
4605 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4606 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4607 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4608 return map_nt_error_from_unix(errno);
4610 return NT_STATUS_OK;
4612 #endif
4614 /****************************************************************************
4615 Deal with SMB_SET_POSIX_LOCK.
4616 ****************************************************************************/
4618 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4619 char *inbuf,
4620 int length,
4621 const char *pdata,
4622 int total_data,
4623 files_struct *fsp)
4625 SMB_BIG_UINT count;
4626 SMB_BIG_UINT offset;
4627 uint32 lock_pid;
4628 BOOL blocking_lock = False;
4629 enum brl_type lock_type;
4630 NTSTATUS status = NT_STATUS_OK;
4632 if (fsp == NULL || fsp->fh->fd == -1) {
4633 return NT_STATUS_INVALID_HANDLE;
4636 if (total_data != POSIX_LOCK_DATA_SIZE) {
4637 return NT_STATUS_INVALID_PARAMETER;
4640 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4641 case POSIX_LOCK_TYPE_READ:
4642 lock_type = READ_LOCK;
4643 break;
4644 case POSIX_LOCK_TYPE_WRITE:
4645 /* Return the right POSIX-mappable error code for files opened read-only. */
4646 if (!fsp->can_write) {
4647 return NT_STATUS_INVALID_HANDLE;
4649 lock_type = WRITE_LOCK;
4650 break;
4651 case POSIX_LOCK_TYPE_UNLOCK:
4652 lock_type = UNLOCK_LOCK;
4653 break;
4654 default:
4655 return NT_STATUS_INVALID_PARAMETER;
4658 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4659 blocking_lock = False;
4660 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4661 blocking_lock = True;
4662 } else {
4663 return NT_STATUS_INVALID_PARAMETER;
4666 if (!lp_blocking_locks(SNUM(conn))) {
4667 blocking_lock = False;
4670 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4671 #if defined(HAVE_LONGLONG)
4672 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4673 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4674 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4675 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4676 #else /* HAVE_LONGLONG */
4677 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4678 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4679 #endif /* HAVE_LONGLONG */
4681 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4682 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4683 fsp->fsp_name,
4684 (unsigned int)lock_type,
4685 (unsigned int)lock_pid,
4686 (double)count,
4687 (double)offset ));
4689 if (lock_type == UNLOCK_LOCK) {
4690 status = do_unlock(fsp,
4691 lock_pid,
4692 count,
4693 offset,
4694 POSIX_LOCK);
4695 } else {
4696 struct byte_range_lock *br_lck = do_lock(fsp,
4697 lock_pid,
4698 count,
4699 offset,
4700 lock_type,
4701 POSIX_LOCK,
4702 blocking_lock,
4703 &status);
4705 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4707 * A blocking lock was requested. Package up
4708 * this smb into a queued request and push it
4709 * onto the blocking lock queue.
4711 if(push_blocking_lock_request(br_lck,
4712 inbuf, length,
4713 fsp,
4714 -1, /* infinite timeout. */
4716 lock_pid,
4717 lock_type,
4718 POSIX_LOCK,
4719 offset,
4720 count)) {
4721 TALLOC_FREE(br_lck);
4722 return status;
4725 TALLOC_FREE(br_lck);
4728 return status;
4731 /****************************************************************************
4732 Deal with SMB_INFO_STANDARD.
4733 ****************************************************************************/
4735 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4736 const char *pdata,
4737 int total_data,
4738 files_struct *fsp,
4739 const char *fname,
4740 const SMB_STRUCT_STAT *psbuf)
4742 struct timespec ts[2];
4744 if (total_data < 12) {
4745 return NT_STATUS_INVALID_PARAMETER;
4748 /* access time */
4749 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4750 /* write time */
4751 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4753 DEBUG(10,("smb_set_info_standard: file %s\n",
4754 fname ? fname : fsp->fsp_name ));
4756 return smb_set_file_time(conn,
4757 fsp,
4758 fname,
4759 psbuf,
4760 ts);
4763 /****************************************************************************
4764 Deal with SMB_SET_FILE_BASIC_INFO.
4765 ****************************************************************************/
4767 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4768 const char *pdata,
4769 int total_data,
4770 files_struct *fsp,
4771 const char *fname,
4772 SMB_STRUCT_STAT *psbuf)
4774 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4775 struct timespec write_time;
4776 struct timespec changed_time;
4777 uint32 dosmode = 0;
4778 struct timespec ts[2];
4779 NTSTATUS status = NT_STATUS_OK;
4781 if (total_data < 36) {
4782 return NT_STATUS_INVALID_PARAMETER;
4785 /* Set the attributes */
4786 dosmode = IVAL(pdata,32);
4787 status = smb_set_file_dosmode(conn,
4788 fname,
4789 psbuf,
4790 dosmode);
4791 if (!NT_STATUS_IS_OK(status)) {
4792 return status;
4795 /* Ignore create time at offset pdata. */
4797 /* access time */
4798 ts[0] = interpret_long_date(pdata+8);
4800 write_time = interpret_long_date(pdata+16);
4801 changed_time = interpret_long_date(pdata+24);
4803 /* mtime */
4804 ts[1] = timespec_min(&write_time, &changed_time);
4806 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4807 ts[1] = write_time;
4810 /* Prefer a defined time to an undefined one. */
4811 if (null_timespec(ts[1])) {
4812 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4815 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4816 fname ? fname : fsp->fsp_name ));
4818 return smb_set_file_time(conn,
4819 fsp,
4820 fname,
4821 psbuf,
4822 ts);
4825 /****************************************************************************
4826 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4827 ****************************************************************************/
4829 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4830 const char *pdata,
4831 int total_data,
4832 files_struct *fsp,
4833 const char *fname,
4834 SMB_STRUCT_STAT *psbuf)
4836 SMB_BIG_UINT allocation_size = 0;
4837 NTSTATUS status = NT_STATUS_OK;
4838 files_struct *new_fsp = NULL;
4840 if (!VALID_STAT(*psbuf)) {
4841 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4844 if (total_data < 8) {
4845 return NT_STATUS_INVALID_PARAMETER;
4848 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4849 #ifdef LARGE_SMB_OFF_T
4850 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4851 #else /* LARGE_SMB_OFF_T */
4852 if (IVAL(pdata,4) != 0) {
4853 /* more than 32 bits? */
4854 return NT_STATUS_INVALID_PARAMETER;
4856 #endif /* LARGE_SMB_OFF_T */
4858 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4859 fname, (double)allocation_size ));
4861 if (allocation_size) {
4862 allocation_size = smb_roundup(conn, allocation_size);
4865 if(allocation_size == get_file_size(*psbuf)) {
4866 return NT_STATUS_OK;
4869 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4870 fname, (double)allocation_size ));
4872 if (fsp && fsp->fh->fd != -1) {
4873 /* Open file handle. */
4874 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4875 return map_nt_error_from_unix(errno);
4877 return NT_STATUS_OK;
4880 /* Pathname or stat or directory file. */
4882 status = open_file_ntcreate(conn, fname, psbuf,
4883 FILE_WRITE_DATA,
4884 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4885 FILE_OPEN,
4887 FILE_ATTRIBUTE_NORMAL,
4888 FORCE_OPLOCK_BREAK_TO_NONE,
4889 NULL, &new_fsp);
4891 if (!NT_STATUS_IS_OK(status)) {
4892 /* NB. We check for open_was_deferred in the caller. */
4893 return status;
4895 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4896 status = map_nt_error_from_unix(errno);
4897 close_file(new_fsp,NORMAL_CLOSE);
4898 return status;
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;
5320 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5321 SSVAL(pdata,2,0); /* No fnum. */
5322 SIVAL(pdata,4,info); /* Was directory created. */
5324 switch (info_level_return) {
5325 case SMB_QUERY_FILE_UNIX_BASIC:
5326 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5327 SSVAL(pdata,10,0); /* Padding. */
5328 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5329 case SMB_QUERY_FILE_UNIX_INFO2:
5330 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5331 SSVAL(pdata,10,0); /* Padding. */
5332 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5333 default:
5334 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5335 SSVAL(pdata,10,0); /* Padding. */
5338 return status;
5341 /****************************************************************************
5342 Open/Create a file with POSIX semantics.
5343 ****************************************************************************/
5345 static NTSTATUS smb_posix_open(connection_struct *conn,
5346 char **ppdata,
5347 int total_data,
5348 const char *fname,
5349 SMB_STRUCT_STAT *psbuf,
5350 int *pdata_return_size)
5352 BOOL extended_oplock_granted = False;
5353 char *pdata = *ppdata;
5354 uint32 flags = 0;
5355 uint32 wire_open_mode = 0;
5356 uint32 raw_unixmode = 0;
5357 uint32 mod_unixmode = 0;
5358 uint32 create_disp = 0;
5359 uint32 access_mask = 0;
5360 uint32 create_options = 0;
5361 NTSTATUS status = NT_STATUS_OK;
5362 mode_t unixmode = (mode_t)0;
5363 files_struct *fsp = NULL;
5364 int oplock_request = 0;
5365 int info = 0;
5366 uint16 info_level_return = 0;
5368 if (total_data < 18) {
5369 return NT_STATUS_INVALID_PARAMETER;
5372 flags = IVAL(pdata,0);
5373 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5374 if (oplock_request) {
5375 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5378 wire_open_mode = IVAL(pdata,4);
5380 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5381 return smb_posix_mkdir(conn,
5382 ppdata,
5383 total_data,
5384 fname,
5385 psbuf,
5386 pdata_return_size);
5389 switch (wire_open_mode & SMB_ACCMODE) {
5390 case SMB_O_RDONLY:
5391 access_mask = FILE_READ_DATA;
5392 break;
5393 case SMB_O_WRONLY:
5394 access_mask = FILE_WRITE_DATA;
5395 break;
5396 case SMB_O_RDWR:
5397 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5398 break;
5399 default:
5400 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5401 (unsigned int)wire_open_mode ));
5402 return NT_STATUS_INVALID_PARAMETER;
5405 wire_open_mode &= ~SMB_ACCMODE;
5407 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5408 create_disp = FILE_CREATE;
5409 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5410 create_disp = FILE_OVERWRITE_IF;
5411 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5412 create_disp = FILE_OPEN_IF;
5413 } else {
5414 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5415 (unsigned int)wire_open_mode ));
5416 return NT_STATUS_INVALID_PARAMETER;
5419 raw_unixmode = IVAL(pdata,8);
5420 /* Next 4 bytes are not yet defined. */
5422 status = unix_perms_from_wire(conn,
5423 psbuf,
5424 raw_unixmode,
5425 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5426 &unixmode);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 return status;
5432 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5434 if (wire_open_mode & SMB_O_SYNC) {
5435 create_options |= FILE_WRITE_THROUGH;
5437 if (wire_open_mode & SMB_O_APPEND) {
5438 access_mask |= FILE_APPEND_DATA;
5440 if (wire_open_mode & SMB_O_DIRECT) {
5441 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5444 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5445 fname,
5446 (unsigned int)wire_open_mode,
5447 (unsigned int)unixmode ));
5449 status = open_file_ntcreate(conn,
5450 fname,
5451 psbuf,
5452 access_mask,
5453 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5454 create_disp,
5455 0, /* no create options yet. */
5456 mod_unixmode,
5457 oplock_request,
5458 &info,
5459 &fsp);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 return status;
5465 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5466 extended_oplock_granted = True;
5469 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5470 extended_oplock_granted = True;
5473 info_level_return = SVAL(pdata,16);
5475 /* Allocate the correct return size. */
5477 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5478 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5479 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5480 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5481 } else {
5482 *pdata_return_size = 12;
5485 /* Realloc the data size */
5486 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5487 if (*ppdata == NULL) {
5488 close_file(fsp,ERROR_CLOSE);
5489 *pdata_return_size = 0;
5490 return NT_STATUS_NO_MEMORY;
5493 if (extended_oplock_granted) {
5494 if (flags & REQUEST_BATCH_OPLOCK) {
5495 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5496 } else {
5497 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5499 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5500 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5501 } else {
5502 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5505 SSVAL(pdata,2,fsp->fnum);
5506 SIVAL(pdata,4,info); /* Was file created etc. */
5508 switch (info_level_return) {
5509 case SMB_QUERY_FILE_UNIX_BASIC:
5510 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5511 SSVAL(pdata,10,0); /* padding. */
5512 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5513 case SMB_QUERY_FILE_UNIX_INFO2:
5514 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5515 SSVAL(pdata,10,0); /* padding. */
5516 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5517 default:
5518 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5519 SSVAL(pdata,10,0); /* padding. */
5521 return NT_STATUS_OK;
5524 /****************************************************************************
5525 Delete a file with POSIX semantics.
5526 ****************************************************************************/
5528 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5529 const char *pdata,
5530 int total_data,
5531 const char *fname,
5532 SMB_STRUCT_STAT *psbuf)
5534 NTSTATUS status = NT_STATUS_OK;
5535 files_struct *fsp = NULL;
5536 uint16 flags = 0;
5537 int info = 0;
5539 if (total_data < 2) {
5540 return NT_STATUS_INVALID_PARAMETER;
5543 flags = SVAL(pdata,0);
5545 if (!VALID_STAT(*psbuf)) {
5546 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5549 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5550 !VALID_STAT_OF_DIR(*psbuf)) {
5551 return NT_STATUS_NOT_A_DIRECTORY;
5554 DEBUG(10,("smb_posix_unlink: %s %s\n",
5555 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5556 fname));
5558 if (VALID_STAT_OF_DIR(*psbuf)) {
5559 status = open_directory(conn,
5560 fname,
5561 psbuf,
5562 DELETE_ACCESS,
5563 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5564 FILE_OPEN,
5565 FILE_DELETE_ON_CLOSE,
5566 FILE_FLAG_POSIX_SEMANTICS|0777,
5567 &info,
5568 &fsp);
5569 } else {
5570 char del = 1;
5572 status = open_file_ntcreate(conn,
5573 fname,
5574 psbuf,
5575 DELETE_ACCESS,
5576 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5577 FILE_OPEN,
5579 FILE_FLAG_POSIX_SEMANTICS|0777,
5580 0, /* No oplock, but break existing ones. */
5581 &info,
5582 &fsp);
5584 * For file opens we must set the delete on close
5585 * after the open.
5588 if (!NT_STATUS_IS_OK(status)) {
5589 return status;
5592 status = smb_set_file_disposition_info(conn,
5593 &del,
5595 fsp,
5596 fname,
5597 psbuf);
5600 if (!NT_STATUS_IS_OK(status)) {
5601 return status;
5603 return close_file(fsp, NORMAL_CLOSE);
5606 /****************************************************************************
5607 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5608 ****************************************************************************/
5610 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5611 unsigned int tran_call,
5612 char **pparams, int total_params, char **ppdata, int total_data,
5613 unsigned int max_data_bytes)
5615 char *params = *pparams;
5616 char *pdata = *ppdata;
5617 uint16 info_level;
5618 SMB_STRUCT_STAT sbuf;
5619 pstring fname;
5620 files_struct *fsp = NULL;
5621 NTSTATUS status = NT_STATUS_OK;
5622 int data_return_size = 0;
5624 if (!params) {
5625 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5628 ZERO_STRUCT(sbuf);
5630 if (tran_call == TRANSACT2_SETFILEINFO) {
5631 if (total_params < 4) {
5632 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5635 fsp = file_fsp(params,0);
5636 info_level = SVAL(params,2);
5638 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5640 * This is actually a SETFILEINFO on a directory
5641 * handle (returned from an NT SMB). NT5.0 seems
5642 * to do this call. JRA.
5644 pstrcpy(fname, fsp->fsp_name);
5645 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5646 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5647 return UNIXERROR(ERRDOS,ERRbadpath);
5649 } else if (fsp && fsp->print_file) {
5651 * Doing a DELETE_ON_CLOSE should cancel a print job.
5653 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5654 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5656 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5658 SSVAL(params,0,0);
5659 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5660 return(-1);
5661 } else
5662 return (UNIXERROR(ERRDOS,ERRbadpath));
5663 } else {
5665 * Original code - this is an open file.
5667 CHECK_FSP(fsp,conn);
5669 pstrcpy(fname, fsp->fsp_name);
5671 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5672 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5673 return(UNIXERROR(ERRDOS,ERRbadfid));
5676 } else {
5677 /* set path info */
5678 if (total_params < 7) {
5679 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5682 info_level = SVAL(params,0);
5683 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5684 if (!NT_STATUS_IS_OK(status)) {
5685 return ERROR_NT(status);
5688 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5691 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5693 return ERROR_NT(status);
5696 status = unix_convert(conn, fname, False, NULL, &sbuf);
5697 if (!NT_STATUS_IS_OK(status)) {
5698 return ERROR_NT(status);
5701 status = check_name(conn, fname);
5702 if (!NT_STATUS_IS_OK(status)) {
5703 return ERROR_NT(status);
5707 * For CIFS UNIX extensions the target name may not exist.
5710 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5711 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5712 return UNIXERROR(ERRDOS,ERRbadpath);
5716 if (!CAN_WRITE(conn)) {
5717 return ERROR_DOS(ERRSRV,ERRaccess);
5720 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5721 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5724 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5725 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5727 /* Realloc the parameter size */
5728 *pparams = (char *)SMB_REALLOC(*pparams,2);
5729 if (*pparams == NULL) {
5730 return ERROR_NT(NT_STATUS_NO_MEMORY);
5732 params = *pparams;
5734 SSVAL(params,0,0);
5736 if (fsp && !null_timespec(fsp->pending_modtime)) {
5737 /* the pending modtime overrides the current modtime */
5738 set_mtimespec(&sbuf, fsp->pending_modtime);
5741 switch (info_level) {
5743 case SMB_INFO_STANDARD:
5745 status = smb_set_info_standard(conn,
5746 pdata,
5747 total_data,
5748 fsp,
5749 fname,
5750 &sbuf);
5751 break;
5754 case SMB_INFO_SET_EA:
5756 status = smb_info_set_ea(conn,
5757 pdata,
5758 total_data,
5759 fsp,
5760 fname);
5761 break;
5764 case SMB_SET_FILE_BASIC_INFO:
5765 case SMB_FILE_BASIC_INFORMATION:
5767 status = smb_set_file_basic_info(conn,
5768 pdata,
5769 total_data,
5770 fsp,
5771 fname,
5772 &sbuf);
5773 break;
5776 case SMB_FILE_ALLOCATION_INFORMATION:
5777 case SMB_SET_FILE_ALLOCATION_INFO:
5779 status = smb_set_file_allocation_info(conn,
5780 pdata,
5781 total_data,
5782 fsp,
5783 fname,
5784 &sbuf);
5785 break;
5788 case SMB_FILE_END_OF_FILE_INFORMATION:
5789 case SMB_SET_FILE_END_OF_FILE_INFO:
5791 status = smb_set_file_end_of_file_info(conn,
5792 pdata,
5793 total_data,
5794 fsp,
5795 fname,
5796 &sbuf);
5797 break;
5800 case SMB_FILE_DISPOSITION_INFORMATION:
5801 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5803 #if 0
5804 /* JRA - We used to just ignore this on a path ?
5805 * Shouldn't this be invalid level on a pathname
5806 * based call ?
5808 if (tran_call != TRANSACT2_SETFILEINFO) {
5809 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5811 #endif
5812 status = smb_set_file_disposition_info(conn,
5813 pdata,
5814 total_data,
5815 fsp,
5816 fname,
5817 &sbuf);
5818 break;
5821 case SMB_FILE_POSITION_INFORMATION:
5823 status = smb_file_position_information(conn,
5824 pdata,
5825 total_data,
5826 fsp);
5827 break;
5830 /* From tridge Samba4 :
5831 * MODE_INFORMATION in setfileinfo (I have no
5832 * idea what "mode information" on a file is - it takes a value of 0,
5833 * 2, 4 or 6. What could it be?).
5836 case SMB_FILE_MODE_INFORMATION:
5838 status = smb_file_mode_information(conn,
5839 pdata,
5840 total_data);
5841 break;
5845 * CIFS UNIX extensions.
5848 case SMB_SET_FILE_UNIX_BASIC:
5850 status = smb_set_file_unix_basic(conn,
5851 pdata,
5852 total_data,
5853 fsp,
5854 fname,
5855 &sbuf);
5856 break;
5859 case SMB_SET_FILE_UNIX_INFO2:
5861 status = smb_set_file_unix_info2(conn,
5862 pdata,
5863 total_data,
5864 fsp,
5865 fname,
5866 &sbuf);
5867 break;
5870 case SMB_SET_FILE_UNIX_LINK:
5872 if (tran_call != TRANSACT2_SETPATHINFO) {
5873 /* We must have a pathname for this. */
5874 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5876 status = smb_set_file_unix_link(conn,
5877 inbuf,
5878 pdata,
5879 total_data,
5880 fname);
5881 break;
5884 case SMB_SET_FILE_UNIX_HLINK:
5886 if (tran_call != TRANSACT2_SETPATHINFO) {
5887 /* We must have a pathname for this. */
5888 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5890 status = smb_set_file_unix_hlink(conn,
5891 inbuf,
5892 outbuf,
5893 pdata,
5894 total_data,
5895 fname);
5896 break;
5899 case SMB_FILE_RENAME_INFORMATION:
5901 status = smb_file_rename_information(conn,
5902 inbuf,
5903 outbuf,
5904 pdata,
5905 total_data,
5906 fsp,
5907 fname);
5908 break;
5911 #if defined(HAVE_POSIX_ACLS)
5912 case SMB_SET_POSIX_ACL:
5914 status = smb_set_posix_acl(conn,
5915 pdata,
5916 total_data,
5917 fsp,
5918 fname,
5919 &sbuf);
5920 break;
5922 #endif
5924 case SMB_SET_POSIX_LOCK:
5926 if (tran_call != TRANSACT2_SETFILEINFO) {
5927 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5929 status = smb_set_posix_lock(conn,
5930 inbuf,
5931 length,
5932 pdata,
5933 total_data,
5934 fsp);
5935 break;
5938 case SMB_POSIX_PATH_OPEN:
5940 if (tran_call != TRANSACT2_SETPATHINFO) {
5941 /* We must have a pathname for this. */
5942 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5945 status = smb_posix_open(conn,
5946 ppdata,
5947 total_data,
5948 fname,
5949 &sbuf,
5950 &data_return_size);
5951 break;
5954 case SMB_POSIX_PATH_UNLINK:
5956 if (tran_call != TRANSACT2_SETPATHINFO) {
5957 /* We must have a pathname for this. */
5958 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5961 status = smb_posix_unlink(conn,
5962 pdata,
5963 total_data,
5964 fname,
5965 &sbuf);
5966 break;
5969 default:
5970 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5974 if (!NT_STATUS_IS_OK(status)) {
5975 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5976 /* We have re-scheduled this call. */
5977 return -1;
5979 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5980 /* We have re-scheduled this call. */
5981 return -1;
5983 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5984 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5986 return ERROR_NT(status);
5989 SSVAL(params,0,0);
5990 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5992 return -1;
5995 /****************************************************************************
5996 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5997 ****************************************************************************/
5999 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6000 char **pparams, int total_params, char **ppdata, int total_data,
6001 unsigned int max_data_bytes)
6003 char *params = *pparams;
6004 char *pdata = *ppdata;
6005 pstring directory;
6006 SMB_STRUCT_STAT sbuf;
6007 NTSTATUS status = NT_STATUS_OK;
6008 struct ea_list *ea_list = NULL;
6010 if (!CAN_WRITE(conn))
6011 return ERROR_DOS(ERRSRV,ERRaccess);
6013 if (total_params < 5) {
6014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6017 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6018 if (!NT_STATUS_IS_OK(status)) {
6019 return ERROR_NT(status);
6022 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6024 status = unix_convert(conn, directory, False, NULL, &sbuf);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 return ERROR_NT(status);
6029 status = check_name(conn, directory);
6030 if (!NT_STATUS_IS_OK(status)) {
6031 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6032 return ERROR_NT(status);
6035 /* Any data in this call is an EA list. */
6036 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6037 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6041 * OS/2 workplace shell seems to send SET_EA requests of "null"
6042 * length (4 bytes containing IVAL 4).
6043 * They seem to have no effect. Bug #3212. JRA.
6046 if (total_data != 4) {
6047 if (total_data < 10) {
6048 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6051 if (IVAL(pdata,0) > total_data) {
6052 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6053 IVAL(pdata,0), (unsigned int)total_data));
6054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6057 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6058 total_data - 4);
6059 if (!ea_list) {
6060 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6062 } else if (IVAL(pdata,0) != 4) {
6063 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6066 status = create_directory(conn, directory);
6068 if (!NT_STATUS_IS_OK(status)) {
6069 return ERROR_NT(status);
6072 /* Try and set any given EA. */
6073 if (ea_list) {
6074 status = set_ea(conn, NULL, directory, ea_list);
6075 if (!NT_STATUS_IS_OK(status)) {
6076 return ERROR_NT(status);
6080 /* Realloc the parameter and data sizes */
6081 *pparams = (char *)SMB_REALLOC(*pparams,2);
6082 if(*pparams == NULL) {
6083 return ERROR_NT(NT_STATUS_NO_MEMORY);
6085 params = *pparams;
6087 SSVAL(params,0,0);
6089 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6091 return(-1);
6094 /****************************************************************************
6095 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6096 We don't actually do this - we just send a null response.
6097 ****************************************************************************/
6099 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6100 char **pparams, int total_params, char **ppdata, int total_data,
6101 unsigned int max_data_bytes)
6103 static uint16 fnf_handle = 257;
6104 char *params = *pparams;
6105 uint16 info_level;
6107 if (total_params < 6) {
6108 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6111 info_level = SVAL(params,4);
6112 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6114 switch (info_level) {
6115 case 1:
6116 case 2:
6117 break;
6118 default:
6119 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6122 /* Realloc the parameter and data sizes */
6123 *pparams = (char *)SMB_REALLOC(*pparams,6);
6124 if (*pparams == NULL) {
6125 return ERROR_NT(NT_STATUS_NO_MEMORY);
6127 params = *pparams;
6129 SSVAL(params,0,fnf_handle);
6130 SSVAL(params,2,0); /* No changes */
6131 SSVAL(params,4,0); /* No EA errors */
6133 fnf_handle++;
6135 if(fnf_handle == 0)
6136 fnf_handle = 257;
6138 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6140 return(-1);
6143 /****************************************************************************
6144 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6145 changes). Currently this does nothing.
6146 ****************************************************************************/
6148 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6149 char **pparams, int total_params, char **ppdata, int total_data,
6150 unsigned int max_data_bytes)
6152 char *params = *pparams;
6154 DEBUG(3,("call_trans2findnotifynext\n"));
6156 /* Realloc the parameter and data sizes */
6157 *pparams = (char *)SMB_REALLOC(*pparams,4);
6158 if (*pparams == NULL) {
6159 return ERROR_NT(NT_STATUS_NO_MEMORY);
6161 params = *pparams;
6163 SSVAL(params,0,0); /* No changes */
6164 SSVAL(params,2,0); /* No EA errors */
6166 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6168 return(-1);
6171 /****************************************************************************
6172 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6173 ****************************************************************************/
6175 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6176 char **pparams, int total_params, char **ppdata, int total_data,
6177 unsigned int max_data_bytes)
6179 char *params = *pparams;
6180 pstring pathname;
6181 int reply_size = 0;
6182 int max_referral_level;
6184 DEBUG(10,("call_trans2getdfsreferral\n"));
6186 if (total_params < 3) {
6187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6190 max_referral_level = SVAL(params,0);
6192 if(!lp_host_msdfs())
6193 return ERROR_DOS(ERRDOS,ERRbadfunc);
6195 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6196 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6197 return UNIXERROR(ERRDOS,ERRbadfile);
6199 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6200 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6202 return(-1);
6205 #define LMCAT_SPL 0x53
6206 #define LMFUNC_GETJOBID 0x60
6208 /****************************************************************************
6209 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6210 ****************************************************************************/
6212 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6213 char **pparams, int total_params, char **ppdata, int total_data,
6214 unsigned int max_data_bytes)
6216 char *pdata = *ppdata;
6217 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6219 /* check for an invalid fid before proceeding */
6221 if (!fsp)
6222 return(ERROR_DOS(ERRDOS,ERRbadfid));
6224 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6225 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6226 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6227 if (*ppdata == NULL) {
6228 return ERROR_NT(NT_STATUS_NO_MEMORY);
6230 pdata = *ppdata;
6232 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6233 CAN ACCEPT THIS IN UNICODE. JRA. */
6235 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6236 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6237 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6238 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6239 return(-1);
6240 } else {
6241 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6242 return ERROR_DOS(ERRSRV,ERRerror);
6246 /****************************************************************************
6247 Reply to a SMBfindclose (stop trans2 directory search).
6248 ****************************************************************************/
6250 int reply_findclose(connection_struct *conn,
6251 char *inbuf,char *outbuf,int length,int bufsize)
6253 int outsize = 0;
6254 int dptr_num=SVALS(inbuf,smb_vwv0);
6255 START_PROFILE(SMBfindclose);
6257 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6259 dptr_close(&dptr_num);
6261 outsize = set_message(outbuf,0,0,False);
6263 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6265 END_PROFILE(SMBfindclose);
6266 return(outsize);
6269 /****************************************************************************
6270 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6271 ****************************************************************************/
6273 int reply_findnclose(connection_struct *conn,
6274 char *inbuf,char *outbuf,int length,int bufsize)
6276 int outsize = 0;
6277 int dptr_num= -1;
6278 START_PROFILE(SMBfindnclose);
6280 dptr_num = SVAL(inbuf,smb_vwv0);
6282 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6284 /* We never give out valid handles for a
6285 findnotifyfirst - so any dptr_num is ok here.
6286 Just ignore it. */
6288 outsize = set_message(outbuf,0,0,False);
6290 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6292 END_PROFILE(SMBfindnclose);
6293 return(outsize);
6296 int handle_trans2(connection_struct *conn,
6297 struct trans_state *state,
6298 char *inbuf, char *outbuf, int size, int bufsize)
6300 int outsize;
6302 if (Protocol >= PROTOCOL_NT1) {
6303 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6306 /* Now we must call the relevant TRANS2 function */
6307 switch(state->call) {
6308 case TRANSACT2_OPEN:
6310 START_PROFILE(Trans2_open);
6311 outsize = call_trans2open(
6312 conn, inbuf, outbuf, bufsize,
6313 &state->param, state->total_param,
6314 &state->data, state->total_data,
6315 state->max_data_return);
6316 END_PROFILE(Trans2_open);
6317 break;
6320 case TRANSACT2_FINDFIRST:
6322 START_PROFILE(Trans2_findfirst);
6323 outsize = call_trans2findfirst(
6324 conn, inbuf, outbuf, bufsize,
6325 &state->param, state->total_param,
6326 &state->data, state->total_data,
6327 state->max_data_return);
6328 END_PROFILE(Trans2_findfirst);
6329 break;
6332 case TRANSACT2_FINDNEXT:
6334 START_PROFILE(Trans2_findnext);
6335 outsize = call_trans2findnext(
6336 conn, inbuf, outbuf, size, bufsize,
6337 &state->param, state->total_param,
6338 &state->data, state->total_data,
6339 state->max_data_return);
6340 END_PROFILE(Trans2_findnext);
6341 break;
6344 case TRANSACT2_QFSINFO:
6346 START_PROFILE(Trans2_qfsinfo);
6347 outsize = call_trans2qfsinfo(
6348 conn, inbuf, outbuf, size, bufsize,
6349 &state->param, state->total_param,
6350 &state->data, state->total_data,
6351 state->max_data_return);
6352 END_PROFILE(Trans2_qfsinfo);
6353 break;
6356 case TRANSACT2_SETFSINFO:
6358 START_PROFILE(Trans2_setfsinfo);
6359 outsize = call_trans2setfsinfo(
6360 conn, inbuf, outbuf, size, bufsize,
6361 &state->param, state->total_param,
6362 &state->data, state->total_data,
6363 state->max_data_return);
6364 END_PROFILE(Trans2_setfsinfo);
6365 break;
6368 case TRANSACT2_QPATHINFO:
6369 case TRANSACT2_QFILEINFO:
6371 START_PROFILE(Trans2_qpathinfo);
6372 outsize = call_trans2qfilepathinfo(
6373 conn, inbuf, outbuf, size, bufsize, state->call,
6374 &state->param, state->total_param,
6375 &state->data, state->total_data,
6376 state->max_data_return);
6377 END_PROFILE(Trans2_qpathinfo);
6378 break;
6381 case TRANSACT2_SETPATHINFO:
6382 case TRANSACT2_SETFILEINFO:
6384 START_PROFILE(Trans2_setpathinfo);
6385 outsize = call_trans2setfilepathinfo(
6386 conn, inbuf, outbuf, size, bufsize, state->call,
6387 &state->param, state->total_param,
6388 &state->data, state->total_data,
6389 state->max_data_return);
6390 END_PROFILE(Trans2_setpathinfo);
6391 break;
6394 case TRANSACT2_FINDNOTIFYFIRST:
6396 START_PROFILE(Trans2_findnotifyfirst);
6397 outsize = call_trans2findnotifyfirst(
6398 conn, inbuf, outbuf, size, bufsize,
6399 &state->param, state->total_param,
6400 &state->data, state->total_data,
6401 state->max_data_return);
6402 END_PROFILE(Trans2_findnotifyfirst);
6403 break;
6406 case TRANSACT2_FINDNOTIFYNEXT:
6408 START_PROFILE(Trans2_findnotifynext);
6409 outsize = call_trans2findnotifynext(
6410 conn, inbuf, outbuf, size, bufsize,
6411 &state->param, state->total_param,
6412 &state->data, state->total_data,
6413 state->max_data_return);
6414 END_PROFILE(Trans2_findnotifynext);
6415 break;
6418 case TRANSACT2_MKDIR:
6420 START_PROFILE(Trans2_mkdir);
6421 outsize = call_trans2mkdir(
6422 conn, inbuf, outbuf, size, bufsize,
6423 &state->param, state->total_param,
6424 &state->data, state->total_data,
6425 state->max_data_return);
6426 END_PROFILE(Trans2_mkdir);
6427 break;
6430 case TRANSACT2_GET_DFS_REFERRAL:
6432 START_PROFILE(Trans2_get_dfs_referral);
6433 outsize = call_trans2getdfsreferral(
6434 conn, inbuf, outbuf, size, bufsize,
6435 &state->param, state->total_param,
6436 &state->data, state->total_data,
6437 state->max_data_return);
6438 END_PROFILE(Trans2_get_dfs_referral);
6439 break;
6442 case TRANSACT2_IOCTL:
6444 START_PROFILE(Trans2_ioctl);
6445 outsize = call_trans2ioctl(
6446 conn, inbuf, outbuf, size, bufsize,
6447 &state->param, state->total_param,
6448 &state->data, state->total_data,
6449 state->max_data_return);
6450 END_PROFILE(Trans2_ioctl);
6451 break;
6454 default:
6455 /* Error in request */
6456 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6457 outsize = ERROR_DOS(ERRSRV,ERRerror);
6460 return outsize;
6463 /****************************************************************************
6464 Reply to a SMBtrans2.
6465 ****************************************************************************/
6467 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6468 int size, int bufsize)
6470 int outsize = 0;
6471 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6472 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6473 unsigned int psoff = SVAL(inbuf, smb_psoff);
6474 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6475 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6476 struct trans_state *state;
6477 NTSTATUS result;
6479 START_PROFILE(SMBtrans2);
6481 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6482 if (!NT_STATUS_IS_OK(result)) {
6483 DEBUG(2, ("Got invalid trans2 request: %s\n",
6484 nt_errstr(result)));
6485 END_PROFILE(SMBtrans2);
6486 return ERROR_NT(result);
6489 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6490 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6491 END_PROFILE(SMBtrans2);
6492 return ERROR_DOS(ERRSRV,ERRaccess);
6495 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6496 DEBUG(0, ("talloc failed\n"));
6497 END_PROFILE(SMBtrans2);
6498 return ERROR_NT(NT_STATUS_NO_MEMORY);
6501 state->cmd = SMBtrans2;
6503 state->mid = SVAL(inbuf, smb_mid);
6504 state->vuid = SVAL(inbuf, smb_uid);
6505 state->setup_count = SVAL(inbuf, smb_suwcnt);
6506 state->setup = NULL;
6507 state->total_param = SVAL(inbuf, smb_tpscnt);
6508 state->param = NULL;
6509 state->total_data = SVAL(inbuf, smb_tdscnt);
6510 state->data = NULL;
6511 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6512 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6513 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6514 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6515 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6517 state->call = tran_call;
6519 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6520 is so as a sanity check */
6521 if (state->setup_count != 1) {
6523 * Need to have rc=0 for ioctl to get job id for OS/2.
6524 * Network printing will fail if function is not successful.
6525 * Similar function in reply.c will be used if protocol
6526 * is LANMAN1.0 instead of LM1.2X002.
6527 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6528 * outbuf doesn't have to be set(only job id is used).
6530 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6531 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6532 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6533 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6534 } else {
6535 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6536 DEBUG(2,("Transaction is %d\n",tran_call));
6537 TALLOC_FREE(state);
6538 END_PROFILE(SMBtrans2);
6539 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6543 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6544 goto bad_param;
6546 if (state->total_data) {
6547 /* Can't use talloc here, the core routines do realloc on the
6548 * params and data. */
6549 state->data = (char *)SMB_MALLOC(state->total_data);
6550 if (state->data == NULL) {
6551 DEBUG(0,("reply_trans2: data malloc fail for %u "
6552 "bytes !\n", (unsigned int)state->total_data));
6553 TALLOC_FREE(state);
6554 END_PROFILE(SMBtrans2);
6555 return(ERROR_DOS(ERRDOS,ERRnomem));
6557 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6558 goto bad_param;
6559 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6560 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6561 goto bad_param;
6563 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6566 if (state->total_param) {
6567 /* Can't use talloc here, the core routines do realloc on the
6568 * params and data. */
6569 state->param = (char *)SMB_MALLOC(state->total_param);
6570 if (state->param == NULL) {
6571 DEBUG(0,("reply_trans: param malloc fail for %u "
6572 "bytes !\n", (unsigned int)state->total_param));
6573 SAFE_FREE(state->data);
6574 TALLOC_FREE(state);
6575 END_PROFILE(SMBtrans2);
6576 return(ERROR_DOS(ERRDOS,ERRnomem));
6578 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6579 goto bad_param;
6580 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6581 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6582 goto bad_param;
6584 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6587 state->received_data = dscnt;
6588 state->received_param = pscnt;
6590 if ((state->received_param == state->total_param) &&
6591 (state->received_data == state->total_data)) {
6593 outsize = handle_trans2(conn, state, inbuf, outbuf,
6594 size, bufsize);
6595 SAFE_FREE(state->data);
6596 SAFE_FREE(state->param);
6597 TALLOC_FREE(state);
6598 END_PROFILE(SMBtrans2);
6599 return outsize;
6602 DLIST_ADD(conn->pending_trans, state);
6604 /* We need to send an interim response then receive the rest
6605 of the parameter/data bytes */
6606 outsize = set_message(outbuf,0,0,False);
6607 show_msg(outbuf);
6608 END_PROFILE(SMBtrans2);
6609 return outsize;
6611 bad_param:
6613 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6614 SAFE_FREE(state->data);
6615 SAFE_FREE(state->param);
6616 TALLOC_FREE(state);
6617 END_PROFILE(SMBtrans2);
6618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6622 /****************************************************************************
6623 Reply to a SMBtranss2
6624 ****************************************************************************/
6626 int reply_transs2(connection_struct *conn,
6627 char *inbuf,char *outbuf,int size,int bufsize)
6629 int outsize = 0;
6630 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6631 struct trans_state *state;
6633 START_PROFILE(SMBtranss2);
6635 show_msg(inbuf);
6637 for (state = conn->pending_trans; state != NULL;
6638 state = state->next) {
6639 if (state->mid == SVAL(inbuf,smb_mid)) {
6640 break;
6644 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6645 END_PROFILE(SMBtranss2);
6646 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6649 /* Revise state->total_param and state->total_data in case they have
6650 changed downwards */
6652 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6653 state->total_param = SVAL(inbuf, smb_tpscnt);
6654 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6655 state->total_data = SVAL(inbuf, smb_tdscnt);
6657 pcnt = SVAL(inbuf, smb_spscnt);
6658 poff = SVAL(inbuf, smb_spsoff);
6659 pdisp = SVAL(inbuf, smb_spsdisp);
6661 dcnt = SVAL(inbuf, smb_sdscnt);
6662 doff = SVAL(inbuf, smb_sdsoff);
6663 ddisp = SVAL(inbuf, smb_sdsdisp);
6665 state->received_param += pcnt;
6666 state->received_data += dcnt;
6668 if ((state->received_data > state->total_data) ||
6669 (state->received_param > state->total_param))
6670 goto bad_param;
6672 if (pcnt) {
6673 if (pdisp+pcnt > state->total_param)
6674 goto bad_param;
6675 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6676 goto bad_param;
6677 if (pdisp > state->total_param)
6678 goto bad_param;
6679 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6680 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6681 goto bad_param;
6682 if (state->param + pdisp < state->param)
6683 goto bad_param;
6685 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6686 pcnt);
6689 if (dcnt) {
6690 if (ddisp+dcnt > state->total_data)
6691 goto bad_param;
6692 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6693 goto bad_param;
6694 if (ddisp > state->total_data)
6695 goto bad_param;
6696 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6697 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6698 goto bad_param;
6699 if (state->data + ddisp < state->data)
6700 goto bad_param;
6702 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6703 dcnt);
6706 if ((state->received_param < state->total_param) ||
6707 (state->received_data < state->total_data)) {
6708 END_PROFILE(SMBtranss2);
6709 return -1;
6712 /* construct_reply_common has done us the favor to pre-fill the
6713 * command field with SMBtranss2 which is wrong :-)
6715 SCVAL(outbuf,smb_com,SMBtrans2);
6717 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6719 DLIST_REMOVE(conn->pending_trans, state);
6720 SAFE_FREE(state->data);
6721 SAFE_FREE(state->param);
6722 TALLOC_FREE(state);
6724 if (outsize == 0) {
6725 END_PROFILE(SMBtranss2);
6726 return(ERROR_DOS(ERRSRV,ERRnosupport));
6729 END_PROFILE(SMBtranss2);
6730 return(outsize);
6732 bad_param:
6734 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6735 DLIST_REMOVE(conn->pending_trans, state);
6736 SAFE_FREE(state->data);
6737 SAFE_FREE(state->param);
6738 TALLOC_FREE(state);
6739 END_PROFILE(SMBtranss2);
6740 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);