Fix bug #5937 - filenames with "*" char hide other files
[Samba.git] / source / smbd / trans2.c
blob904a84bef6d5748efd7087e41b5ae4203bcfb4ee
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "includes.h"
29 extern int max_send;
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
62 return val;
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
67 account sparse files.
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 SMB_BIG_UINT ret;
74 if(S_ISDIR(sbuf->st_mode)) {
75 return 0;
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 #else
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 #endif
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
97 NULL
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
106 int i;
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 return True;
112 return False;
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
124 char *val = NULL;
125 ssize_t sizeret;
127 again:
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
130 if (!val) {
131 return False;
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 } else {
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
141 attr_size = 65536;
142 goto again;
145 if (sizeret == -1) {
146 return False;
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, val, sizeret);
152 pea->flags = 0;
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
155 } else {
156 pea->name = ea_name;
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
160 return True;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
172 char *ea_namelist;
173 char *p;
174 ssize_t sizeret;
175 int i;
176 struct ea_list *ea_list_head = NULL;
178 *pea_total_len = 0;
180 if (!lp_ea_support(SNUM(conn))) {
181 return NULL;
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
187 if (!ea_namelist) {
188 return NULL;
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 } else {
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
199 } else {
200 break;
204 if (sizeret == -1)
205 return NULL;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 if (sizeret) {
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 continue;
216 listp = TALLOC_P(mem_ctx, struct ea_list);
217 if (!listp)
218 return NULL;
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
221 return NULL;
225 fstring dos_ea_name;
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
236 *pea_total_len += 4;
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
241 return ea_list_head;
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 that was filled.
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
253 char *p = pdata;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
258 SIVAL(pdata,4,0);
259 return 4;
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 size_t dos_namelen;
264 fstring dos_ea_name;
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
268 break;
270 if (ea_list->ea.value.length > 65535) {
271 break;
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274 break;
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
300 return 0;
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
305 return total_ea_len;
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 size_t total_ea_len;
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
323 break;
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
340 int ret;
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 } else {
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 #ifdef ENOATTR
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
370 unix_ea_name));
371 ret = 0;
373 #endif
374 } else {
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 } else {
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (ret == -1) {
389 #ifdef ENOTSUP
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
393 #endif
394 return map_nt_error_from_unix(errno);
398 return NT_STATUS_OK;
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
407 size_t offset = 0;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
419 break;
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
423 return NULL;
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
426 if (!eal->ea.name) {
427 return NULL;
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
435 return ea_list_head;
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 uint16 val_len;
446 unsigned int namelen;
448 if (!eal) {
449 return NULL;
452 if (data_size < 6) {
453 return NULL;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
461 return NULL;
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
466 return NULL;
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
469 if (!eal->ea.name) {
470 return NULL;
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
475 return NULL;
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
485 if (pbytes_used) {
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
492 return eal;
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
502 size_t offset = 0;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
508 if (!eal) {
509 return NULL;
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
516 return ea_list_head;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
525 fstring dos_ea_name;
526 struct ea_list *listp;
527 size_t ret = 0;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
534 if (ret) {
535 ret += 4;
538 return ret;
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
554 break;
558 if (flistp) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
562 } else {
563 /* Null entry. */
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
570 return name_list;
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(char *outbuf,
581 int bufsize,
582 const char *params,
583 int paramsize,
584 const char *pdata,
585 int datasize,
586 int max_data_bytes)
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
596 int useable_space;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
610 for OS/2. */
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
622 show_msg(outbuf);
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
625 return 0;
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
685 else
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
693 } else {
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
717 show_msg(outbuf);
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
727 /* Sanity check */
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
731 return -1;
735 return 0;
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
748 int deny_mode;
749 int32 open_attr;
750 BOOL oplock_request;
751 #if 0
752 BOOL return_additional_info;
753 int16 open_sattr;
754 time_t open_time;
755 #endif
756 int open_ofun;
757 uint32 open_size;
758 char *pname;
759 pstring fname;
760 SMB_OFF_T size=0;
761 int fattr=0,mtime=0;
762 SMB_INO_T inode = 0;
763 SMB_STRUCT_STAT sbuf;
764 int smb_action = 0;
765 files_struct *fsp;
766 struct ea_list *ea_list = NULL;
767 uint16 flags = 0;
768 NTSTATUS status;
769 uint32 access_mask;
770 uint32 share_mode;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
790 #if 0
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
794 #endif
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
797 pname = &params[28];
799 if (IS_IPC(conn)) {
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
829 &access_mask,
830 &share_mode,
831 &create_disposition,
832 &create_options)) {
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
853 total_data - 4);
854 if (!ea_list) {
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
862 access_mask,
863 share_mode,
864 create_disposition,
865 create_options,
866 open_attr,
867 oplock_request,
868 &smb_action, &fsp);
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
873 return -1;
875 return ERROR_OPEN(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
881 inode = sbuf.st_ino;
882 if (fattr & aDIR) {
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
906 } else {
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
924 params = *pparams;
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
945 if (flags & 8) {
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
948 } else {
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
955 return -1;
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
968 return False;
969 if (dptr_has_wild(conn->dirptr)) {
970 return False;
972 if (conn->case_sensitive)
973 return strcmp(str,mask)==0;
974 else
975 return StrCaseCmp(str,mask) == 0;
978 /****************************************************************************
979 Return the filetype for UNIX extensions.
980 ****************************************************************************/
982 static uint32 unix_filetype(mode_t mode)
984 if(S_ISREG(mode))
985 return UNIX_TYPE_FILE;
986 else if(S_ISDIR(mode))
987 return UNIX_TYPE_DIR;
988 #ifdef S_ISLNK
989 else if(S_ISLNK(mode))
990 return UNIX_TYPE_SYMLINK;
991 #endif
992 #ifdef S_ISCHR
993 else if(S_ISCHR(mode))
994 return UNIX_TYPE_CHARDEV;
995 #endif
996 #ifdef S_ISBLK
997 else if(S_ISBLK(mode))
998 return UNIX_TYPE_BLKDEV;
999 #endif
1000 #ifdef S_ISFIFO
1001 else if(S_ISFIFO(mode))
1002 return UNIX_TYPE_FIFO;
1003 #endif
1004 #ifdef S_ISSOCK
1005 else if(S_ISSOCK(mode))
1006 return UNIX_TYPE_SOCKET;
1007 #endif
1009 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1010 return UNIX_TYPE_UNKNOWN;
1013 /****************************************************************************
1014 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1015 ****************************************************************************/
1017 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1019 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1020 SMB_STRUCT_STAT *psbuf,
1021 uint32 perms,
1022 enum perm_type ptype,
1023 mode_t *ret_perms)
1025 mode_t ret = 0;
1027 if (perms == SMB_MODE_NO_CHANGE) {
1028 if (!VALID_STAT(*psbuf)) {
1029 return NT_STATUS_INVALID_PARAMETER;
1030 } else {
1031 *ret_perms = psbuf->st_mode;
1032 return NT_STATUS_OK;
1036 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1037 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1038 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1039 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1040 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1041 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1042 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1043 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1044 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1045 #ifdef S_ISVTX
1046 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1047 #endif
1048 #ifdef S_ISGID
1049 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1050 #endif
1051 #ifdef S_ISUID
1052 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1053 #endif
1055 switch (ptype) {
1056 case PERM_NEW_FILE:
1057 /* Apply mode mask */
1058 ret &= lp_create_mask(SNUM(conn));
1059 /* Add in force bits */
1060 ret |= lp_force_create_mode(SNUM(conn));
1061 break;
1062 case PERM_NEW_DIR:
1063 ret &= lp_dir_mask(SNUM(conn));
1064 /* Add in force bits */
1065 ret |= lp_force_dir_mode(SNUM(conn));
1066 break;
1067 case PERM_EXISTING_FILE:
1068 /* Apply mode mask */
1069 ret &= lp_security_mask(SNUM(conn));
1070 /* Add in force bits */
1071 ret |= lp_force_security_mode(SNUM(conn));
1072 break;
1073 case PERM_EXISTING_DIR:
1074 /* Apply mode mask */
1075 ret &= lp_dir_security_mask(SNUM(conn));
1076 /* Add in force bits */
1077 ret |= lp_force_dir_security_mode(SNUM(conn));
1078 break;
1081 *ret_perms = ret;
1082 return NT_STATUS_OK;
1085 /****************************************************************************
1086 Get a level dependent lanman2 dir entry.
1087 ****************************************************************************/
1089 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1090 void *inbuf, char *outbuf,
1091 char *path_mask,uint32 dirtype,int info_level,
1092 int requires_resume_key,
1093 BOOL dont_descend,char **ppdata,
1094 char *base_data, char *end_data, int space_remaining,
1095 BOOL *out_of_space, BOOL *got_exact_match,
1096 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1098 const char *dname;
1099 BOOL found = False;
1100 SMB_STRUCT_STAT sbuf;
1101 pstring mask;
1102 pstring pathreal;
1103 pstring fname;
1104 char *p, *q, *pdata = *ppdata;
1105 uint32 reskey=0;
1106 long prev_dirpos=0;
1107 uint32 mode=0;
1108 SMB_OFF_T file_size = 0;
1109 SMB_BIG_UINT allocation_size = 0;
1110 uint32 len;
1111 struct timespec mdate_ts, adate_ts, create_date_ts;
1112 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1113 char *nameptr;
1114 char *last_entry_ptr;
1115 BOOL was_8_3;
1116 uint32 nt_extmode; /* Used for NT connections instead of mode */
1117 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1118 BOOL check_mangled_names = lp_manglednames(conn->params);
1120 *fname = 0;
1121 *out_of_space = False;
1122 *got_exact_match = False;
1124 ZERO_STRUCT(mdate_ts);
1125 ZERO_STRUCT(adate_ts);
1126 ZERO_STRUCT(create_date_ts);
1128 if (!conn->dirptr)
1129 return(False);
1131 p = strrchr_m(path_mask,'/');
1132 if(p != NULL) {
1133 if(p[1] == '\0')
1134 pstrcpy(mask,"*.*");
1135 else
1136 pstrcpy(mask, p+1);
1137 } else
1138 pstrcpy(mask, path_mask);
1141 while (!found) {
1142 BOOL got_match;
1143 BOOL ms_dfs_link = False;
1145 /* Needed if we run out of space */
1146 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1147 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1150 * Due to bugs in NT client redirectors we are not using
1151 * resume keys any more - set them to zero.
1152 * Check out the related comments in findfirst/findnext.
1153 * JRA.
1156 reskey = 0;
1158 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1159 (long)conn->dirptr,curr_dirpos));
1161 if (!dname)
1162 return(False);
1164 pstrcpy(fname,dname);
1166 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1167 got_match = mask_match(fname, mask, conn->case_sensitive);
1169 if(!got_match && check_mangled_names &&
1170 !mangle_is_8_3(fname, False, conn->params)) {
1173 * It turns out that NT matches wildcards against
1174 * both long *and* short names. This may explain some
1175 * of the wildcard wierdness from old DOS clients
1176 * that some people have been seeing.... JRA.
1179 pstring newname;
1180 pstrcpy( newname, fname);
1181 mangle_map( newname, True, False, conn->params);
1182 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1183 got_match = mask_match(newname, mask, conn->case_sensitive);
1186 if(got_match) {
1187 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1188 if (dont_descend && !isdots)
1189 continue;
1191 pstrcpy(pathreal,conn->dirpath);
1192 if(needslash)
1193 pstrcat(pathreal,"/");
1194 pstrcat(pathreal,dname);
1196 if (INFO_LEVEL_IS_UNIX(info_level)) {
1197 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1198 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1199 pathreal,strerror(errno)));
1200 continue;
1202 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1203 pstring link_target;
1205 /* Needed to show the msdfs symlinks as
1206 * directories */
1208 if(lp_host_msdfs() &&
1209 lp_msdfs_root(SNUM(conn)) &&
1210 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1211 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1212 "as a directory\n",
1213 pathreal));
1214 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1216 } else {
1218 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1219 pathreal,strerror(errno)));
1220 continue;
1224 if (ms_dfs_link) {
1225 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1226 } else {
1227 mode = dos_mode(conn,pathreal,&sbuf);
1230 if (!dir_check_ftype(conn,mode,dirtype)) {
1231 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1232 continue;
1235 if (!(mode & aDIR))
1236 file_size = get_file_size(sbuf);
1237 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1239 mdate_ts = get_mtimespec(&sbuf);
1240 adate_ts = get_atimespec(&sbuf);
1241 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1243 if (lp_dos_filetime_resolution(SNUM(conn))) {
1244 dos_filetime_timespec(&create_date_ts);
1245 dos_filetime_timespec(&mdate_ts);
1246 dos_filetime_timespec(&adate_ts);
1249 create_date = convert_timespec_to_time_t(create_date_ts);
1250 mdate = convert_timespec_to_time_t(mdate_ts);
1251 adate = convert_timespec_to_time_t(adate_ts);
1253 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1255 found = True;
1257 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1261 mangle_map(fname,False,True,conn->params);
1263 p = pdata;
1264 last_entry_ptr = p;
1266 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1268 switch (info_level) {
1269 case SMB_FIND_INFO_STANDARD:
1270 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1271 if(requires_resume_key) {
1272 SIVAL(p,0,reskey);
1273 p += 4;
1275 srv_put_dos_date2(p,0,create_date);
1276 srv_put_dos_date2(p,4,adate);
1277 srv_put_dos_date2(p,8,mdate);
1278 SIVAL(p,12,(uint32)file_size);
1279 SIVAL(p,16,(uint32)allocation_size);
1280 SSVAL(p,20,mode);
1281 p += 23;
1282 nameptr = p;
1283 p += align_string(outbuf, p, 0);
1284 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE);
1285 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1286 if (len > 2) {
1287 SCVAL(nameptr, -1, len - 2);
1288 } else {
1289 SCVAL(nameptr, -1, 0);
1291 } else {
1292 if (len > 1) {
1293 SCVAL(nameptr, -1, len - 1);
1294 } else {
1295 SCVAL(nameptr, -1, 0);
1298 p += len;
1299 break;
1301 case SMB_FIND_EA_SIZE:
1302 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1303 if(requires_resume_key) {
1304 SIVAL(p,0,reskey);
1305 p += 4;
1307 srv_put_dos_date2(p,0,create_date);
1308 srv_put_dos_date2(p,4,adate);
1309 srv_put_dos_date2(p,8,mdate);
1310 SIVAL(p,12,(uint32)file_size);
1311 SIVAL(p,16,(uint32)allocation_size);
1312 SSVAL(p,20,mode);
1314 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1315 SIVAL(p,22,ea_size); /* Extended attributes */
1317 p += 27;
1318 nameptr = p - 1;
1319 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE | STR_NOALIGN);
1320 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1321 if (len > 2) {
1322 len -= 2;
1323 } else {
1324 len = 0;
1326 } else {
1327 if (len > 1) {
1328 len -= 1;
1329 } else {
1330 len = 0;
1333 SCVAL(nameptr,0,len);
1334 p += len;
1335 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1336 break;
1338 case SMB_FIND_EA_LIST:
1340 struct ea_list *file_list = NULL;
1341 size_t ea_len = 0;
1343 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1344 if (!name_list) {
1345 return False;
1347 if(requires_resume_key) {
1348 SIVAL(p,0,reskey);
1349 p += 4;
1351 srv_put_dos_date2(p,0,create_date);
1352 srv_put_dos_date2(p,4,adate);
1353 srv_put_dos_date2(p,8,mdate);
1354 SIVAL(p,12,(uint32)file_size);
1355 SIVAL(p,16,(uint32)allocation_size);
1356 SSVAL(p,20,mode);
1357 p += 22; /* p now points to the EA area. */
1359 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1360 name_list = ea_list_union(name_list, file_list, &ea_len);
1362 /* We need to determine if this entry will fit in the space available. */
1363 /* Max string size is 255 bytes. */
1364 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1365 /* Move the dirptr back to prev_dirpos */
1366 dptr_SeekDir(conn->dirptr, prev_dirpos);
1367 *out_of_space = True;
1368 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1369 return False; /* Not finished - just out of space */
1372 /* Push the ea_data followed by the name. */
1373 p += fill_ea_buffer(ea_ctx, p, space_remaining - (p - pdata), conn, name_list);
1374 nameptr = p;
1375 len = srvstr_push(outbuf, p + 1, fname, PTR_DIFF(end_data, p+1), STR_TERMINATE | STR_NOALIGN);
1376 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1377 if (len > 2) {
1378 len -= 2;
1379 } else {
1380 len = 0;
1382 } else {
1383 if (len > 1) {
1384 len -= 1;
1385 } else {
1386 len = 0;
1389 SCVAL(nameptr,0,len);
1390 p += len + 1;
1391 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1392 break;
1395 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1396 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1397 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1398 p += 4;
1399 SIVAL(p,0,reskey); p += 4;
1400 put_long_date_timespec(p,create_date_ts); p += 8;
1401 put_long_date_timespec(p,adate_ts); p += 8;
1402 put_long_date_timespec(p,mdate_ts); p += 8;
1403 put_long_date_timespec(p,mdate_ts); p += 8;
1404 SOFF_T(p,0,file_size); p += 8;
1405 SOFF_T(p,0,allocation_size); p += 8;
1406 SIVAL(p,0,nt_extmode); p += 4;
1407 q = p; p += 4; /* q is placeholder for name length. */
1409 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1410 SIVAL(p,0,ea_size); /* Extended attributes */
1411 p += 4;
1413 /* Clear the short name buffer. This is
1414 * IMPORTANT as not doing so will trigger
1415 * a Win2k client bug. JRA.
1417 if (!was_8_3 && check_mangled_names) {
1418 pstring mangled_name;
1419 pstrcpy(mangled_name, fname);
1420 mangle_map(mangled_name,True,True,
1421 conn->params);
1422 mangled_name[12] = 0;
1423 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1424 if (len < 24) {
1425 memset(p + 2 + len,'\0',24 - len);
1427 SSVAL(p, 0, len);
1428 } else {
1429 memset(p,'\0',26);
1431 p += 2 + 24;
1432 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1433 SIVAL(q,0,len);
1434 p += len;
1435 SIVAL(p,0,0); /* Ensure any padding is null. */
1436 len = PTR_DIFF(p, pdata);
1437 len = (len + 3) & ~3;
1438 SIVAL(pdata,0,len);
1439 p = pdata + len;
1440 break;
1442 case SMB_FIND_FILE_DIRECTORY_INFO:
1443 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1444 p += 4;
1445 SIVAL(p,0,reskey); p += 4;
1446 put_long_date_timespec(p,create_date_ts); p += 8;
1447 put_long_date_timespec(p,adate_ts); p += 8;
1448 put_long_date_timespec(p,mdate_ts); p += 8;
1449 put_long_date_timespec(p,mdate_ts); p += 8;
1450 SOFF_T(p,0,file_size); p += 8;
1451 SOFF_T(p,0,allocation_size); p += 8;
1452 SIVAL(p,0,nt_extmode); p += 4;
1453 len = srvstr_push(outbuf, p + 4, fname, PTR_DIFF(end_data, p+4), STR_TERMINATE_ASCII);
1454 SIVAL(p,0,len);
1455 p += 4 + len;
1456 SIVAL(p,0,0); /* Ensure any padding is null. */
1457 len = PTR_DIFF(p, pdata);
1458 len = (len + 3) & ~3;
1459 SIVAL(pdata,0,len);
1460 p = pdata + len;
1461 break;
1463 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1464 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1465 p += 4;
1466 SIVAL(p,0,reskey); p += 4;
1467 put_long_date_timespec(p,create_date_ts); p += 8;
1468 put_long_date_timespec(p,adate_ts); p += 8;
1469 put_long_date_timespec(p,mdate_ts); p += 8;
1470 put_long_date_timespec(p,mdate_ts); p += 8;
1471 SOFF_T(p,0,file_size); p += 8;
1472 SOFF_T(p,0,allocation_size); p += 8;
1473 SIVAL(p,0,nt_extmode); p += 4;
1474 q = p; p += 4; /* q is placeholder for name length. */
1476 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1477 SIVAL(p,0,ea_size); /* Extended attributes */
1478 p +=4;
1480 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1481 SIVAL(q, 0, len);
1482 p += len;
1484 SIVAL(p,0,0); /* Ensure any padding is null. */
1485 len = PTR_DIFF(p, pdata);
1486 len = (len + 3) & ~3;
1487 SIVAL(pdata,0,len);
1488 p = pdata + len;
1489 break;
1491 case SMB_FIND_FILE_NAMES_INFO:
1492 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1493 p += 4;
1494 SIVAL(p,0,reskey); p += 4;
1495 p += 4;
1496 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1497 acl on a dir (tridge) */
1498 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1499 SIVAL(p, -4, len);
1500 p += len;
1501 SIVAL(p,0,0); /* Ensure any padding is null. */
1502 len = PTR_DIFF(p, pdata);
1503 len = (len + 3) & ~3;
1504 SIVAL(pdata,0,len);
1505 p = pdata + len;
1506 break;
1508 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1510 p += 4;
1511 SIVAL(p,0,reskey); p += 4;
1512 put_long_date_timespec(p,create_date_ts); p += 8;
1513 put_long_date_timespec(p,adate_ts); p += 8;
1514 put_long_date_timespec(p,mdate_ts); p += 8;
1515 put_long_date_timespec(p,mdate_ts); p += 8;
1516 SOFF_T(p,0,file_size); p += 8;
1517 SOFF_T(p,0,allocation_size); p += 8;
1518 SIVAL(p,0,nt_extmode); p += 4;
1519 q = p; p += 4; /* q is placeholder for name length. */
1521 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1522 SIVAL(p,0,ea_size); /* Extended attributes */
1523 p +=4;
1525 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1526 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1527 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1528 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1529 SIVAL(q, 0, len);
1530 p += len;
1531 SIVAL(p,0,0); /* Ensure any padding is null. */
1532 len = PTR_DIFF(p, pdata);
1533 len = (len + 3) & ~3;
1534 SIVAL(pdata,0,len);
1535 p = pdata + len;
1536 break;
1538 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1540 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1541 p += 4;
1542 SIVAL(p,0,reskey); p += 4;
1543 put_long_date_timespec(p,create_date_ts); p += 8;
1544 put_long_date_timespec(p,adate_ts); p += 8;
1545 put_long_date_timespec(p,mdate_ts); p += 8;
1546 put_long_date_timespec(p,mdate_ts); p += 8;
1547 SOFF_T(p,0,file_size); p += 8;
1548 SOFF_T(p,0,allocation_size); p += 8;
1549 SIVAL(p,0,nt_extmode); p += 4;
1550 q = p; p += 4; /* q is placeholder for name length */
1552 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1553 SIVAL(p,0,ea_size); /* Extended attributes */
1554 p +=4;
1556 /* Clear the short name buffer. This is
1557 * IMPORTANT as not doing so will trigger
1558 * a Win2k client bug. JRA.
1560 if (!was_8_3 && check_mangled_names) {
1561 pstring mangled_name;
1562 pstrcpy(mangled_name, fname);
1563 mangle_map(mangled_name,True,True,
1564 conn->params);
1565 mangled_name[12] = 0;
1566 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1567 SSVAL(p, 0, len);
1568 if (len < 24) {
1569 memset(p + 2 + len,'\0',24 - len);
1571 SSVAL(p, 0, len);
1572 } else {
1573 memset(p,'\0',26);
1575 p += 26;
1576 SSVAL(p,0,0); p += 2; /* Reserved ? */
1577 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1578 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1579 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1580 SIVAL(q,0,len);
1581 p += len;
1582 SIVAL(p,0,0); /* Ensure any padding is null. */
1583 len = PTR_DIFF(p, pdata);
1584 len = (len + 3) & ~3;
1585 SIVAL(pdata,0,len);
1586 p = pdata + len;
1587 break;
1589 /* CIFS UNIX Extension. */
1591 case SMB_FIND_FILE_UNIX:
1592 case SMB_FIND_FILE_UNIX_INFO2:
1593 p+= 4;
1594 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1596 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1598 if (info_level == SMB_FIND_FILE_UNIX) {
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1600 p = store_file_unix_basic(conn, p,
1601 NULL, &sbuf);
1602 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE);
1603 } else {
1604 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1605 p = store_file_unix_basic_info2(conn, p,
1606 NULL, &sbuf);
1607 nameptr = p;
1608 p += 4;
1609 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), 0);
1610 SIVAL(nameptr, 0, len);
1613 p += len;
1614 SIVAL(p,0,0); /* Ensure any padding is null. */
1616 len = PTR_DIFF(p, pdata);
1617 len = (len + 3) & ~3;
1618 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1619 p = pdata + len;
1620 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1622 break;
1624 default:
1625 return(False);
1629 if (PTR_DIFF(p,pdata) > space_remaining) {
1630 /* Move the dirptr back to prev_dirpos */
1631 dptr_SeekDir(conn->dirptr, prev_dirpos);
1632 *out_of_space = True;
1633 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1634 return False; /* Not finished - just out of space */
1637 /* Setup the last entry pointer, as an offset from base_data */
1638 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1639 /* Advance the data pointer to the next slot */
1640 *ppdata = p;
1642 return(found);
1645 /****************************************************************************
1646 Reply to a TRANS2_FINDFIRST.
1647 ****************************************************************************/
1649 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1650 char **pparams, int total_params, char **ppdata, int total_data,
1651 unsigned int max_data_bytes)
1653 /* We must be careful here that we don't return more than the
1654 allowed number of data bytes. If this means returning fewer than
1655 maxentries then so be it. We assume that the redirector has
1656 enough room for the fixed number of parameter bytes it has
1657 requested. */
1658 char *params = *pparams;
1659 char *pdata = *ppdata;
1660 char *data_end;
1661 uint32 dirtype;
1662 int maxentries;
1663 uint16 findfirst_flags;
1664 BOOL close_after_first;
1665 BOOL close_if_end;
1666 BOOL requires_resume_key;
1667 int info_level;
1668 pstring directory;
1669 pstring mask;
1670 char *p;
1671 int last_entry_off=0;
1672 int dptr_num = -1;
1673 int numentries = 0;
1674 int i;
1675 BOOL finished = False;
1676 BOOL dont_descend = False;
1677 BOOL out_of_space = False;
1678 int space_remaining;
1679 BOOL mask_contains_wcard = False;
1680 SMB_STRUCT_STAT sbuf;
1681 TALLOC_CTX *ea_ctx = NULL;
1682 struct ea_list *ea_list = NULL;
1683 NTSTATUS ntstatus = NT_STATUS_OK;
1685 if (total_params < 13) {
1686 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1689 dirtype = SVAL(params,0);
1690 maxentries = SVAL(params,2);
1691 findfirst_flags = SVAL(params,4);
1692 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1693 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1694 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1695 info_level = SVAL(params,6);
1697 *directory = *mask = 0;
1699 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1700 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1701 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1702 info_level, max_data_bytes));
1704 if (!maxentries) {
1705 /* W2K3 seems to treat zero as 1. */
1706 maxentries = 1;
1709 switch (info_level) {
1710 case SMB_FIND_INFO_STANDARD:
1711 case SMB_FIND_EA_SIZE:
1712 case SMB_FIND_EA_LIST:
1713 case SMB_FIND_FILE_DIRECTORY_INFO:
1714 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1715 case SMB_FIND_FILE_NAMES_INFO:
1716 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1717 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1718 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1719 break;
1720 case SMB_FIND_FILE_UNIX:
1721 case SMB_FIND_FILE_UNIX_INFO2:
1722 if (!lp_unix_extensions()) {
1723 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1725 break;
1726 default:
1727 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1730 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1731 if (!NT_STATUS_IS_OK(ntstatus)) {
1732 return ERROR_NT(ntstatus);
1735 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1736 if (!NT_STATUS_IS_OK(ntstatus)) {
1737 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1738 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1740 return ERROR_NT(ntstatus);
1743 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1744 if (!NT_STATUS_IS_OK(ntstatus)) {
1745 return ERROR_NT(ntstatus);
1747 ntstatus = check_name(conn, directory);
1748 if (!NT_STATUS_IS_OK(ntstatus)) {
1749 return ERROR_NT(ntstatus);
1752 p = strrchr_m(directory,'/');
1753 if(p == NULL) {
1754 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1755 if((directory[0] == '.') && (directory[1] == '\0')) {
1756 pstrcpy(mask,"*");
1757 mask_contains_wcard = True;
1758 } else {
1759 pstrcpy(mask,directory);
1761 pstrcpy(directory,"./");
1762 } else {
1763 pstrcpy(mask,p+1);
1764 *p = 0;
1767 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1769 if (info_level == SMB_FIND_EA_LIST) {
1770 uint32 ea_size;
1772 if (total_data < 4) {
1773 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1776 ea_size = IVAL(pdata,0);
1777 if (ea_size != total_data) {
1778 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1779 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1783 if (!lp_ea_support(SNUM(conn))) {
1784 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1787 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1788 return ERROR_NT(NT_STATUS_NO_MEMORY);
1791 /* Pull out the list of names. */
1792 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1793 if (!ea_list) {
1794 talloc_destroy(ea_ctx);
1795 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1799 *ppdata = (char *)SMB_REALLOC(
1800 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1801 if(*ppdata == NULL ) {
1802 talloc_destroy(ea_ctx);
1803 return ERROR_NT(NT_STATUS_NO_MEMORY);
1805 pdata = *ppdata;
1806 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1808 /* Realloc the params space */
1809 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1810 if (*pparams == NULL) {
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_NO_MEMORY);
1814 params = *pparams;
1816 /* Save the wildcard match and attribs we are using on this directory -
1817 needed as lanman2 assumes these are being saved between calls */
1819 ntstatus = dptr_create(conn,
1820 directory,
1821 False,
1822 True,
1823 SVAL(inbuf,smb_pid),
1824 mask,
1825 mask_contains_wcard,
1826 dirtype,
1827 &conn->dirptr);
1829 if (!NT_STATUS_IS_OK(ntstatus)) {
1830 talloc_destroy(ea_ctx);
1831 return ERROR_NT(ntstatus);
1834 dptr_num = dptr_dnum(conn->dirptr);
1835 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1837 /* We don't need to check for VOL here as this is returned by
1838 a different TRANS2 call. */
1840 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1841 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1842 dont_descend = True;
1844 p = pdata;
1845 space_remaining = max_data_bytes;
1846 out_of_space = False;
1848 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1849 BOOL got_exact_match = False;
1851 /* this is a heuristic to avoid seeking the dirptr except when
1852 absolutely necessary. It allows for a filename of about 40 chars */
1853 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1854 out_of_space = True;
1855 finished = False;
1856 } else {
1857 finished = !get_lanman2_dir_entry(conn,
1858 inbuf, outbuf,
1859 mask,dirtype,info_level,
1860 requires_resume_key,dont_descend,
1861 &p,pdata,data_end,space_remaining, &out_of_space, &got_exact_match,
1862 &last_entry_off, ea_list, ea_ctx);
1865 if (finished && out_of_space)
1866 finished = False;
1868 if (!finished && !out_of_space)
1869 numentries++;
1872 * As an optimisation if we know we aren't looking
1873 * for a wildcard name (ie. the name matches the wildcard exactly)
1874 * then we can finish on any (first) match.
1875 * This speeds up large directory searches. JRA.
1878 if(got_exact_match)
1879 finished = True;
1881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1884 talloc_destroy(ea_ctx);
1886 /* Check if we can close the dirptr */
1887 if(close_after_first || (finished && close_if_end)) {
1888 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1889 dptr_close(&dptr_num);
1893 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1894 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1895 * the protocol level is less than NT1. Tested with smbclient. JRA.
1896 * This should fix the OS/2 client bug #2335.
1899 if(numentries == 0) {
1900 dptr_close(&dptr_num);
1901 if (Protocol < PROTOCOL_NT1) {
1902 return ERROR_DOS(ERRDOS,ERRnofiles);
1903 } else {
1904 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1908 /* At this point pdata points to numentries directory entries. */
1910 /* Set up the return parameter block */
1911 SSVAL(params,0,dptr_num);
1912 SSVAL(params,2,numentries);
1913 SSVAL(params,4,finished);
1914 SSVAL(params,6,0); /* Never an EA error */
1915 SSVAL(params,8,last_entry_off);
1917 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1919 if ((! *directory) && dptr_path(dptr_num))
1920 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1922 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1923 smb_fn_name(CVAL(inbuf,smb_com)),
1924 mask, directory, dirtype, numentries ) );
1927 * Force a name mangle here to ensure that the
1928 * mask as an 8.3 name is top of the mangled cache.
1929 * The reasons for this are subtle. Don't remove
1930 * this code unless you know what you are doing
1931 * (see PR#13758). JRA.
1934 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1935 mangle_map(mask, True, True, conn->params);
1937 return(-1);
1940 /****************************************************************************
1941 Reply to a TRANS2_FINDNEXT.
1942 ****************************************************************************/
1944 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1945 char **pparams, int total_params, char **ppdata, int total_data,
1946 unsigned int max_data_bytes)
1948 /* We must be careful here that we don't return more than the
1949 allowed number of data bytes. If this means returning fewer than
1950 maxentries then so be it. We assume that the redirector has
1951 enough room for the fixed number of parameter bytes it has
1952 requested. */
1953 char *params = *pparams;
1954 char *pdata = *ppdata;
1955 char *data_end;
1956 int dptr_num;
1957 int maxentries;
1958 uint16 info_level;
1959 uint32 resume_key;
1960 uint16 findnext_flags;
1961 BOOL close_after_request;
1962 BOOL close_if_end;
1963 BOOL requires_resume_key;
1964 BOOL continue_bit;
1965 BOOL mask_contains_wcard = False;
1966 pstring resume_name;
1967 pstring mask;
1968 pstring directory;
1969 char *p;
1970 uint16 dirtype;
1971 int numentries = 0;
1972 int i, last_entry_off=0;
1973 BOOL finished = False;
1974 BOOL dont_descend = False;
1975 BOOL out_of_space = False;
1976 int space_remaining;
1977 TALLOC_CTX *ea_ctx = NULL;
1978 struct ea_list *ea_list = NULL;
1979 NTSTATUS ntstatus = NT_STATUS_OK;
1981 if (total_params < 13) {
1982 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1985 dptr_num = SVAL(params,0);
1986 maxentries = SVAL(params,2);
1987 info_level = SVAL(params,4);
1988 resume_key = IVAL(params,6);
1989 findnext_flags = SVAL(params,10);
1990 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1991 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1992 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1993 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1995 *mask = *directory = *resume_name = 0;
1997 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1998 if (!NT_STATUS_IS_OK(ntstatus)) {
1999 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2000 complain (it thinks we're asking for the directory above the shared
2001 path or an invalid name). Catch this as the resume name is only compared, never used in
2002 a file access. JRA. */
2003 srvstr_pull(inbuf, resume_name, params+12,
2004 sizeof(resume_name), total_params - 12,
2005 STR_TERMINATE);
2007 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2008 return ERROR_NT(ntstatus);
2012 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2013 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2014 resume_key = %d resume name = %s continue=%d level = %d\n",
2015 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2016 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2018 if (!maxentries) {
2019 /* W2K3 seems to treat zero as 1. */
2020 maxentries = 1;
2023 switch (info_level) {
2024 case SMB_FIND_INFO_STANDARD:
2025 case SMB_FIND_EA_SIZE:
2026 case SMB_FIND_EA_LIST:
2027 case SMB_FIND_FILE_DIRECTORY_INFO:
2028 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2029 case SMB_FIND_FILE_NAMES_INFO:
2030 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2031 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2032 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2033 break;
2034 case SMB_FIND_FILE_UNIX:
2035 case SMB_FIND_FILE_UNIX_INFO2:
2036 if (!lp_unix_extensions()) {
2037 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2039 break;
2040 default:
2041 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2044 if (info_level == SMB_FIND_EA_LIST) {
2045 uint32 ea_size;
2047 if (total_data < 4) {
2048 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2051 ea_size = IVAL(pdata,0);
2052 if (ea_size != total_data) {
2053 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2054 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2055 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2058 if (!lp_ea_support(SNUM(conn))) {
2059 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2062 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2063 return ERROR_NT(NT_STATUS_NO_MEMORY);
2066 /* Pull out the list of names. */
2067 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2068 if (!ea_list) {
2069 talloc_destroy(ea_ctx);
2070 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2074 *ppdata = (char *)SMB_REALLOC(
2075 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2076 if(*ppdata == NULL) {
2077 talloc_destroy(ea_ctx);
2078 return ERROR_NT(NT_STATUS_NO_MEMORY);
2081 pdata = *ppdata;
2082 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2084 /* Realloc the params space */
2085 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2086 if(*pparams == NULL ) {
2087 talloc_destroy(ea_ctx);
2088 return ERROR_NT(NT_STATUS_NO_MEMORY);
2091 params = *pparams;
2093 /* Check that the dptr is valid */
2094 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2095 talloc_destroy(ea_ctx);
2096 return ERROR_DOS(ERRDOS,ERRnofiles);
2099 string_set(&conn->dirpath,dptr_path(dptr_num));
2101 /* Get the wildcard mask from the dptr */
2102 if((p = dptr_wcard(dptr_num))== NULL) {
2103 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2104 talloc_destroy(ea_ctx);
2105 return ERROR_DOS(ERRDOS,ERRnofiles);
2108 pstrcpy(mask, p);
2109 pstrcpy(directory,conn->dirpath);
2111 /* Get the attr mask from the dptr */
2112 dirtype = dptr_attr(dptr_num);
2114 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2115 dptr_num, mask, dirtype,
2116 (long)conn->dirptr,
2117 dptr_TellDir(conn->dirptr)));
2119 /* We don't need to check for VOL here as this is returned by
2120 a different TRANS2 call. */
2122 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2123 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2124 dont_descend = True;
2126 p = pdata;
2127 space_remaining = max_data_bytes;
2128 out_of_space = False;
2131 * Seek to the correct position. We no longer use the resume key but
2132 * depend on the last file name instead.
2135 if(*resume_name && !continue_bit) {
2136 SMB_STRUCT_STAT st;
2138 long current_pos = 0;
2140 * Remember, mangle_map is called by
2141 * get_lanman2_dir_entry(), so the resume name
2142 * could be mangled. Ensure we check the unmangled name.
2145 if (mangle_is_mangled(resume_name, conn->params)) {
2146 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2147 conn->params);
2151 * Fix for NT redirector problem triggered by resume key indexes
2152 * changing between directory scans. We now return a resume key of 0
2153 * and instead look for the filename to continue from (also given
2154 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2155 * findfirst/findnext (as is usual) then the directory pointer
2156 * should already be at the correct place.
2159 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2160 } /* end if resume_name && !continue_bit */
2162 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2163 BOOL got_exact_match = False;
2165 /* this is a heuristic to avoid seeking the dirptr except when
2166 absolutely necessary. It allows for a filename of about 40 chars */
2167 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2168 out_of_space = True;
2169 finished = False;
2170 } else {
2171 finished = !get_lanman2_dir_entry(conn,
2172 inbuf, outbuf,
2173 mask,dirtype,info_level,
2174 requires_resume_key,dont_descend,
2175 &p,pdata,data_end,space_remaining, &out_of_space, &got_exact_match,
2176 &last_entry_off, ea_list, ea_ctx);
2179 if (finished && out_of_space)
2180 finished = False;
2182 if (!finished && !out_of_space)
2183 numentries++;
2186 * As an optimisation if we know we aren't looking
2187 * for a wildcard name (ie. the name matches the wildcard exactly)
2188 * then we can finish on any (first) match.
2189 * This speeds up large directory searches. JRA.
2192 if(got_exact_match)
2193 finished = True;
2195 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2198 talloc_destroy(ea_ctx);
2200 /* Check if we can close the dirptr */
2201 if(close_after_request || (finished && close_if_end)) {
2202 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2203 dptr_close(&dptr_num); /* This frees up the saved mask */
2206 /* Set up the return parameter block */
2207 SSVAL(params,0,numentries);
2208 SSVAL(params,2,finished);
2209 SSVAL(params,4,0); /* Never an EA error */
2210 SSVAL(params,6,last_entry_off);
2212 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2214 if ((! *directory) && dptr_path(dptr_num))
2215 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2217 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2218 smb_fn_name(CVAL(inbuf,smb_com)),
2219 mask, directory, dirtype, numentries ) );
2221 return(-1);
2224 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2226 SMB_ASSERT(extended_info != NULL);
2228 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2229 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2230 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2231 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2232 #ifdef SAMBA_VERSION_REVISION
2233 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2234 #endif
2235 extended_info->samba_subversion = 0;
2236 #ifdef SAMBA_VERSION_RC_RELEASE
2237 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2238 #else
2239 #ifdef SAMBA_VERSION_PRE_RELEASE
2240 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2241 #endif
2242 #endif
2243 #ifdef SAMBA_VERSION_VENDOR_PATCH
2244 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2245 #endif
2246 extended_info->samba_subversion = 0;
2247 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2248 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2249 #endif
2251 memset(extended_info->samba_version_string, 0,
2252 sizeof(extended_info->samba_version_string));
2254 snprintf (extended_info->samba_version_string,
2255 sizeof(extended_info->samba_version_string),
2256 "%s", samba_version_string());
2259 /****************************************************************************
2260 Reply to a TRANS2_QFSINFO (query filesystem info).
2261 ****************************************************************************/
2263 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2264 char **pparams, int total_params, char **ppdata, int total_data,
2265 unsigned int max_data_bytes)
2267 char *pdata;
2268 char *params = *pparams;
2269 uint16 info_level;
2270 int data_len, len;
2271 SMB_STRUCT_STAT st;
2272 const char *vname = volume_label(SNUM(conn));
2273 int snum = SNUM(conn);
2274 char *fstype = lp_fstype(SNUM(conn));
2275 int quota_flag = 0;
2277 if (total_params < 2) {
2278 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2281 info_level = SVAL(params,0);
2283 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2285 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2286 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2287 return ERROR_DOS(ERRSRV,ERRinvdevice);
2290 *ppdata = (char *)SMB_REALLOC(
2291 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2292 if (*ppdata == NULL ) {
2293 return ERROR_NT(NT_STATUS_NO_MEMORY);
2296 pdata = *ppdata;
2297 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2299 switch (info_level) {
2300 case SMB_INFO_ALLOCATION:
2302 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2303 data_len = 18;
2304 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2305 return(UNIXERROR(ERRHRD,ERRgeneral));
2308 block_size = lp_block_size(snum);
2309 if (bsize < block_size) {
2310 SMB_BIG_UINT factor = block_size/bsize;
2311 bsize = block_size;
2312 dsize /= factor;
2313 dfree /= factor;
2315 if (bsize > block_size) {
2316 SMB_BIG_UINT factor = bsize/block_size;
2317 bsize = block_size;
2318 dsize *= factor;
2319 dfree *= factor;
2321 bytes_per_sector = 512;
2322 sectors_per_unit = bsize/bytes_per_sector;
2324 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2325 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2326 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2328 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2329 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2330 SIVAL(pdata,l1_cUnit,dsize);
2331 SIVAL(pdata,l1_cUnitAvail,dfree);
2332 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2333 break;
2336 case SMB_INFO_VOLUME:
2337 /* Return volume name */
2339 * Add volume serial number - hash of a combination of
2340 * the called hostname and the service name.
2342 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2344 * Win2k3 and previous mess this up by sending a name length
2345 * one byte short. I believe only older clients (OS/2 Win9x) use
2346 * this call so try fixing this by adding a terminating null to
2347 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2349 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, max_data_bytes - l2_vol_szVolLabel, STR_NOALIGN|STR_TERMINATE);
2350 SCVAL(pdata,l2_vol_cch,len);
2351 data_len = l2_vol_szVolLabel + len;
2352 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2353 (unsigned)st.st_ctime, len, vname));
2354 break;
2356 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2357 case SMB_FS_ATTRIBUTE_INFORMATION:
2360 #if defined(HAVE_SYS_QUOTAS)
2361 quota_flag = FILE_VOLUME_QUOTAS;
2362 #endif
2364 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2365 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2366 FILE_UNICODE_ON_DISK|
2367 quota_flag); /* FS ATTRIBUTES */
2369 SIVAL(pdata,4,255); /* Max filename component length */
2370 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2371 and will think we can't do long filenames */
2372 len = srvstr_push(outbuf, pdata+12, fstype, max_data_bytes - 12, STR_UNICODE);
2373 SIVAL(pdata,8,len);
2374 data_len = 12 + len;
2375 break;
2377 case SMB_QUERY_FS_LABEL_INFO:
2378 case SMB_FS_LABEL_INFORMATION:
2379 len = srvstr_push(outbuf, pdata+4, vname, max_data_bytes - 4, 0);
2380 data_len = 4 + len;
2381 SIVAL(pdata,0,len);
2382 break;
2384 case SMB_QUERY_FS_VOLUME_INFO:
2385 case SMB_FS_VOLUME_INFORMATION:
2388 * Add volume serial number - hash of a combination of
2389 * the called hostname and the service name.
2391 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2392 (str_checksum(get_local_machine_name())<<16));
2394 /* Max label len is 32 characters. */
2395 len = srvstr_push(outbuf, pdata+18, vname, max_data_bytes - 18, STR_UNICODE);
2396 SIVAL(pdata,12,len);
2397 data_len = 18+len;
2399 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2400 (int)strlen(vname),vname, lp_servicename(snum)));
2401 break;
2403 case SMB_QUERY_FS_SIZE_INFO:
2404 case SMB_FS_SIZE_INFORMATION:
2406 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2407 data_len = 24;
2408 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2409 return(UNIXERROR(ERRHRD,ERRgeneral));
2411 block_size = lp_block_size(snum);
2412 if (bsize < block_size) {
2413 SMB_BIG_UINT factor = block_size/bsize;
2414 bsize = block_size;
2415 dsize /= factor;
2416 dfree /= factor;
2418 if (bsize > block_size) {
2419 SMB_BIG_UINT factor = bsize/block_size;
2420 bsize = block_size;
2421 dsize *= factor;
2422 dfree *= factor;
2424 bytes_per_sector = 512;
2425 sectors_per_unit = bsize/bytes_per_sector;
2426 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2427 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2428 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2429 SBIG_UINT(pdata,0,dsize);
2430 SBIG_UINT(pdata,8,dfree);
2431 SIVAL(pdata,16,sectors_per_unit);
2432 SIVAL(pdata,20,bytes_per_sector);
2433 break;
2436 case SMB_FS_FULL_SIZE_INFORMATION:
2438 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2439 data_len = 32;
2440 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2441 return(UNIXERROR(ERRHRD,ERRgeneral));
2443 block_size = lp_block_size(snum);
2444 if (bsize < block_size) {
2445 SMB_BIG_UINT factor = block_size/bsize;
2446 bsize = block_size;
2447 dsize /= factor;
2448 dfree /= factor;
2450 if (bsize > block_size) {
2451 SMB_BIG_UINT factor = bsize/block_size;
2452 bsize = block_size;
2453 dsize *= factor;
2454 dfree *= factor;
2456 bytes_per_sector = 512;
2457 sectors_per_unit = bsize/bytes_per_sector;
2458 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2459 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2460 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2461 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2462 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2463 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2464 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2465 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2466 break;
2469 case SMB_QUERY_FS_DEVICE_INFO:
2470 case SMB_FS_DEVICE_INFORMATION:
2471 data_len = 8;
2472 SIVAL(pdata,0,0); /* dev type */
2473 SIVAL(pdata,4,0); /* characteristics */
2474 break;
2476 #ifdef HAVE_SYS_QUOTAS
2477 case SMB_FS_QUOTA_INFORMATION:
2479 * what we have to send --metze:
2481 * Unknown1: 24 NULL bytes
2482 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2483 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2484 * Quota Flags: 2 byte :
2485 * Unknown3: 6 NULL bytes
2487 * 48 bytes total
2489 * details for Quota Flags:
2491 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2492 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2493 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2494 * 0x0001 Enable Quotas: enable quota for this fs
2498 /* we need to fake up a fsp here,
2499 * because its not send in this call
2501 files_struct fsp;
2502 SMB_NTQUOTA_STRUCT quotas;
2504 ZERO_STRUCT(fsp);
2505 ZERO_STRUCT(quotas);
2507 fsp.conn = conn;
2508 fsp.fnum = -1;
2510 /* access check */
2511 if (current_user.ut.uid != 0) {
2512 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2513 lp_servicename(SNUM(conn)),conn->user));
2514 return ERROR_DOS(ERRDOS,ERRnoaccess);
2517 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2518 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2519 return ERROR_DOS(ERRSRV,ERRerror);
2522 data_len = 48;
2524 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2526 /* Unknown1 24 NULL bytes*/
2527 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2528 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2529 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2531 /* Default Soft Quota 8 bytes */
2532 SBIG_UINT(pdata,24,quotas.softlim);
2534 /* Default Hard Quota 8 bytes */
2535 SBIG_UINT(pdata,32,quotas.hardlim);
2537 /* Quota flag 2 bytes */
2538 SSVAL(pdata,40,quotas.qflags);
2540 /* Unknown3 6 NULL bytes */
2541 SSVAL(pdata,42,0);
2542 SIVAL(pdata,44,0);
2544 break;
2546 #endif /* HAVE_SYS_QUOTAS */
2547 case SMB_FS_OBJECTID_INFORMATION:
2550 * No object id, but we transmit version information.
2552 struct smb_extended_info extended_info;
2553 samba_extended_info_version (&extended_info);
2554 SIVAL(pdata,16,extended_info.samba_magic);
2555 SIVAL(pdata,20,extended_info.samba_version);
2556 SIVAL(pdata,24,extended_info.samba_subversion);
2557 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2558 memcpy(pdata+36,extended_info.samba_version_string,28);
2559 data_len = 64;
2560 break;
2564 * Query the version and capabilities of the CIFS UNIX extensions
2565 * in use.
2568 case SMB_QUERY_CIFS_UNIX_INFO:
2569 if (!lp_unix_extensions()) {
2570 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2572 data_len = 12;
2573 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2574 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2575 /* We have POSIX ACLs, pathname and locking capability. */
2576 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2577 CIFS_UNIX_POSIX_ACLS_CAP|
2578 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2579 CIFS_UNIX_FCNTL_LOCKS_CAP|
2580 CIFS_UNIX_EXTATTR_CAP|
2581 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2582 break;
2584 case SMB_QUERY_POSIX_FS_INFO:
2586 int rc;
2587 vfs_statvfs_struct svfs;
2589 if (!lp_unix_extensions()) {
2590 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2593 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2595 if (!rc) {
2596 data_len = 56;
2597 SIVAL(pdata,0,svfs.OptimalTransferSize);
2598 SIVAL(pdata,4,svfs.BlockSize);
2599 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2600 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2601 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2602 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2603 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2604 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2605 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2606 #ifdef EOPNOTSUPP
2607 } else if (rc == EOPNOTSUPP) {
2608 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2609 #endif /* EOPNOTSUPP */
2610 } else {
2611 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2612 return ERROR_DOS(ERRSRV,ERRerror);
2614 break;
2617 case SMB_QUERY_POSIX_WHOAMI:
2619 uint32_t flags = 0;
2620 uint32_t sid_bytes;
2621 int i;
2623 if (!lp_unix_extensions()) {
2624 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2627 if (max_data_bytes < 40) {
2628 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2631 /* We ARE guest if global_sid_Builtin_Guests is
2632 * in our list of SIDs.
2634 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2635 current_user.nt_user_token)) {
2636 flags |= SMB_WHOAMI_GUEST;
2639 /* We are NOT guest if global_sid_Authenticated_Users
2640 * is in our list of SIDs.
2642 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2643 current_user.nt_user_token)) {
2644 flags &= ~SMB_WHOAMI_GUEST;
2647 /* NOTE: 8 bytes for UID/GID, irrespective of native
2648 * platform size. This matches
2649 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2651 data_len = 4 /* flags */
2652 + 4 /* flag mask */
2653 + 8 /* uid */
2654 + 8 /* gid */
2655 + 4 /* ngroups */
2656 + 4 /* num_sids */
2657 + 4 /* SID bytes */
2658 + 4 /* pad/reserved */
2659 + (current_user.ut.ngroups * 8)
2660 /* groups list */
2661 + (current_user.nt_user_token->num_sids *
2662 SID_MAX_SIZE)
2663 /* SID list */;
2665 SIVAL(pdata, 0, flags);
2666 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2667 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2668 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2671 if (data_len >= max_data_bytes) {
2672 /* Potential overflow, skip the GIDs and SIDs. */
2674 SIVAL(pdata, 24, 0); /* num_groups */
2675 SIVAL(pdata, 28, 0); /* num_sids */
2676 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2677 SIVAL(pdata, 36, 0); /* reserved */
2679 data_len = 40;
2680 break;
2683 SIVAL(pdata, 24, current_user.ut.ngroups);
2684 SIVAL(pdata, 28,
2685 current_user.nt_user_token->num_sids);
2687 /* We walk the SID list twice, but this call is fairly
2688 * infrequent, and I don't expect that it's performance
2689 * sensitive -- jpeach
2691 for (i = 0, sid_bytes = 0;
2692 i < current_user.nt_user_token->num_sids; ++i) {
2693 sid_bytes +=
2694 sid_size(&current_user.nt_user_token->user_sids[i]);
2697 /* SID list byte count */
2698 SIVAL(pdata, 32, sid_bytes);
2700 /* 4 bytes pad/reserved - must be zero */
2701 SIVAL(pdata, 36, 0);
2702 data_len = 40;
2704 /* GID list */
2705 for (i = 0; i < current_user.ut.ngroups; ++i) {
2706 SBIG_UINT(pdata, data_len,
2707 (SMB_BIG_UINT)current_user.ut.groups[i]);
2708 data_len += 8;
2711 /* SID list */
2712 for (i = 0;
2713 i < current_user.nt_user_token->num_sids; ++i) {
2714 int sid_len =
2715 sid_size(&current_user.nt_user_token->user_sids[i]);
2717 sid_linearize(pdata + data_len, sid_len,
2718 &current_user.nt_user_token->user_sids[i]);
2719 data_len += sid_len;
2722 break;
2725 case SMB_MAC_QUERY_FS_INFO:
2727 * Thursby MAC extension... ONLY on NTFS filesystems
2728 * once we do streams then we don't need this
2730 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2731 data_len = 88;
2732 SIVAL(pdata,84,0x100); /* Don't support mac... */
2733 break;
2735 /* drop through */
2736 default:
2737 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2741 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2743 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2745 return -1;
2748 /****************************************************************************
2749 Reply to a TRANS2_SETFSINFO (set filesystem info).
2750 ****************************************************************************/
2752 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2753 char **pparams, int total_params, char **ppdata, int total_data,
2754 unsigned int max_data_bytes)
2756 char *pdata = *ppdata;
2757 char *params = *pparams;
2758 uint16 info_level;
2759 int outsize;
2761 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2763 /* */
2764 if (total_params < 4) {
2765 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2766 total_params));
2767 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2770 info_level = SVAL(params,2);
2772 switch(info_level) {
2773 case SMB_SET_CIFS_UNIX_INFO:
2775 uint16 client_unix_major;
2776 uint16 client_unix_minor;
2777 uint32 client_unix_cap_low;
2778 uint32 client_unix_cap_high;
2780 if (!lp_unix_extensions()) {
2781 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2784 /* There should be 12 bytes of capabilities set. */
2785 if (total_data < 8) {
2786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2788 client_unix_major = SVAL(pdata,0);
2789 client_unix_minor = SVAL(pdata,2);
2790 client_unix_cap_low = IVAL(pdata,4);
2791 client_unix_cap_high = IVAL(pdata,8);
2792 /* Just print these values for now. */
2793 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2794 cap_low = 0x%x, cap_high = 0x%x\n",
2795 (unsigned int)client_unix_major,
2796 (unsigned int)client_unix_minor,
2797 (unsigned int)client_unix_cap_low,
2798 (unsigned int)client_unix_cap_high ));
2800 /* Here is where we must switch to posix pathname processing... */
2801 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2802 lp_set_posix_pathnames();
2803 mangle_change_to_posix();
2806 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2807 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2808 /* Client that knows how to do posix locks,
2809 * but not posix open/mkdir operations. Set a
2810 * default type for read/write checks. */
2812 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2815 break;
2817 case SMB_FS_QUOTA_INFORMATION:
2819 files_struct *fsp = NULL;
2820 SMB_NTQUOTA_STRUCT quotas;
2822 ZERO_STRUCT(quotas);
2824 /* access check */
2825 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2826 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2827 lp_servicename(SNUM(conn)),conn->user));
2828 return ERROR_DOS(ERRSRV,ERRaccess);
2831 /* note: normaly there're 48 bytes,
2832 * but we didn't use the last 6 bytes for now
2833 * --metze
2835 fsp = file_fsp(params,0);
2836 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2837 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2838 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2841 if (total_data < 42) {
2842 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2843 total_data));
2844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2847 /* unknown_1 24 NULL bytes in pdata*/
2849 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2850 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2851 #ifdef LARGE_SMB_OFF_T
2852 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2853 #else /* LARGE_SMB_OFF_T */
2854 if ((IVAL(pdata,28) != 0)&&
2855 ((quotas.softlim != 0xFFFFFFFF)||
2856 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2857 /* more than 32 bits? */
2858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2860 #endif /* LARGE_SMB_OFF_T */
2862 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2863 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2864 #ifdef LARGE_SMB_OFF_T
2865 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2866 #else /* LARGE_SMB_OFF_T */
2867 if ((IVAL(pdata,36) != 0)&&
2868 ((quotas.hardlim != 0xFFFFFFFF)||
2869 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2870 /* more than 32 bits? */
2871 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2873 #endif /* LARGE_SMB_OFF_T */
2875 /* quota_flags 2 bytes **/
2876 quotas.qflags = SVAL(pdata,40);
2878 /* unknown_2 6 NULL bytes follow*/
2880 /* now set the quotas */
2881 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2882 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2883 return ERROR_DOS(ERRSRV,ERRerror);
2886 break;
2888 default:
2889 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2890 info_level));
2891 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2892 break;
2896 * sending this reply works fine,
2897 * but I'm not sure it's the same
2898 * like windows do...
2899 * --metze
2901 outsize = set_message(outbuf,10,0,True);
2903 return outsize;
2906 #if defined(HAVE_POSIX_ACLS)
2907 /****************************************************************************
2908 Utility function to count the number of entries in a POSIX acl.
2909 ****************************************************************************/
2911 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2913 unsigned int ace_count = 0;
2914 int entry_id = SMB_ACL_FIRST_ENTRY;
2915 SMB_ACL_ENTRY_T entry;
2917 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2918 /* get_next... */
2919 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2920 entry_id = SMB_ACL_NEXT_ENTRY;
2922 ace_count++;
2924 return ace_count;
2927 /****************************************************************************
2928 Utility function to marshall a POSIX acl into wire format.
2929 ****************************************************************************/
2931 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2933 int entry_id = SMB_ACL_FIRST_ENTRY;
2934 SMB_ACL_ENTRY_T entry;
2936 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2937 SMB_ACL_TAG_T tagtype;
2938 SMB_ACL_PERMSET_T permset;
2939 unsigned char perms = 0;
2940 unsigned int own_grp;
2942 /* get_next... */
2943 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2944 entry_id = SMB_ACL_NEXT_ENTRY;
2947 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2948 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2949 return False;
2952 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2953 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2954 return False;
2957 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2958 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2959 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2961 SCVAL(pdata,1,perms);
2963 switch (tagtype) {
2964 case SMB_ACL_USER_OBJ:
2965 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2966 own_grp = (unsigned int)pst->st_uid;
2967 SIVAL(pdata,2,own_grp);
2968 SIVAL(pdata,6,0);
2969 break;
2970 case SMB_ACL_USER:
2972 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2973 if (!puid) {
2974 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2976 own_grp = (unsigned int)*puid;
2977 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2978 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2979 SIVAL(pdata,2,own_grp);
2980 SIVAL(pdata,6,0);
2981 break;
2983 case SMB_ACL_GROUP_OBJ:
2984 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2985 own_grp = (unsigned int)pst->st_gid;
2986 SIVAL(pdata,2,own_grp);
2987 SIVAL(pdata,6,0);
2988 break;
2989 case SMB_ACL_GROUP:
2991 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2992 if (!pgid) {
2993 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2995 own_grp = (unsigned int)*pgid;
2996 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2997 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2998 SIVAL(pdata,2,own_grp);
2999 SIVAL(pdata,6,0);
3000 break;
3002 case SMB_ACL_MASK:
3003 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3004 SIVAL(pdata,2,0xFFFFFFFF);
3005 SIVAL(pdata,6,0xFFFFFFFF);
3006 break;
3007 case SMB_ACL_OTHER:
3008 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3009 SIVAL(pdata,2,0xFFFFFFFF);
3010 SIVAL(pdata,6,0xFFFFFFFF);
3011 break;
3012 default:
3013 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3014 return False;
3016 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3019 return True;
3021 #endif
3023 /****************************************************************************
3024 Store the FILE_UNIX_BASIC info.
3025 ****************************************************************************/
3027 static char *store_file_unix_basic(connection_struct *conn,
3028 char *pdata,
3029 files_struct *fsp,
3030 const SMB_STRUCT_STAT *psbuf)
3032 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3033 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3035 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3036 pdata += 8;
3038 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3039 pdata += 8;
3041 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3042 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3043 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3044 pdata += 24;
3046 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3047 SIVAL(pdata,4,0);
3048 pdata += 8;
3050 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3051 SIVAL(pdata,4,0);
3052 pdata += 8;
3054 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3055 pdata += 4;
3057 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3058 SIVAL(pdata,4,0);
3059 pdata += 8;
3061 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3062 SIVAL(pdata,4,0);
3063 pdata += 8;
3065 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3066 pdata += 8;
3068 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3069 SIVAL(pdata,4,0);
3070 pdata += 8;
3072 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3073 SIVAL(pdata,4,0);
3074 pdata += 8;
3076 return pdata;
3079 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3080 * the chflags(2) (or equivalent) flags.
3082 * XXX: this really should be behind the VFS interface. To do this, we would
3083 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3084 * Each VFS module could then implement it's own mapping as appropriate for the
3085 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3087 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3088 info2_flags_map[] =
3090 #ifdef UF_NODUMP
3091 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3092 #endif
3094 #ifdef UF_IMMUTABLE
3095 { UF_IMMUTABLE, EXT_IMMUTABLE },
3096 #endif
3098 #ifdef UF_APPEND
3099 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3100 #endif
3102 #ifdef UF_HIDDEN
3103 { UF_HIDDEN, EXT_HIDDEN },
3104 #endif
3106 /* Do not remove. We need to guarantee that this array has at least one
3107 * entry to build on HP-UX.
3109 { 0, 0 }
3113 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3114 uint32 *smb_fflags, uint32 *smb_fmask)
3116 #ifdef HAVE_STAT_ST_FLAGS
3117 int i;
3119 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3120 *smb_fmask |= info2_flags_map[i].smb_fflag;
3121 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3122 *smb_fflags |= info2_flags_map[i].smb_fflag;
3125 #endif /* HAVE_STAT_ST_FLAGS */
3128 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3129 const uint32 smb_fflags,
3130 const uint32 smb_fmask,
3131 int *stat_fflags)
3133 #ifdef HAVE_STAT_ST_FLAGS
3134 uint32 max_fmask = 0;
3135 int i;
3137 *stat_fflags = psbuf->st_flags;
3139 /* For each flags requested in smb_fmask, check the state of the
3140 * corresponding flag in smb_fflags and set or clear the matching
3141 * stat flag.
3144 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3145 max_fmask |= info2_flags_map[i].smb_fflag;
3146 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3147 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3148 *stat_fflags |= info2_flags_map[i].stat_fflag;
3149 } else {
3150 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3155 /* If smb_fmask is asking to set any bits that are not supported by
3156 * our flag mappings, we should fail.
3158 if ((smb_fmask & max_fmask) != smb_fmask) {
3159 return False;
3162 return True;
3163 #else
3164 return False;
3165 #endif /* HAVE_STAT_ST_FLAGS */
3169 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3170 * of file flags and birth (create) time.
3172 static char *store_file_unix_basic_info2(connection_struct *conn,
3173 char *pdata,
3174 files_struct *fsp,
3175 const SMB_STRUCT_STAT *psbuf)
3177 uint32 file_flags = 0;
3178 uint32 flags_mask = 0;
3180 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3182 /* Create (birth) time 64 bit */
3183 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3184 pdata += 8;
3186 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3187 SIVAL(pdata, 0, file_flags); /* flags */
3188 SIVAL(pdata, 4, flags_mask); /* mask */
3189 pdata += 8;
3191 return pdata;
3194 /****************************************************************************
3195 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3196 file name or file id).
3197 ****************************************************************************/
3199 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3200 unsigned int tran_call,
3201 char **pparams, int total_params, char **ppdata, int total_data,
3202 unsigned int max_data_bytes)
3204 char *params = *pparams;
3205 char *pdata = *ppdata;
3206 uint16 info_level;
3207 int mode=0;
3208 int nlink;
3209 SMB_OFF_T file_size=0;
3210 SMB_BIG_UINT allocation_size=0;
3211 unsigned int data_size = 0;
3212 unsigned int param_size = 2;
3213 SMB_STRUCT_STAT sbuf;
3214 pstring fname, dos_fname;
3215 char *fullpathname;
3216 char *base_name;
3217 char *p;
3218 SMB_OFF_T pos = 0;
3219 BOOL delete_pending = False;
3220 int len;
3221 time_t create_time, mtime, atime;
3222 struct timespec create_time_ts, mtime_ts, atime_ts;
3223 files_struct *fsp = NULL;
3224 TALLOC_CTX *data_ctx = NULL;
3225 struct ea_list *ea_list = NULL;
3226 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3227 char *lock_data = NULL;
3229 if (!params)
3230 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3232 ZERO_STRUCT(sbuf);
3234 if (tran_call == TRANSACT2_QFILEINFO) {
3235 if (total_params < 4) {
3236 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3239 fsp = file_fsp(params,0);
3240 info_level = SVAL(params,2);
3242 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3244 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3245 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3248 if(fsp && (fsp->fake_file_handle)) {
3250 * This is actually for the QUOTA_FAKE_FILE --metze
3253 pstrcpy(fname, fsp->fsp_name);
3254 /* We know this name is ok, it's already passed the checks. */
3256 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3258 * This is actually a QFILEINFO on a directory
3259 * handle (returned from an NT SMB). NT5.0 seems
3260 * to do this call. JRA.
3262 /* We know this name is ok, it's already passed the checks. */
3263 pstrcpy(fname, fsp->fsp_name);
3265 if (INFO_LEVEL_IS_UNIX(info_level)) {
3266 /* Always do lstat for UNIX calls. */
3267 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3268 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3269 return UNIXERROR(ERRDOS,ERRbadpath);
3271 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3272 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3273 return UNIXERROR(ERRDOS,ERRbadpath);
3276 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3277 } else {
3279 * Original code - this is an open file.
3281 CHECK_FSP(fsp,conn);
3283 pstrcpy(fname, fsp->fsp_name);
3284 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3285 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3286 return(UNIXERROR(ERRDOS,ERRbadfid));
3288 pos = fsp->fh->position_information;
3289 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3290 access_mask = fsp->access_mask;
3292 } else {
3293 NTSTATUS status = NT_STATUS_OK;
3295 /* qpathinfo */
3296 if (total_params < 7) {
3297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3300 info_level = SVAL(params,0);
3302 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3304 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3305 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3308 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3309 if (!NT_STATUS_IS_OK(status)) {
3310 return ERROR_NT(status);
3313 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3316 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3318 return ERROR_NT(status);
3321 status = unix_convert(conn, fname, False, NULL, &sbuf);
3322 if (!NT_STATUS_IS_OK(status)) {
3323 return ERROR_NT(status);
3325 status = check_name(conn, fname);
3326 if (!NT_STATUS_IS_OK(status)) {
3327 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3328 return ERROR_NT(status);
3331 if (INFO_LEVEL_IS_UNIX(info_level)) {
3332 /* Always do lstat for UNIX calls. */
3333 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3334 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3335 return UNIXERROR(ERRDOS,ERRbadpath);
3337 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3338 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3339 return UNIXERROR(ERRDOS,ERRbadpath);
3342 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3343 if (delete_pending) {
3344 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3348 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3349 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3352 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3353 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3355 p = strrchr_m(fname,'/');
3356 if (!p)
3357 base_name = fname;
3358 else
3359 base_name = p+1;
3361 mode = dos_mode(conn,fname,&sbuf);
3362 if (!mode)
3363 mode = FILE_ATTRIBUTE_NORMAL;
3365 nlink = sbuf.st_nlink;
3367 if (nlink && (mode&aDIR)) {
3368 nlink = 1;
3371 if ((nlink > 0) && delete_pending) {
3372 nlink -= 1;
3375 fullpathname = fname;
3376 if (!(mode & aDIR))
3377 file_size = get_file_size(sbuf);
3379 /* Pull out any data sent here before we realloc. */
3380 switch (info_level) {
3381 case SMB_INFO_QUERY_EAS_FROM_LIST:
3383 /* Pull any EA list from the data portion. */
3384 uint32 ea_size;
3386 if (total_data < 4) {
3387 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3389 ea_size = IVAL(pdata,0);
3391 if (total_data > 0 && ea_size != total_data) {
3392 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3393 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3394 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3397 if (!lp_ea_support(SNUM(conn))) {
3398 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3401 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3402 return ERROR_NT(NT_STATUS_NO_MEMORY);
3405 /* Pull out the list of names. */
3406 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3407 if (!ea_list) {
3408 talloc_destroy(data_ctx);
3409 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3411 break;
3414 case SMB_QUERY_POSIX_LOCK:
3416 if (fsp == NULL || fsp->fh->fd == -1) {
3417 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3420 if (total_data != POSIX_LOCK_DATA_SIZE) {
3421 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3424 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3425 return ERROR_NT(NT_STATUS_NO_MEMORY);
3428 /* Copy the lock range data. */
3429 lock_data = (char *)TALLOC_MEMDUP(
3430 data_ctx, pdata, total_data);
3431 if (!lock_data) {
3432 talloc_destroy(data_ctx);
3433 return ERROR_NT(NT_STATUS_NO_MEMORY);
3436 default:
3437 break;
3440 *pparams = (char *)SMB_REALLOC(*pparams,2);
3441 if (*pparams == NULL) {
3442 talloc_destroy(data_ctx);
3443 return ERROR_NT(NT_STATUS_NO_MEMORY);
3445 params = *pparams;
3446 SSVAL(params,0,0);
3447 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3448 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3449 if (*ppdata == NULL ) {
3450 talloc_destroy(data_ctx);
3451 return ERROR_NT(NT_STATUS_NO_MEMORY);
3453 pdata = *ppdata;
3455 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3456 mtime_ts = get_mtimespec(&sbuf);
3457 atime_ts = get_atimespec(&sbuf);
3459 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3461 if (fsp) {
3462 if (!null_timespec(fsp->pending_modtime)) {
3463 /* the pending modtime overrides the current modtime */
3464 mtime_ts = fsp->pending_modtime;
3466 } else {
3467 /* Do we have this path open ? */
3468 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3469 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3470 /* the pending modtime overrides the current modtime */
3471 mtime_ts = fsp1->pending_modtime;
3473 if (fsp1 && fsp1->initial_allocation_size) {
3474 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3478 if (lp_dos_filetime_resolution(SNUM(conn))) {
3479 dos_filetime_timespec(&create_time_ts);
3480 dos_filetime_timespec(&mtime_ts);
3481 dos_filetime_timespec(&atime_ts);
3484 create_time = convert_timespec_to_time_t(create_time_ts);
3485 mtime = convert_timespec_to_time_t(mtime_ts);
3486 atime = convert_timespec_to_time_t(atime_ts);
3488 /* NT expects the name to be in an exact form of the *full*
3489 filename. See the trans2 torture test */
3490 if (strequal(base_name,".")) {
3491 pstrcpy(dos_fname, "\\");
3492 } else {
3493 pstr_sprintf(dos_fname, "\\%s", fname);
3494 string_replace(dos_fname, '/', '\\');
3497 switch (info_level) {
3498 case SMB_INFO_STANDARD:
3499 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3500 data_size = 22;
3501 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3502 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3503 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3504 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3505 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3506 SSVAL(pdata,l1_attrFile,mode);
3507 break;
3509 case SMB_INFO_QUERY_EA_SIZE:
3511 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3512 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3513 data_size = 26;
3514 srv_put_dos_date2(pdata,0,create_time);
3515 srv_put_dos_date2(pdata,4,atime);
3516 srv_put_dos_date2(pdata,8,mtime); /* write time */
3517 SIVAL(pdata,12,(uint32)file_size);
3518 SIVAL(pdata,16,(uint32)allocation_size);
3519 SSVAL(pdata,20,mode);
3520 SIVAL(pdata,22,ea_size);
3521 break;
3524 case SMB_INFO_IS_NAME_VALID:
3525 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3526 if (tran_call == TRANSACT2_QFILEINFO) {
3527 /* os/2 needs this ? really ?*/
3528 return ERROR_DOS(ERRDOS,ERRbadfunc);
3530 data_size = 0;
3531 param_size = 0;
3532 break;
3534 case SMB_INFO_QUERY_EAS_FROM_LIST:
3536 size_t total_ea_len = 0;
3537 struct ea_list *ea_file_list = NULL;
3539 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3541 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3542 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3544 if (!ea_list || (total_ea_len > data_size)) {
3545 talloc_destroy(data_ctx);
3546 data_size = 4;
3547 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3548 break;
3551 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3552 talloc_destroy(data_ctx);
3553 break;
3556 case SMB_INFO_QUERY_ALL_EAS:
3558 /* We have data_size bytes to put EA's into. */
3559 size_t total_ea_len = 0;
3561 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3563 data_ctx = talloc_init("ea_ctx");
3564 if (!data_ctx) {
3565 return ERROR_NT(NT_STATUS_NO_MEMORY);
3568 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3569 if (!ea_list || (total_ea_len > data_size)) {
3570 talloc_destroy(data_ctx);
3571 data_size = 4;
3572 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3573 break;
3576 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3577 talloc_destroy(data_ctx);
3578 break;
3581 case SMB_FILE_BASIC_INFORMATION:
3582 case SMB_QUERY_FILE_BASIC_INFO:
3584 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3585 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3586 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3587 } else {
3588 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3589 data_size = 40;
3590 SIVAL(pdata,36,0);
3592 put_long_date_timespec(pdata,create_time_ts);
3593 put_long_date_timespec(pdata+8,atime_ts);
3594 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3595 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3596 SIVAL(pdata,32,mode);
3598 DEBUG(5,("SMB_QFBI - "));
3599 DEBUG(5,("create: %s ", ctime(&create_time)));
3600 DEBUG(5,("access: %s ", ctime(&atime)));
3601 DEBUG(5,("write: %s ", ctime(&mtime)));
3602 DEBUG(5,("change: %s ", ctime(&mtime)));
3603 DEBUG(5,("mode: %x\n", mode));
3604 break;
3606 case SMB_FILE_STANDARD_INFORMATION:
3607 case SMB_QUERY_FILE_STANDARD_INFO:
3609 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3610 data_size = 24;
3611 SOFF_T(pdata,0,allocation_size);
3612 SOFF_T(pdata,8,file_size);
3613 SIVAL(pdata,16,nlink);
3614 SCVAL(pdata,20,delete_pending?1:0);
3615 SCVAL(pdata,21,(mode&aDIR)?1:0);
3616 SSVAL(pdata,22,0); /* Padding. */
3617 break;
3619 case SMB_FILE_EA_INFORMATION:
3620 case SMB_QUERY_FILE_EA_INFO:
3622 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3623 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3624 data_size = 4;
3625 SIVAL(pdata,0,ea_size);
3626 break;
3629 /* Get the 8.3 name - used if NT SMB was negotiated. */
3630 case SMB_QUERY_FILE_ALT_NAME_INFO:
3631 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3633 pstring short_name;
3635 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3636 pstrcpy(short_name,base_name);
3637 /* Mangle if not already 8.3 */
3638 if(!mangle_is_8_3(short_name, True, conn->params)) {
3639 mangle_map(short_name,True,True,conn->params);
3641 len = srvstr_push(outbuf, pdata+4, short_name, max_data_bytes - 4, STR_UNICODE);
3642 data_size = 4 + len;
3643 SIVAL(pdata,0,len);
3644 break;
3647 case SMB_QUERY_FILE_NAME_INFO:
3649 this must be *exactly* right for ACLs on mapped drives to work
3651 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - 4, STR_UNICODE);
3652 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3653 data_size = 4 + len;
3654 SIVAL(pdata,0,len);
3655 break;
3657 case SMB_FILE_ALLOCATION_INFORMATION:
3658 case SMB_QUERY_FILE_ALLOCATION_INFO:
3659 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3660 data_size = 8;
3661 SOFF_T(pdata,0,allocation_size);
3662 break;
3664 case SMB_FILE_END_OF_FILE_INFORMATION:
3665 case SMB_QUERY_FILE_END_OF_FILEINFO:
3666 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3667 data_size = 8;
3668 SOFF_T(pdata,0,file_size);
3669 break;
3671 case SMB_QUERY_FILE_ALL_INFO:
3672 case SMB_FILE_ALL_INFORMATION:
3674 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3675 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3676 put_long_date_timespec(pdata,create_time_ts);
3677 put_long_date_timespec(pdata+8,atime_ts);
3678 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3679 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3680 SIVAL(pdata,32,mode);
3681 SIVAL(pdata,36,0); /* padding. */
3682 pdata += 40;
3683 SOFF_T(pdata,0,allocation_size);
3684 SOFF_T(pdata,8,file_size);
3685 SIVAL(pdata,16,nlink);
3686 SCVAL(pdata,20,delete_pending);
3687 SCVAL(pdata,21,(mode&aDIR)?1:0);
3688 SSVAL(pdata,22,0);
3689 pdata += 24;
3690 SIVAL(pdata,0,ea_size);
3691 pdata += 4; /* EA info */
3692 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - (pdata+4 - *ppdata), STR_UNICODE);
3693 SIVAL(pdata,0,len);
3694 pdata += 4 + len;
3695 data_size = PTR_DIFF(pdata,(*ppdata));
3696 break;
3698 case SMB_FILE_INTERNAL_INFORMATION:
3699 /* This should be an index number - looks like
3700 dev/ino to me :-)
3702 I think this causes us to fail the IFSKIT
3703 BasicFileInformationTest. -tpot */
3705 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3706 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3707 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3708 data_size = 8;
3709 break;
3711 case SMB_FILE_ACCESS_INFORMATION:
3712 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3713 SIVAL(pdata,0,access_mask);
3714 data_size = 4;
3715 break;
3717 case SMB_FILE_NAME_INFORMATION:
3718 /* Pathname with leading '\'. */
3720 size_t byte_len;
3721 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3722 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3723 SIVAL(pdata,0,byte_len);
3724 data_size = 4 + byte_len;
3725 break;
3728 case SMB_FILE_DISPOSITION_INFORMATION:
3729 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3730 data_size = 1;
3731 SCVAL(pdata,0,delete_pending);
3732 break;
3734 case SMB_FILE_POSITION_INFORMATION:
3735 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3736 data_size = 8;
3737 SOFF_T(pdata,0,pos);
3738 break;
3740 case SMB_FILE_MODE_INFORMATION:
3741 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3742 SIVAL(pdata,0,mode);
3743 data_size = 4;
3744 break;
3746 case SMB_FILE_ALIGNMENT_INFORMATION:
3747 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3748 SIVAL(pdata,0,0); /* No alignment needed. */
3749 data_size = 4;
3750 break;
3752 #if 0
3754 * NT4 server just returns "invalid query" to this - if we try to answer
3755 * it then NTws gets a BSOD! (tridge).
3756 * W2K seems to want this. JRA.
3758 case SMB_QUERY_FILE_STREAM_INFO:
3759 #endif
3760 case SMB_FILE_STREAM_INFORMATION:
3761 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3762 if (mode & aDIR) {
3763 data_size = 0;
3764 } else {
3765 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3766 SIVAL(pdata,0,0); /* ??? */
3767 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3768 SOFF_T(pdata,8,file_size);
3769 SOFF_T(pdata,16,allocation_size);
3770 data_size = 24 + byte_len;
3772 break;
3774 case SMB_QUERY_COMPRESSION_INFO:
3775 case SMB_FILE_COMPRESSION_INFORMATION:
3776 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3777 SOFF_T(pdata,0,file_size);
3778 SIVAL(pdata,8,0); /* ??? */
3779 SIVAL(pdata,12,0); /* ??? */
3780 data_size = 16;
3781 break;
3783 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3784 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3785 put_long_date_timespec(pdata,create_time_ts);
3786 put_long_date_timespec(pdata+8,atime_ts);
3787 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3788 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3789 SOFF_T(pdata,32,allocation_size);
3790 SOFF_T(pdata,40,file_size);
3791 SIVAL(pdata,48,mode);
3792 SIVAL(pdata,52,0); /* ??? */
3793 data_size = 56;
3794 break;
3796 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3797 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3798 SIVAL(pdata,0,mode);
3799 SIVAL(pdata,4,0);
3800 data_size = 8;
3801 break;
3804 * CIFS UNIX Extensions.
3807 case SMB_QUERY_FILE_UNIX_BASIC:
3809 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3810 data_size = PTR_DIFF(pdata,(*ppdata));
3813 int i;
3814 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3816 for (i=0; i<100; i++)
3817 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3818 DEBUG(4,("\n"));
3821 break;
3823 case SMB_QUERY_FILE_UNIX_INFO2:
3825 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3826 data_size = PTR_DIFF(pdata,(*ppdata));
3829 int i;
3830 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3832 for (i=0; i<100; i++)
3833 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3834 DEBUG(4,("\n"));
3837 break;
3839 case SMB_QUERY_FILE_UNIX_LINK:
3841 pstring buffer;
3843 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3844 #ifdef S_ISLNK
3845 if(!S_ISLNK(sbuf.st_mode))
3846 return(UNIXERROR(ERRSRV,ERRbadlink));
3847 #else
3848 return(UNIXERROR(ERRDOS,ERRbadlink));
3849 #endif
3850 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3851 if (len == -1)
3852 return(UNIXERROR(ERRDOS,ERRnoaccess));
3853 buffer[len] = 0;
3854 len = srvstr_push(outbuf, pdata, buffer, max_data_bytes, STR_TERMINATE);
3855 pdata += len;
3856 data_size = PTR_DIFF(pdata,(*ppdata));
3858 break;
3861 #if defined(HAVE_POSIX_ACLS)
3862 case SMB_QUERY_POSIX_ACL:
3864 SMB_ACL_T file_acl = NULL;
3865 SMB_ACL_T def_acl = NULL;
3866 uint16 num_file_acls = 0;
3867 uint16 num_def_acls = 0;
3869 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3870 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3871 } else {
3872 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3875 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3876 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3877 fname ));
3878 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3881 if (S_ISDIR(sbuf.st_mode)) {
3882 if (fsp && fsp->is_directory) {
3883 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3884 } else {
3885 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3887 def_acl = free_empty_sys_acl(conn, def_acl);
3890 num_file_acls = count_acl_entries(conn, file_acl);
3891 num_def_acls = count_acl_entries(conn, def_acl);
3893 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3894 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3895 data_size,
3896 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3897 SMB_POSIX_ACL_HEADER_SIZE) ));
3898 if (file_acl) {
3899 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3901 if (def_acl) {
3902 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3904 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3907 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3908 SSVAL(pdata,2,num_file_acls);
3909 SSVAL(pdata,4,num_def_acls);
3910 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3911 if (file_acl) {
3912 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3914 if (def_acl) {
3915 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3917 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3919 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3920 if (file_acl) {
3921 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3923 if (def_acl) {
3924 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3926 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3929 if (file_acl) {
3930 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3932 if (def_acl) {
3933 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3935 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3936 break;
3938 #endif
3941 case SMB_QUERY_POSIX_LOCK:
3943 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3944 SMB_BIG_UINT count;
3945 SMB_BIG_UINT offset;
3946 uint32 lock_pid;
3947 enum brl_type lock_type;
3949 if (total_data != POSIX_LOCK_DATA_SIZE) {
3950 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3953 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3954 case POSIX_LOCK_TYPE_READ:
3955 lock_type = READ_LOCK;
3956 break;
3957 case POSIX_LOCK_TYPE_WRITE:
3958 lock_type = WRITE_LOCK;
3959 break;
3960 case POSIX_LOCK_TYPE_UNLOCK:
3961 default:
3962 /* There's no point in asking for an unlock... */
3963 talloc_destroy(data_ctx);
3964 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3967 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3968 #if defined(HAVE_LONGLONG)
3969 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3970 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3971 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3972 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3973 #else /* HAVE_LONGLONG */
3974 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3975 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3976 #endif /* HAVE_LONGLONG */
3978 status = query_lock(fsp,
3979 &lock_pid,
3980 &count,
3981 &offset,
3982 &lock_type,
3983 POSIX_LOCK);
3985 if (ERROR_WAS_LOCK_DENIED(status)) {
3986 /* Here we need to report who has it locked... */
3987 data_size = POSIX_LOCK_DATA_SIZE;
3989 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3990 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3991 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3992 #if defined(HAVE_LONGLONG)
3993 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3994 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3995 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3996 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3997 #else /* HAVE_LONGLONG */
3998 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3999 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4000 #endif /* HAVE_LONGLONG */
4002 } else if (NT_STATUS_IS_OK(status)) {
4003 /* For success we just return a copy of what we sent
4004 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4005 data_size = POSIX_LOCK_DATA_SIZE;
4006 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4007 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4008 } else {
4009 return ERROR_NT(status);
4011 break;
4014 default:
4015 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4018 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4020 return(-1);
4023 /****************************************************************************
4024 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4025 code.
4026 ****************************************************************************/
4028 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4030 SMB_STRUCT_STAT sbuf1, sbuf2;
4031 pstring last_component_oldname;
4032 pstring last_component_newname;
4033 NTSTATUS status = NT_STATUS_OK;
4035 ZERO_STRUCT(sbuf1);
4036 ZERO_STRUCT(sbuf2);
4038 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 return status;
4043 status = check_name(conn, oldname);
4044 if (!NT_STATUS_IS_OK(status)) {
4045 return status;
4048 /* source must already exist. */
4049 if (!VALID_STAT(sbuf1)) {
4050 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4053 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4054 if (!NT_STATUS_IS_OK(status)) {
4055 return status;
4058 status = check_name(conn, newname);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 return status;
4063 /* Disallow if newname already exists. */
4064 if (VALID_STAT(sbuf2)) {
4065 return NT_STATUS_OBJECT_NAME_COLLISION;
4068 /* No links from a directory. */
4069 if (S_ISDIR(sbuf1.st_mode)) {
4070 return NT_STATUS_FILE_IS_A_DIRECTORY;
4073 /* Ensure this is within the share. */
4074 status = reduce_name(conn, oldname);
4075 if (!NT_STATUS_IS_OK(status)) {
4076 return status;
4079 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4081 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4082 status = map_nt_error_from_unix(errno);
4083 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4084 nt_errstr(status), newname, oldname));
4087 return status;
4090 /****************************************************************************
4091 Deal with setting the time from any of the setfilepathinfo functions.
4092 ****************************************************************************/
4094 static NTSTATUS smb_set_file_time(connection_struct *conn,
4095 files_struct *fsp,
4096 const char *fname,
4097 const SMB_STRUCT_STAT *psbuf,
4098 struct timespec ts[2])
4100 uint32 action =
4101 FILE_NOTIFY_CHANGE_LAST_ACCESS
4102 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4105 if (!VALID_STAT(*psbuf)) {
4106 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4109 /* get some defaults (no modifications) if any info is zero or -1. */
4110 if (null_timespec(ts[0])) {
4111 ts[0] = get_atimespec(psbuf);
4112 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4115 if (null_timespec(ts[1])) {
4116 ts[1] = get_mtimespec(psbuf);
4117 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4120 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4121 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4124 * Try and set the times of this file if
4125 * they are different from the current values.
4129 struct timespec mts = get_mtimespec(psbuf);
4130 struct timespec ats = get_atimespec(psbuf);
4131 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4132 return NT_STATUS_OK;
4136 if(fsp != NULL) {
4138 * This was a setfileinfo on an open file.
4139 * NT does this a lot. We also need to
4140 * set the time here, as it can be read by
4141 * FindFirst/FindNext and with the patch for bug #2045
4142 * in smbd/fileio.c it ensures that this timestamp is
4143 * kept sticky even after a write. We save the request
4144 * away and will set it on file close and after a write. JRA.
4147 if (!null_timespec(ts[1])) {
4148 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4149 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4150 fsp_set_pending_modtime(fsp, ts[1]);
4154 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4156 if(file_ntimes(conn, fname, ts)!=0) {
4157 return map_nt_error_from_unix(errno);
4159 if (action != 0) {
4160 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4162 return NT_STATUS_OK;
4165 /****************************************************************************
4166 Deal with setting the dosmode from any of the setfilepathinfo functions.
4167 ****************************************************************************/
4169 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4170 const char *fname,
4171 SMB_STRUCT_STAT *psbuf,
4172 uint32 dosmode)
4174 if (!VALID_STAT(*psbuf)) {
4175 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4178 if (dosmode) {
4179 if (S_ISDIR(psbuf->st_mode)) {
4180 dosmode |= aDIR;
4181 } else {
4182 dosmode &= ~aDIR;
4186 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4188 /* check the mode isn't different, before changing it */
4189 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4191 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4192 fname, (unsigned int)dosmode ));
4194 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4195 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4196 fname, strerror(errno)));
4197 return map_nt_error_from_unix(errno);
4200 return NT_STATUS_OK;
4203 /****************************************************************************
4204 Deal with setting the size from any of the setfilepathinfo functions.
4205 ****************************************************************************/
4207 static NTSTATUS smb_set_file_size(connection_struct *conn,
4208 files_struct *fsp,
4209 const char *fname,
4210 SMB_STRUCT_STAT *psbuf,
4211 SMB_OFF_T size)
4213 NTSTATUS status = NT_STATUS_OK;
4214 files_struct *new_fsp = NULL;
4216 if (!VALID_STAT(*psbuf)) {
4217 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4220 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4222 if (size == get_file_size(*psbuf)) {
4223 return NT_STATUS_OK;
4226 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4227 fname, (double)size ));
4229 if (fsp && fsp->fh->fd != -1) {
4230 /* Handle based call. */
4231 if (vfs_set_filelen(fsp, size) == -1) {
4232 return map_nt_error_from_unix(errno);
4234 return NT_STATUS_OK;
4237 status = open_file_ntcreate(conn, fname, psbuf,
4238 FILE_WRITE_DATA,
4239 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4240 FILE_OPEN,
4242 FILE_ATTRIBUTE_NORMAL,
4243 FORCE_OPLOCK_BREAK_TO_NONE,
4244 NULL, &new_fsp);
4246 if (!NT_STATUS_IS_OK(status)) {
4247 /* NB. We check for open_was_deferred in the caller. */
4248 return status;
4251 if (vfs_set_filelen(new_fsp, size) == -1) {
4252 status = map_nt_error_from_unix(errno);
4253 close_file(new_fsp,NORMAL_CLOSE);
4254 return status;
4257 close_file(new_fsp,NORMAL_CLOSE);
4258 return NT_STATUS_OK;
4261 /****************************************************************************
4262 Deal with SMB_INFO_SET_EA.
4263 ****************************************************************************/
4265 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4266 const char *pdata,
4267 int total_data,
4268 files_struct *fsp,
4269 const char *fname)
4271 struct ea_list *ea_list = NULL;
4272 TALLOC_CTX *ctx = NULL;
4273 NTSTATUS status = NT_STATUS_OK;
4275 if (total_data < 10) {
4277 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4278 length. They seem to have no effect. Bug #3212. JRA */
4280 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4281 /* We're done. We only get EA info in this call. */
4282 return NT_STATUS_OK;
4285 return NT_STATUS_INVALID_PARAMETER;
4288 if (IVAL(pdata,0) > total_data) {
4289 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4290 IVAL(pdata,0), (unsigned int)total_data));
4291 return NT_STATUS_INVALID_PARAMETER;
4294 ctx = talloc_init("SMB_INFO_SET_EA");
4295 if (!ctx) {
4296 return NT_STATUS_NO_MEMORY;
4298 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4299 if (!ea_list) {
4300 talloc_destroy(ctx);
4301 return NT_STATUS_INVALID_PARAMETER;
4303 status = set_ea(conn, fsp, fname, ea_list);
4304 talloc_destroy(ctx);
4306 return status;
4309 /****************************************************************************
4310 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4311 ****************************************************************************/
4313 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4314 const char *pdata,
4315 int total_data,
4316 files_struct *fsp,
4317 const char *fname,
4318 SMB_STRUCT_STAT *psbuf)
4320 NTSTATUS status = NT_STATUS_OK;
4321 BOOL delete_on_close;
4322 uint32 dosmode = 0;
4324 if (total_data < 1) {
4325 return NT_STATUS_INVALID_PARAMETER;
4328 if (fsp == NULL) {
4329 return NT_STATUS_INVALID_HANDLE;
4332 delete_on_close = (CVAL(pdata,0) ? True : False);
4333 dosmode = dos_mode(conn, fname, psbuf);
4335 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4336 "delete_on_close = %u\n",
4337 fsp->fsp_name,
4338 (unsigned int)dosmode,
4339 (unsigned int)delete_on_close ));
4341 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 return status;
4347 /* The set is across all open files on this dev/inode pair. */
4348 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4349 return NT_STATUS_ACCESS_DENIED;
4351 return NT_STATUS_OK;
4354 /****************************************************************************
4355 Deal with SMB_FILE_POSITION_INFORMATION.
4356 ****************************************************************************/
4358 static NTSTATUS smb_file_position_information(connection_struct *conn,
4359 const char *pdata,
4360 int total_data,
4361 files_struct *fsp)
4363 SMB_BIG_UINT position_information;
4365 if (total_data < 8) {
4366 return NT_STATUS_INVALID_PARAMETER;
4369 if (fsp == NULL) {
4370 /* Ignore on pathname based set. */
4371 return NT_STATUS_OK;
4374 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4375 #ifdef LARGE_SMB_OFF_T
4376 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4377 #else /* LARGE_SMB_OFF_T */
4378 if (IVAL(pdata,4) != 0) {
4379 /* more than 32 bits? */
4380 return NT_STATUS_INVALID_PARAMETER;
4382 #endif /* LARGE_SMB_OFF_T */
4384 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4385 fsp->fsp_name, (double)position_information ));
4386 fsp->fh->position_information = position_information;
4387 return NT_STATUS_OK;
4390 /****************************************************************************
4391 Deal with SMB_FILE_MODE_INFORMATION.
4392 ****************************************************************************/
4394 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4395 const char *pdata,
4396 int total_data)
4398 uint32 mode;
4400 if (total_data < 4) {
4401 return NT_STATUS_INVALID_PARAMETER;
4403 mode = IVAL(pdata,0);
4404 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4405 return NT_STATUS_INVALID_PARAMETER;
4407 return NT_STATUS_OK;
4410 /****************************************************************************
4411 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4412 ****************************************************************************/
4414 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4415 char *inbuf,
4416 const char *pdata,
4417 int total_data,
4418 const char *fname)
4420 pstring link_target;
4421 const char *newname = fname;
4422 NTSTATUS status = NT_STATUS_OK;
4424 /* Set a symbolic link. */
4425 /* Don't allow this if follow links is false. */
4427 if (total_data == 0) {
4428 return NT_STATUS_INVALID_PARAMETER;
4431 if (!lp_symlinks(SNUM(conn))) {
4432 return NT_STATUS_ACCESS_DENIED;
4435 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4437 /* !widelinks forces the target path to be within the share. */
4438 /* This means we can interpret the target as a pathname. */
4439 if (!lp_widelinks(SNUM(conn))) {
4440 pstring rel_name;
4441 char *last_dirp = NULL;
4443 if (*link_target == '/') {
4444 /* No absolute paths allowed. */
4445 return NT_STATUS_ACCESS_DENIED;
4447 pstrcpy(rel_name, newname);
4448 last_dirp = strrchr_m(rel_name, '/');
4449 if (last_dirp) {
4450 last_dirp[1] = '\0';
4451 } else {
4452 pstrcpy(rel_name, "./");
4454 pstrcat(rel_name, link_target);
4456 status = check_name(conn, rel_name);
4457 if (!NT_STATUS_IS_OK(status)) {
4458 return status;
4462 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4463 newname, link_target ));
4465 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4466 return map_nt_error_from_unix(errno);
4469 return NT_STATUS_OK;
4472 /****************************************************************************
4473 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4474 ****************************************************************************/
4476 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4477 char *inbuf,
4478 char *outbuf,
4479 const char *pdata,
4480 int total_data,
4481 pstring fname)
4483 pstring oldname;
4484 NTSTATUS status = NT_STATUS_OK;
4486 /* Set a hard link. */
4487 if (total_data == 0) {
4488 return NT_STATUS_INVALID_PARAMETER;
4491 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4492 if (!NT_STATUS_IS_OK(status)) {
4493 return status;
4496 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4497 if (!NT_STATUS_IS_OK(status)) {
4498 return status;
4501 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4502 fname, oldname));
4504 return hardlink_internals(conn, oldname, fname);
4507 /****************************************************************************
4508 Deal with SMB_FILE_RENAME_INFORMATION.
4509 ****************************************************************************/
4511 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4512 char *inbuf,
4513 char *outbuf,
4514 const char *pdata,
4515 int total_data,
4516 files_struct *fsp,
4517 pstring fname)
4519 BOOL overwrite;
4520 /* uint32 root_fid; */ /* Not used */
4521 uint32 len;
4522 pstring newname;
4523 pstring base_name;
4524 BOOL dest_has_wcard = False;
4525 NTSTATUS status = NT_STATUS_OK;
4526 char *p;
4528 if (total_data < 13) {
4529 return NT_STATUS_INVALID_PARAMETER;
4532 overwrite = (CVAL(pdata,0) ? True : False);
4533 /* root_fid = IVAL(pdata,4); */
4534 len = IVAL(pdata,8);
4536 if (len > (total_data - 12) || (len == 0)) {
4537 return NT_STATUS_INVALID_PARAMETER;
4540 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4541 if (!NT_STATUS_IS_OK(status)) {
4542 return status;
4545 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 return status;
4550 /* Check the new name has no '/' characters. */
4551 if (strchr_m(newname, '/')) {
4552 return NT_STATUS_NOT_SUPPORTED;
4555 /* Create the base directory. */
4556 pstrcpy(base_name, fname);
4557 p = strrchr_m(base_name, '/');
4558 if (p) {
4559 p[1] = '\0';
4560 } else {
4561 pstrcpy(base_name, "./");
4563 /* Append the new name. */
4564 pstrcat(base_name, newname);
4566 if (fsp) {
4567 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4568 fsp->fnum, fsp->fsp_name, base_name ));
4569 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4570 } else {
4571 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4572 fname, newname ));
4573 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4576 return status;
4579 /****************************************************************************
4580 Deal with SMB_SET_POSIX_ACL.
4581 ****************************************************************************/
4583 #if defined(HAVE_POSIX_ACLS)
4584 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4585 const char *pdata,
4586 int total_data,
4587 files_struct *fsp,
4588 const char *fname,
4589 SMB_STRUCT_STAT *psbuf)
4591 uint16 posix_acl_version;
4592 uint16 num_file_acls;
4593 uint16 num_def_acls;
4594 BOOL valid_file_acls = True;
4595 BOOL valid_def_acls = True;
4597 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4598 return NT_STATUS_INVALID_PARAMETER;
4600 posix_acl_version = SVAL(pdata,0);
4601 num_file_acls = SVAL(pdata,2);
4602 num_def_acls = SVAL(pdata,4);
4604 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4605 valid_file_acls = False;
4606 num_file_acls = 0;
4609 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4610 valid_def_acls = False;
4611 num_def_acls = 0;
4614 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4615 return NT_STATUS_INVALID_PARAMETER;
4618 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4619 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4620 return NT_STATUS_INVALID_PARAMETER;
4623 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4624 fname ? fname : fsp->fsp_name,
4625 (unsigned int)num_file_acls,
4626 (unsigned int)num_def_acls));
4628 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4629 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4630 return map_nt_error_from_unix(errno);
4633 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4634 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4635 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4636 return map_nt_error_from_unix(errno);
4638 return NT_STATUS_OK;
4640 #endif
4642 /****************************************************************************
4643 Deal with SMB_SET_POSIX_LOCK.
4644 ****************************************************************************/
4646 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4647 char *inbuf,
4648 int length,
4649 const char *pdata,
4650 int total_data,
4651 files_struct *fsp)
4653 SMB_BIG_UINT count;
4654 SMB_BIG_UINT offset;
4655 uint32 lock_pid;
4656 BOOL blocking_lock = False;
4657 enum brl_type lock_type;
4658 NTSTATUS status = NT_STATUS_OK;
4660 if (fsp == NULL || fsp->fh->fd == -1) {
4661 return NT_STATUS_INVALID_HANDLE;
4664 if (total_data != POSIX_LOCK_DATA_SIZE) {
4665 return NT_STATUS_INVALID_PARAMETER;
4668 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4669 case POSIX_LOCK_TYPE_READ:
4670 lock_type = READ_LOCK;
4671 break;
4672 case POSIX_LOCK_TYPE_WRITE:
4673 /* Return the right POSIX-mappable error code for files opened read-only. */
4674 if (!fsp->can_write) {
4675 return NT_STATUS_INVALID_HANDLE;
4677 lock_type = WRITE_LOCK;
4678 break;
4679 case POSIX_LOCK_TYPE_UNLOCK:
4680 lock_type = UNLOCK_LOCK;
4681 break;
4682 default:
4683 return NT_STATUS_INVALID_PARAMETER;
4686 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4687 blocking_lock = False;
4688 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4689 blocking_lock = True;
4690 } else {
4691 return NT_STATUS_INVALID_PARAMETER;
4694 if (!lp_blocking_locks(SNUM(conn))) {
4695 blocking_lock = False;
4698 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4699 #if defined(HAVE_LONGLONG)
4700 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4701 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4702 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4703 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4704 #else /* HAVE_LONGLONG */
4705 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4706 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4707 #endif /* HAVE_LONGLONG */
4709 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4710 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4711 fsp->fsp_name,
4712 (unsigned int)lock_type,
4713 (unsigned int)lock_pid,
4714 (double)count,
4715 (double)offset ));
4717 if (lock_type == UNLOCK_LOCK) {
4718 status = do_unlock(fsp,
4719 lock_pid,
4720 count,
4721 offset,
4722 POSIX_LOCK);
4723 } else {
4724 uint32 block_smbpid;
4726 struct byte_range_lock *br_lck = do_lock(fsp,
4727 lock_pid,
4728 count,
4729 offset,
4730 lock_type,
4731 POSIX_LOCK,
4732 blocking_lock,
4733 &status,
4734 &block_smbpid);
4736 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4738 * A blocking lock was requested. Package up
4739 * this smb into a queued request and push it
4740 * onto the blocking lock queue.
4742 if(push_blocking_lock_request(br_lck,
4743 inbuf, length,
4744 fsp,
4745 -1, /* infinite timeout. */
4747 lock_pid,
4748 lock_type,
4749 POSIX_LOCK,
4750 offset,
4751 count,
4752 block_smbpid)) {
4753 TALLOC_FREE(br_lck);
4754 return status;
4757 TALLOC_FREE(br_lck);
4760 return status;
4763 /****************************************************************************
4764 Deal with SMB_INFO_STANDARD.
4765 ****************************************************************************/
4767 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4768 const char *pdata,
4769 int total_data,
4770 files_struct *fsp,
4771 const char *fname,
4772 const SMB_STRUCT_STAT *psbuf)
4774 struct timespec ts[2];
4776 if (total_data < 12) {
4777 return NT_STATUS_INVALID_PARAMETER;
4780 /* access time */
4781 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4782 /* write time */
4783 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4785 DEBUG(10,("smb_set_info_standard: file %s\n",
4786 fname ? fname : fsp->fsp_name ));
4788 return smb_set_file_time(conn,
4789 fsp,
4790 fname,
4791 psbuf,
4792 ts);
4795 /****************************************************************************
4796 Deal with SMB_SET_FILE_BASIC_INFO.
4797 ****************************************************************************/
4799 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4800 const char *pdata,
4801 int total_data,
4802 files_struct *fsp,
4803 const char *fname,
4804 SMB_STRUCT_STAT *psbuf)
4806 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4807 struct timespec write_time;
4808 struct timespec changed_time;
4809 uint32 dosmode = 0;
4810 struct timespec ts[2];
4811 NTSTATUS status = NT_STATUS_OK;
4813 if (total_data < 36) {
4814 return NT_STATUS_INVALID_PARAMETER;
4817 /* Set the attributes */
4818 dosmode = IVAL(pdata,32);
4819 status = smb_set_file_dosmode(conn,
4820 fname,
4821 psbuf,
4822 dosmode);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 return status;
4827 /* Ignore create time at offset pdata. */
4829 /* access time */
4830 ts[0] = interpret_long_date(pdata+8);
4832 write_time = interpret_long_date(pdata+16);
4833 changed_time = interpret_long_date(pdata+24);
4835 /* mtime */
4836 ts[1] = timespec_min(&write_time, &changed_time);
4838 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4839 ts[1] = write_time;
4842 /* Prefer a defined time to an undefined one. */
4843 if (null_timespec(ts[1])) {
4844 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4847 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4848 fname ? fname : fsp->fsp_name ));
4850 return smb_set_file_time(conn,
4851 fsp,
4852 fname,
4853 psbuf,
4854 ts);
4857 /****************************************************************************
4858 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4859 ****************************************************************************/
4861 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4862 const char *pdata,
4863 int total_data,
4864 files_struct *fsp,
4865 const char *fname,
4866 SMB_STRUCT_STAT *psbuf)
4868 SMB_BIG_UINT allocation_size = 0;
4869 NTSTATUS status = NT_STATUS_OK;
4870 files_struct *new_fsp = NULL;
4872 if (!VALID_STAT(*psbuf)) {
4873 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4876 if (total_data < 8) {
4877 return NT_STATUS_INVALID_PARAMETER;
4880 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4881 #ifdef LARGE_SMB_OFF_T
4882 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4883 #else /* LARGE_SMB_OFF_T */
4884 if (IVAL(pdata,4) != 0) {
4885 /* more than 32 bits? */
4886 return NT_STATUS_INVALID_PARAMETER;
4888 #endif /* LARGE_SMB_OFF_T */
4890 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4891 fname, (double)allocation_size ));
4893 if (allocation_size) {
4894 allocation_size = smb_roundup(conn, allocation_size);
4897 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4898 fname, (double)allocation_size ));
4900 if (fsp && fsp->fh->fd != -1) {
4901 /* Open file handle. */
4902 /* Only change if needed. */
4903 if (allocation_size != get_file_size(*psbuf)) {
4904 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4905 return map_nt_error_from_unix(errno);
4908 /* But always update the time. */
4909 if (null_timespec(fsp->pending_modtime)) {
4911 * This is equivalent to a write. Ensure it's seen immediately
4912 * if there are no pending writes.
4914 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
4916 return NT_STATUS_OK;
4919 /* Pathname or stat or directory file. */
4921 status = open_file_ntcreate(conn, fname, psbuf,
4922 FILE_WRITE_DATA,
4923 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4924 FILE_OPEN,
4926 FILE_ATTRIBUTE_NORMAL,
4927 FORCE_OPLOCK_BREAK_TO_NONE,
4928 NULL, &new_fsp);
4930 if (!NT_STATUS_IS_OK(status)) {
4931 /* NB. We check for open_was_deferred in the caller. */
4932 return status;
4935 /* Only change if needed. */
4936 if (allocation_size != get_file_size(*psbuf)) {
4937 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4938 status = map_nt_error_from_unix(errno);
4939 close_file(new_fsp,NORMAL_CLOSE);
4940 return status;
4944 /* Changing the allocation size should set the last mod time. */
4945 /* Don't need to call set_filetime as this will be flushed on
4946 * close. */
4948 fsp_set_pending_modtime(new_fsp, timespec_current());
4950 close_file(new_fsp,NORMAL_CLOSE);
4951 return NT_STATUS_OK;
4954 /****************************************************************************
4955 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4956 ****************************************************************************/
4958 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4959 const char *pdata,
4960 int total_data,
4961 files_struct *fsp,
4962 const char *fname,
4963 SMB_STRUCT_STAT *psbuf)
4965 SMB_OFF_T size;
4967 if (total_data < 8) {
4968 return NT_STATUS_INVALID_PARAMETER;
4971 size = IVAL(pdata,0);
4972 #ifdef LARGE_SMB_OFF_T
4973 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4974 #else /* LARGE_SMB_OFF_T */
4975 if (IVAL(pdata,4) != 0) {
4976 /* more than 32 bits? */
4977 return NT_STATUS_INVALID_PARAMETER;
4979 #endif /* LARGE_SMB_OFF_T */
4980 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4981 "file %s to %.0f\n", fname, (double)size ));
4983 return smb_set_file_size(conn,
4984 fsp,
4985 fname,
4986 psbuf,
4987 size);
4990 /****************************************************************************
4991 Allow a UNIX info mknod.
4992 ****************************************************************************/
4994 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4995 const char *pdata,
4996 int total_data,
4997 const char *fname,
4998 SMB_STRUCT_STAT *psbuf)
5000 uint32 file_type = IVAL(pdata,56);
5001 #if defined(HAVE_MAKEDEV)
5002 uint32 dev_major = IVAL(pdata,60);
5003 uint32 dev_minor = IVAL(pdata,68);
5004 #endif
5005 SMB_DEV_T dev = (SMB_DEV_T)0;
5006 uint32 raw_unixmode = IVAL(pdata,84);
5007 NTSTATUS status;
5008 mode_t unixmode;
5010 if (total_data < 100) {
5011 return NT_STATUS_INVALID_PARAMETER;
5014 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 return status;
5019 #if defined(HAVE_MAKEDEV)
5020 dev = makedev(dev_major, dev_minor);
5021 #endif
5023 switch (file_type) {
5024 #if defined(S_IFIFO)
5025 case UNIX_TYPE_FIFO:
5026 unixmode |= S_IFIFO;
5027 break;
5028 #endif
5029 #if defined(S_IFSOCK)
5030 case UNIX_TYPE_SOCKET:
5031 unixmode |= S_IFSOCK;
5032 break;
5033 #endif
5034 #if defined(S_IFCHR)
5035 case UNIX_TYPE_CHARDEV:
5036 unixmode |= S_IFCHR;
5037 break;
5038 #endif
5039 #if defined(S_IFBLK)
5040 case UNIX_TYPE_BLKDEV:
5041 unixmode |= S_IFBLK;
5042 break;
5043 #endif
5044 default:
5045 return NT_STATUS_INVALID_PARAMETER;
5048 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5049 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5051 /* Ok - do the mknod. */
5052 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5053 return map_nt_error_from_unix(errno);
5056 /* If any of the other "set" calls fail we
5057 * don't want to end up with a half-constructed mknod.
5060 if (lp_inherit_perms(SNUM(conn))) {
5061 inherit_access_acl(
5062 conn, parent_dirname(fname),
5063 fname, unixmode);
5066 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5067 status = map_nt_error_from_unix(errno);
5068 SMB_VFS_UNLINK(conn,fname);
5069 return status;
5071 return NT_STATUS_OK;
5074 /****************************************************************************
5075 Deal with SMB_SET_FILE_UNIX_BASIC.
5076 ****************************************************************************/
5078 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5079 const char *pdata,
5080 int total_data,
5081 files_struct *fsp,
5082 const char *fname,
5083 SMB_STRUCT_STAT *psbuf)
5085 struct timespec ts[2];
5086 uint32 raw_unixmode;
5087 mode_t unixmode;
5088 SMB_OFF_T size = 0;
5089 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5090 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5091 NTSTATUS status = NT_STATUS_OK;
5092 BOOL delete_on_fail = False;
5093 enum perm_type ptype;
5095 if (total_data < 100) {
5096 return NT_STATUS_INVALID_PARAMETER;
5099 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5100 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5101 size=IVAL(pdata,0); /* first 8 Bytes are size */
5102 #ifdef LARGE_SMB_OFF_T
5103 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5104 #else /* LARGE_SMB_OFF_T */
5105 if (IVAL(pdata,4) != 0) {
5106 /* more than 32 bits? */
5107 return NT_STATUS_INVALID_PARAMETER;
5109 #endif /* LARGE_SMB_OFF_T */
5112 ts[0] = interpret_long_date(pdata+24); /* access_time */
5113 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5114 set_owner = (uid_t)IVAL(pdata,40);
5115 set_grp = (gid_t)IVAL(pdata,48);
5116 raw_unixmode = IVAL(pdata,84);
5118 if (VALID_STAT(*psbuf)) {
5119 if (S_ISDIR(psbuf->st_mode)) {
5120 ptype = PERM_EXISTING_DIR;
5121 } else {
5122 ptype = PERM_EXISTING_FILE;
5124 } else {
5125 ptype = PERM_NEW_FILE;
5128 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5129 if (!NT_STATUS_IS_OK(status)) {
5130 return status;
5133 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5134 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5135 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5137 if (!VALID_STAT(*psbuf)) {
5139 * The only valid use of this is to create character and block
5140 * devices, and named pipes. This is deprecated (IMHO) and
5141 * a new info level should be used for mknod. JRA.
5144 status = smb_unix_mknod(conn,
5145 pdata,
5146 total_data,
5147 fname,
5148 psbuf);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 return status;
5153 /* Ensure we don't try and change anything else. */
5154 raw_unixmode = SMB_MODE_NO_CHANGE;
5155 size = get_file_size(*psbuf);
5156 ts[0] = get_atimespec(psbuf);
5157 ts[1] = get_mtimespec(psbuf);
5159 * We continue here as we might want to change the
5160 * owner uid/gid.
5162 delete_on_fail = True;
5165 #if 1
5166 /* Horrible backwards compatibility hack as an old server bug
5167 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5168 * */
5170 if (!size) {
5171 size = get_file_size(*psbuf);
5173 #endif
5176 * Deal with the UNIX specific mode set.
5179 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5180 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5181 (unsigned int)unixmode, fname ));
5182 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5183 return map_nt_error_from_unix(errno);
5188 * Deal with the UNIX specific uid set.
5191 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5192 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5193 (unsigned int)set_owner, fname ));
5194 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5195 status = map_nt_error_from_unix(errno);
5196 if (delete_on_fail) {
5197 SMB_VFS_UNLINK(conn,fname);
5199 return status;
5204 * Deal with the UNIX specific gid set.
5207 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5208 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5209 (unsigned int)set_owner, fname ));
5210 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5211 status = map_nt_error_from_unix(errno);
5212 if (delete_on_fail) {
5213 SMB_VFS_UNLINK(conn,fname);
5215 return status;
5219 /* Deal with any size changes. */
5221 status = smb_set_file_size(conn,
5222 fsp,
5223 fname,
5224 psbuf,
5225 size);
5226 if (!NT_STATUS_IS_OK(status)) {
5227 return status;
5230 /* Deal with any time changes. */
5232 return smb_set_file_time(conn,
5233 fsp,
5234 fname,
5235 psbuf,
5236 ts);
5239 /****************************************************************************
5240 Deal with SMB_SET_FILE_UNIX_INFO2.
5241 ****************************************************************************/
5243 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5244 const char *pdata,
5245 int total_data,
5246 files_struct *fsp,
5247 const char *fname,
5248 SMB_STRUCT_STAT *psbuf)
5250 NTSTATUS status;
5251 uint32 smb_fflags;
5252 uint32 smb_fmask;
5254 if (total_data < 116) {
5255 return NT_STATUS_INVALID_PARAMETER;
5258 /* Start by setting all the fields that are common between UNIX_BASIC
5259 * and UNIX_INFO2.
5261 status = smb_set_file_unix_basic(conn, pdata, total_data,
5262 fsp, fname, psbuf);
5263 if (!NT_STATUS_IS_OK(status)) {
5264 return status;
5267 smb_fflags = IVAL(pdata, 108);
5268 smb_fmask = IVAL(pdata, 112);
5270 /* NB: We should only attempt to alter the file flags if the client
5271 * sends a non-zero mask.
5273 if (smb_fmask != 0) {
5274 int stat_fflags = 0;
5276 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5277 &stat_fflags)) {
5278 /* Client asked to alter a flag we don't understand. */
5279 return NT_STATUS_INVALID_PARAMETER;
5282 if (fsp && fsp->fh->fd != -1) {
5283 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5284 return NT_STATUS_NOT_SUPPORTED;
5285 } else {
5286 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5287 return map_nt_error_from_unix(errno);
5292 /* XXX: need to add support for changing the create_time here. You
5293 * can do this for paths on Darwin with setattrlist(2). The right way
5294 * to hook this up is probably by extending the VFS utimes interface.
5297 return NT_STATUS_OK;
5300 /****************************************************************************
5301 Create a directory with POSIX semantics.
5302 ****************************************************************************/
5304 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5305 char **ppdata,
5306 int total_data,
5307 const char *fname,
5308 SMB_STRUCT_STAT *psbuf,
5309 int *pdata_return_size)
5311 NTSTATUS status = NT_STATUS_OK;
5312 uint32 raw_unixmode = 0;
5313 uint32 mod_unixmode = 0;
5314 mode_t unixmode = (mode_t)0;
5315 files_struct *fsp = NULL;
5316 uint16 info_level_return = 0;
5317 int info;
5318 char *pdata = *ppdata;
5320 if (total_data < 18) {
5321 return NT_STATUS_INVALID_PARAMETER;
5324 raw_unixmode = IVAL(pdata,8);
5325 /* Next 4 bytes are not yet defined. */
5327 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 return status;
5332 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5334 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5335 fname, (unsigned int)unixmode ));
5337 status = open_directory(conn,
5338 fname,
5339 psbuf,
5340 FILE_READ_ATTRIBUTES, /* Just a stat open */
5341 FILE_SHARE_NONE, /* Ignored for stat opens */
5342 FILE_CREATE,
5344 mod_unixmode,
5345 &info,
5346 &fsp);
5348 if (NT_STATUS_IS_OK(status)) {
5349 close_file(fsp, NORMAL_CLOSE);
5352 info_level_return = SVAL(pdata,16);
5354 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5355 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5356 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5357 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5358 } else {
5359 *pdata_return_size = 12;
5362 /* Realloc the data size */
5363 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5364 if (*ppdata == NULL) {
5365 *pdata_return_size = 0;
5366 return NT_STATUS_NO_MEMORY;
5368 pdata = *ppdata;
5370 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5371 SSVAL(pdata,2,0); /* No fnum. */
5372 SIVAL(pdata,4,info); /* Was directory created. */
5374 switch (info_level_return) {
5375 case SMB_QUERY_FILE_UNIX_BASIC:
5376 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5377 SSVAL(pdata,10,0); /* Padding. */
5378 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5379 break;
5380 case SMB_QUERY_FILE_UNIX_INFO2:
5381 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5382 SSVAL(pdata,10,0); /* Padding. */
5383 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5384 break;
5385 default:
5386 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5387 SSVAL(pdata,10,0); /* Padding. */
5388 break;
5391 return status;
5394 /****************************************************************************
5395 Open/Create a file with POSIX semantics.
5396 ****************************************************************************/
5398 static NTSTATUS smb_posix_open(connection_struct *conn,
5399 char **ppdata,
5400 int total_data,
5401 const char *fname,
5402 SMB_STRUCT_STAT *psbuf,
5403 int *pdata_return_size)
5405 BOOL extended_oplock_granted = False;
5406 char *pdata = *ppdata;
5407 uint32 flags = 0;
5408 uint32 wire_open_mode = 0;
5409 uint32 raw_unixmode = 0;
5410 uint32 mod_unixmode = 0;
5411 uint32 create_disp = 0;
5412 uint32 access_mask = 0;
5413 uint32 create_options = 0;
5414 NTSTATUS status = NT_STATUS_OK;
5415 mode_t unixmode = (mode_t)0;
5416 files_struct *fsp = NULL;
5417 int oplock_request = 0;
5418 int info = 0;
5419 uint16 info_level_return = 0;
5421 if (total_data < 18) {
5422 return NT_STATUS_INVALID_PARAMETER;
5425 flags = IVAL(pdata,0);
5426 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5427 if (oplock_request) {
5428 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5431 wire_open_mode = IVAL(pdata,4);
5433 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5434 return smb_posix_mkdir(conn,
5435 ppdata,
5436 total_data,
5437 fname,
5438 psbuf,
5439 pdata_return_size);
5442 switch (wire_open_mode & SMB_ACCMODE) {
5443 case SMB_O_RDONLY:
5444 access_mask = FILE_READ_DATA;
5445 break;
5446 case SMB_O_WRONLY:
5447 access_mask = FILE_WRITE_DATA;
5448 break;
5449 case SMB_O_RDWR:
5450 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5451 break;
5452 default:
5453 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5454 (unsigned int)wire_open_mode ));
5455 return NT_STATUS_INVALID_PARAMETER;
5458 wire_open_mode &= ~SMB_ACCMODE;
5460 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5461 create_disp = FILE_CREATE;
5462 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5463 create_disp = FILE_OVERWRITE_IF;
5464 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5465 create_disp = FILE_OPEN_IF;
5466 } else {
5467 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5468 (unsigned int)wire_open_mode ));
5469 return NT_STATUS_INVALID_PARAMETER;
5472 raw_unixmode = IVAL(pdata,8);
5473 /* Next 4 bytes are not yet defined. */
5475 status = unix_perms_from_wire(conn,
5476 psbuf,
5477 raw_unixmode,
5478 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5479 &unixmode);
5481 if (!NT_STATUS_IS_OK(status)) {
5482 return status;
5485 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5487 if (wire_open_mode & SMB_O_SYNC) {
5488 create_options |= FILE_WRITE_THROUGH;
5490 if (wire_open_mode & SMB_O_APPEND) {
5491 access_mask |= FILE_APPEND_DATA;
5493 if (wire_open_mode & SMB_O_DIRECT) {
5494 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5497 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5498 fname,
5499 (unsigned int)wire_open_mode,
5500 (unsigned int)unixmode ));
5502 status = open_file_ntcreate(conn,
5503 fname,
5504 psbuf,
5505 access_mask,
5506 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5507 create_disp,
5508 0, /* no create options yet. */
5509 mod_unixmode,
5510 oplock_request,
5511 &info,
5512 &fsp);
5514 if (!NT_STATUS_IS_OK(status)) {
5515 return status;
5518 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5519 extended_oplock_granted = True;
5522 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5523 extended_oplock_granted = True;
5526 info_level_return = SVAL(pdata,16);
5528 /* Allocate the correct return size. */
5530 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5531 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5532 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5533 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5534 } else {
5535 *pdata_return_size = 12;
5538 /* Realloc the data size */
5539 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5540 if (*ppdata == NULL) {
5541 close_file(fsp,ERROR_CLOSE);
5542 *pdata_return_size = 0;
5543 return NT_STATUS_NO_MEMORY;
5545 pdata = *ppdata;
5547 if (extended_oplock_granted) {
5548 if (flags & REQUEST_BATCH_OPLOCK) {
5549 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5550 } else {
5551 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5553 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5554 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5555 } else {
5556 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5559 SSVAL(pdata,2,fsp->fnum);
5560 SIVAL(pdata,4,info); /* Was file created etc. */
5562 switch (info_level_return) {
5563 case SMB_QUERY_FILE_UNIX_BASIC:
5564 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5565 SSVAL(pdata,10,0); /* padding. */
5566 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5567 break;
5568 case SMB_QUERY_FILE_UNIX_INFO2:
5569 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5570 SSVAL(pdata,10,0); /* padding. */
5571 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5572 break;
5573 default:
5574 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5575 SSVAL(pdata,10,0); /* padding. */
5576 break;
5578 return NT_STATUS_OK;
5581 /****************************************************************************
5582 Delete a file with POSIX semantics.
5583 ****************************************************************************/
5585 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5586 const char *pdata,
5587 int total_data,
5588 const char *fname,
5589 SMB_STRUCT_STAT *psbuf)
5591 NTSTATUS status = NT_STATUS_OK;
5592 files_struct *fsp = NULL;
5593 uint16 flags = 0;
5594 char del = 1;
5595 int info = 0;
5596 int i;
5597 struct share_mode_lock *lck = NULL;
5599 if (total_data < 2) {
5600 return NT_STATUS_INVALID_PARAMETER;
5603 flags = SVAL(pdata,0);
5605 if (!VALID_STAT(*psbuf)) {
5606 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5609 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5610 !VALID_STAT_OF_DIR(*psbuf)) {
5611 return NT_STATUS_NOT_A_DIRECTORY;
5614 DEBUG(10,("smb_posix_unlink: %s %s\n",
5615 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5616 fname));
5618 if (VALID_STAT_OF_DIR(*psbuf)) {
5619 status = open_directory(conn,
5620 fname,
5621 psbuf,
5622 DELETE_ACCESS,
5623 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5624 FILE_OPEN,
5626 FILE_FLAG_POSIX_SEMANTICS|0777,
5627 &info,
5628 &fsp);
5629 } else {
5631 status = open_file_ntcreate(conn,
5632 fname,
5633 psbuf,
5634 DELETE_ACCESS,
5635 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5636 FILE_OPEN,
5638 FILE_FLAG_POSIX_SEMANTICS|0777,
5639 0, /* No oplock, but break existing ones. */
5640 &info,
5641 &fsp);
5644 if (!NT_STATUS_IS_OK(status)) {
5645 return status;
5649 * Don't lie to client. If we can't really delete due to
5650 * non-POSIX opens return SHARING_VIOLATION.
5653 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
5654 if (lck == NULL) {
5655 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5656 "lock for file %s\n", fsp->fsp_name));
5657 close_file(fsp, NORMAL_CLOSE);
5658 return NT_STATUS_INVALID_PARAMETER;
5662 * See if others still have the file open. If this is the case, then
5663 * don't delete. If all opens are POSIX delete we can set the delete
5664 * on close disposition.
5666 for (i=0; i<lck->num_share_modes; i++) {
5667 struct share_mode_entry *e = &lck->share_modes[i];
5668 if (is_valid_share_mode_entry(e)) {
5669 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5670 continue;
5672 /* Fail with sharing violation. */
5673 close_file(fsp, NORMAL_CLOSE);
5674 TALLOC_FREE(lck);
5675 return NT_STATUS_SHARING_VIOLATION;
5680 * Set the delete on close.
5682 status = smb_set_file_disposition_info(conn,
5683 &del,
5685 fsp,
5686 fname,
5687 psbuf);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 close_file(fsp, NORMAL_CLOSE);
5691 TALLOC_FREE(lck);
5692 return status;
5694 TALLOC_FREE(lck);
5695 return close_file(fsp, NORMAL_CLOSE);
5698 /****************************************************************************
5699 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5700 ****************************************************************************/
5702 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5703 unsigned int tran_call,
5704 char **pparams, int total_params, char **ppdata, int total_data,
5705 unsigned int max_data_bytes)
5707 char *params = *pparams;
5708 char *pdata = *ppdata;
5709 uint16 info_level;
5710 SMB_STRUCT_STAT sbuf;
5711 pstring fname;
5712 files_struct *fsp = NULL;
5713 NTSTATUS status = NT_STATUS_OK;
5714 int data_return_size = 0;
5716 if (!params) {
5717 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5720 ZERO_STRUCT(sbuf);
5722 if (tran_call == TRANSACT2_SETFILEINFO) {
5723 if (total_params < 4) {
5724 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5727 fsp = file_fsp(params,0);
5728 info_level = SVAL(params,2);
5730 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5732 * This is actually a SETFILEINFO on a directory
5733 * handle (returned from an NT SMB). NT5.0 seems
5734 * to do this call. JRA.
5736 pstrcpy(fname, fsp->fsp_name);
5737 if (INFO_LEVEL_IS_UNIX(info_level)) {
5738 /* Always do lstat for UNIX calls. */
5739 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5740 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5741 return UNIXERROR(ERRDOS,ERRbadpath);
5743 } else {
5744 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5745 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5746 return UNIXERROR(ERRDOS,ERRbadpath);
5749 } else if (fsp && fsp->print_file) {
5751 * Doing a DELETE_ON_CLOSE should cancel a print job.
5753 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5754 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5756 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5758 SSVAL(params,0,0);
5759 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5760 return(-1);
5761 } else
5762 return (UNIXERROR(ERRDOS,ERRbadpath));
5763 } else {
5765 * Original code - this is an open file.
5767 CHECK_FSP(fsp,conn);
5769 pstrcpy(fname, fsp->fsp_name);
5771 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5772 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5773 return(UNIXERROR(ERRDOS,ERRbadfid));
5776 } else {
5777 /* set path info */
5778 if (total_params < 7) {
5779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5782 info_level = SVAL(params,0);
5783 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5784 if (!NT_STATUS_IS_OK(status)) {
5785 return ERROR_NT(status);
5788 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5789 if (!NT_STATUS_IS_OK(status)) {
5790 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5791 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5793 return ERROR_NT(status);
5796 status = unix_convert(conn, fname, False, NULL, &sbuf);
5797 if (!NT_STATUS_IS_OK(status)) {
5798 return ERROR_NT(status);
5801 status = check_name(conn, fname);
5802 if (!NT_STATUS_IS_OK(status)) {
5803 return ERROR_NT(status);
5806 if (INFO_LEVEL_IS_UNIX(info_level)) {
5808 * For CIFS UNIX extensions the target name may not exist.
5811 /* Always do lstat for UNIX calls. */
5812 SMB_VFS_LSTAT(conn,fname,&sbuf);
5814 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5815 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5816 return UNIXERROR(ERRDOS,ERRbadpath);
5820 if (!CAN_WRITE(conn)) {
5821 return ERROR_DOS(ERRSRV,ERRaccess);
5824 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5825 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5828 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5829 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5831 /* Realloc the parameter size */
5832 *pparams = (char *)SMB_REALLOC(*pparams,2);
5833 if (*pparams == NULL) {
5834 return ERROR_NT(NT_STATUS_NO_MEMORY);
5836 params = *pparams;
5838 SSVAL(params,0,0);
5840 if (fsp && !null_timespec(fsp->pending_modtime)) {
5841 /* the pending modtime overrides the current modtime */
5842 set_mtimespec(&sbuf, fsp->pending_modtime);
5845 switch (info_level) {
5847 case SMB_INFO_STANDARD:
5849 status = smb_set_info_standard(conn,
5850 pdata,
5851 total_data,
5852 fsp,
5853 fname,
5854 &sbuf);
5855 break;
5858 case SMB_INFO_SET_EA:
5860 status = smb_info_set_ea(conn,
5861 pdata,
5862 total_data,
5863 fsp,
5864 fname);
5865 break;
5868 case SMB_SET_FILE_BASIC_INFO:
5869 case SMB_FILE_BASIC_INFORMATION:
5871 status = smb_set_file_basic_info(conn,
5872 pdata,
5873 total_data,
5874 fsp,
5875 fname,
5876 &sbuf);
5877 break;
5880 case SMB_FILE_ALLOCATION_INFORMATION:
5881 case SMB_SET_FILE_ALLOCATION_INFO:
5883 status = smb_set_file_allocation_info(conn,
5884 pdata,
5885 total_data,
5886 fsp,
5887 fname,
5888 &sbuf);
5889 break;
5892 case SMB_FILE_END_OF_FILE_INFORMATION:
5893 case SMB_SET_FILE_END_OF_FILE_INFO:
5895 status = smb_set_file_end_of_file_info(conn,
5896 pdata,
5897 total_data,
5898 fsp,
5899 fname,
5900 &sbuf);
5901 break;
5904 case SMB_FILE_DISPOSITION_INFORMATION:
5905 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5907 #if 0
5908 /* JRA - We used to just ignore this on a path ?
5909 * Shouldn't this be invalid level on a pathname
5910 * based call ?
5912 if (tran_call != TRANSACT2_SETFILEINFO) {
5913 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5915 #endif
5916 status = smb_set_file_disposition_info(conn,
5917 pdata,
5918 total_data,
5919 fsp,
5920 fname,
5921 &sbuf);
5922 break;
5925 case SMB_FILE_POSITION_INFORMATION:
5927 status = smb_file_position_information(conn,
5928 pdata,
5929 total_data,
5930 fsp);
5931 break;
5934 /* From tridge Samba4 :
5935 * MODE_INFORMATION in setfileinfo (I have no
5936 * idea what "mode information" on a file is - it takes a value of 0,
5937 * 2, 4 or 6. What could it be?).
5940 case SMB_FILE_MODE_INFORMATION:
5942 status = smb_file_mode_information(conn,
5943 pdata,
5944 total_data);
5945 break;
5949 * CIFS UNIX extensions.
5952 case SMB_SET_FILE_UNIX_BASIC:
5954 status = smb_set_file_unix_basic(conn,
5955 pdata,
5956 total_data,
5957 fsp,
5958 fname,
5959 &sbuf);
5960 break;
5963 case SMB_SET_FILE_UNIX_INFO2:
5965 status = smb_set_file_unix_info2(conn,
5966 pdata,
5967 total_data,
5968 fsp,
5969 fname,
5970 &sbuf);
5971 break;
5974 case SMB_SET_FILE_UNIX_LINK:
5976 if (tran_call != TRANSACT2_SETPATHINFO) {
5977 /* We must have a pathname for this. */
5978 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5980 status = smb_set_file_unix_link(conn,
5981 inbuf,
5982 pdata,
5983 total_data,
5984 fname);
5985 break;
5988 case SMB_SET_FILE_UNIX_HLINK:
5990 if (tran_call != TRANSACT2_SETPATHINFO) {
5991 /* We must have a pathname for this. */
5992 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5994 status = smb_set_file_unix_hlink(conn,
5995 inbuf,
5996 outbuf,
5997 pdata,
5998 total_data,
5999 fname);
6000 break;
6003 case SMB_FILE_RENAME_INFORMATION:
6005 status = smb_file_rename_information(conn,
6006 inbuf,
6007 outbuf,
6008 pdata,
6009 total_data,
6010 fsp,
6011 fname);
6012 break;
6015 #if defined(HAVE_POSIX_ACLS)
6016 case SMB_SET_POSIX_ACL:
6018 status = smb_set_posix_acl(conn,
6019 pdata,
6020 total_data,
6021 fsp,
6022 fname,
6023 &sbuf);
6024 break;
6026 #endif
6028 case SMB_SET_POSIX_LOCK:
6030 if (tran_call != TRANSACT2_SETFILEINFO) {
6031 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6033 status = smb_set_posix_lock(conn,
6034 inbuf,
6035 length,
6036 pdata,
6037 total_data,
6038 fsp);
6039 break;
6042 case SMB_POSIX_PATH_OPEN:
6044 if (tran_call != TRANSACT2_SETPATHINFO) {
6045 /* We must have a pathname for this. */
6046 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6049 status = smb_posix_open(conn,
6050 ppdata,
6051 total_data,
6052 fname,
6053 &sbuf,
6054 &data_return_size);
6055 break;
6058 case SMB_POSIX_PATH_UNLINK:
6060 if (tran_call != TRANSACT2_SETPATHINFO) {
6061 /* We must have a pathname for this. */
6062 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6065 status = smb_posix_unlink(conn,
6066 pdata,
6067 total_data,
6068 fname,
6069 &sbuf);
6070 break;
6073 default:
6074 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6078 if (!NT_STATUS_IS_OK(status)) {
6079 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6080 /* We have re-scheduled this call. */
6081 return -1;
6083 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6084 /* We have re-scheduled this call. */
6085 return -1;
6087 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6088 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6090 if (info_level == SMB_POSIX_PATH_OPEN) {
6091 return ERROR_OPEN(status);
6093 return ERROR_NT(status);
6096 SSVAL(params,0,0);
6097 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6099 return -1;
6102 /****************************************************************************
6103 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6104 ****************************************************************************/
6106 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6107 char **pparams, int total_params, char **ppdata, int total_data,
6108 unsigned int max_data_bytes)
6110 char *params = *pparams;
6111 char *pdata = *ppdata;
6112 pstring directory;
6113 SMB_STRUCT_STAT sbuf;
6114 NTSTATUS status = NT_STATUS_OK;
6115 struct ea_list *ea_list = NULL;
6117 if (!CAN_WRITE(conn))
6118 return ERROR_DOS(ERRSRV,ERRaccess);
6120 if (total_params < 5) {
6121 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6124 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 return ERROR_NT(status);
6129 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6131 status = unix_convert(conn, directory, False, NULL, &sbuf);
6132 if (!NT_STATUS_IS_OK(status)) {
6133 return ERROR_NT(status);
6136 status = check_name(conn, directory);
6137 if (!NT_STATUS_IS_OK(status)) {
6138 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6139 return ERROR_NT(status);
6142 /* Any data in this call is an EA list. */
6143 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6144 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6148 * OS/2 workplace shell seems to send SET_EA requests of "null"
6149 * length (4 bytes containing IVAL 4).
6150 * They seem to have no effect. Bug #3212. JRA.
6153 if (total_data != 4) {
6154 if (total_data < 10) {
6155 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6158 if (IVAL(pdata,0) > total_data) {
6159 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6160 IVAL(pdata,0), (unsigned int)total_data));
6161 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6164 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6165 total_data - 4);
6166 if (!ea_list) {
6167 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6170 /* If total_data == 4 Windows doesn't care what values
6171 * are placed in that field, it just ignores them.
6172 * The System i QNTC IBM SMB client puts bad values here,
6173 * so ignore them. */
6175 status = create_directory(conn, directory);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 return ERROR_NT(status);
6181 /* Try and set any given EA. */
6182 if (ea_list) {
6183 status = set_ea(conn, NULL, directory, ea_list);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 return ERROR_NT(status);
6189 /* Realloc the parameter and data sizes */
6190 *pparams = (char *)SMB_REALLOC(*pparams,2);
6191 if(*pparams == NULL) {
6192 return ERROR_NT(NT_STATUS_NO_MEMORY);
6194 params = *pparams;
6196 SSVAL(params,0,0);
6198 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6200 return(-1);
6203 /****************************************************************************
6204 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6205 We don't actually do this - we just send a null response.
6206 ****************************************************************************/
6208 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6209 char **pparams, int total_params, char **ppdata, int total_data,
6210 unsigned int max_data_bytes)
6212 static uint16 fnf_handle = 257;
6213 char *params = *pparams;
6214 uint16 info_level;
6216 if (total_params < 6) {
6217 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6220 info_level = SVAL(params,4);
6221 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6223 switch (info_level) {
6224 case 1:
6225 case 2:
6226 break;
6227 default:
6228 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6231 /* Realloc the parameter and data sizes */
6232 *pparams = (char *)SMB_REALLOC(*pparams,6);
6233 if (*pparams == NULL) {
6234 return ERROR_NT(NT_STATUS_NO_MEMORY);
6236 params = *pparams;
6238 SSVAL(params,0,fnf_handle);
6239 SSVAL(params,2,0); /* No changes */
6240 SSVAL(params,4,0); /* No EA errors */
6242 fnf_handle++;
6244 if(fnf_handle == 0)
6245 fnf_handle = 257;
6247 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6249 return(-1);
6252 /****************************************************************************
6253 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6254 changes). Currently this does nothing.
6255 ****************************************************************************/
6257 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6258 char **pparams, int total_params, char **ppdata, int total_data,
6259 unsigned int max_data_bytes)
6261 char *params = *pparams;
6263 DEBUG(3,("call_trans2findnotifynext\n"));
6265 /* Realloc the parameter and data sizes */
6266 *pparams = (char *)SMB_REALLOC(*pparams,4);
6267 if (*pparams == NULL) {
6268 return ERROR_NT(NT_STATUS_NO_MEMORY);
6270 params = *pparams;
6272 SSVAL(params,0,0); /* No changes */
6273 SSVAL(params,2,0); /* No EA errors */
6275 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6277 return(-1);
6280 /****************************************************************************
6281 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6282 ****************************************************************************/
6284 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6285 char **pparams, int total_params, char **ppdata, int total_data,
6286 unsigned int max_data_bytes)
6288 char *params = *pparams;
6289 pstring pathname;
6290 int reply_size = 0;
6291 int max_referral_level;
6292 NTSTATUS status = NT_STATUS_OK;
6294 DEBUG(10,("call_trans2getdfsreferral\n"));
6296 if (total_params < 3) {
6297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6300 max_referral_level = SVAL(params,0);
6302 if(!lp_host_msdfs())
6303 return ERROR_DOS(ERRDOS,ERRbadfunc);
6305 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6306 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6307 return ERROR_NT(status);
6309 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6310 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6312 return(-1);
6315 #define LMCAT_SPL 0x53
6316 #define LMFUNC_GETJOBID 0x60
6318 /****************************************************************************
6319 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6320 ****************************************************************************/
6322 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6323 char **pparams, int total_params, char **ppdata, int total_data,
6324 unsigned int max_data_bytes)
6326 char *pdata = *ppdata;
6327 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6329 /* check for an invalid fid before proceeding */
6331 if (!fsp)
6332 return(ERROR_DOS(ERRDOS,ERRbadfid));
6334 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6335 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6336 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6337 if (*ppdata == NULL) {
6338 return ERROR_NT(NT_STATUS_NO_MEMORY);
6340 pdata = *ppdata;
6342 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6343 CAN ACCEPT THIS IN UNICODE. JRA. */
6345 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6346 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6347 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6348 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6349 return(-1);
6350 } else {
6351 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6352 return ERROR_DOS(ERRSRV,ERRerror);
6356 /****************************************************************************
6357 Reply to a SMBfindclose (stop trans2 directory search).
6358 ****************************************************************************/
6360 int reply_findclose(connection_struct *conn,
6361 char *inbuf,char *outbuf,int length,int bufsize)
6363 int outsize = 0;
6364 int dptr_num=SVALS(inbuf,smb_vwv0);
6365 START_PROFILE(SMBfindclose);
6367 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6369 dptr_close(&dptr_num);
6371 outsize = set_message(outbuf,0,0,False);
6373 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6375 END_PROFILE(SMBfindclose);
6376 return(outsize);
6379 /****************************************************************************
6380 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6381 ****************************************************************************/
6383 int reply_findnclose(connection_struct *conn,
6384 char *inbuf,char *outbuf,int length,int bufsize)
6386 int outsize = 0;
6387 int dptr_num= -1;
6388 START_PROFILE(SMBfindnclose);
6390 dptr_num = SVAL(inbuf,smb_vwv0);
6392 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6394 /* We never give out valid handles for a
6395 findnotifyfirst - so any dptr_num is ok here.
6396 Just ignore it. */
6398 outsize = set_message(outbuf,0,0,False);
6400 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6402 END_PROFILE(SMBfindnclose);
6403 return(outsize);
6406 int handle_trans2(connection_struct *conn,
6407 struct trans_state *state,
6408 char *inbuf, char *outbuf, int size, int bufsize)
6410 int outsize;
6412 if (Protocol >= PROTOCOL_NT1) {
6413 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6416 /* Now we must call the relevant TRANS2 function */
6417 switch(state->call) {
6418 case TRANSACT2_OPEN:
6420 START_PROFILE(Trans2_open);
6421 outsize = call_trans2open(
6422 conn, inbuf, outbuf, bufsize,
6423 &state->param, state->total_param,
6424 &state->data, state->total_data,
6425 state->max_data_return);
6426 END_PROFILE(Trans2_open);
6427 break;
6430 case TRANSACT2_FINDFIRST:
6432 START_PROFILE(Trans2_findfirst);
6433 outsize = call_trans2findfirst(
6434 conn, inbuf, outbuf, bufsize,
6435 &state->param, state->total_param,
6436 &state->data, state->total_data,
6437 state->max_data_return);
6438 END_PROFILE(Trans2_findfirst);
6439 break;
6442 case TRANSACT2_FINDNEXT:
6444 START_PROFILE(Trans2_findnext);
6445 outsize = call_trans2findnext(
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_findnext);
6451 break;
6454 case TRANSACT2_QFSINFO:
6456 START_PROFILE(Trans2_qfsinfo);
6457 outsize = call_trans2qfsinfo(
6458 conn, inbuf, outbuf, size, bufsize,
6459 &state->param, state->total_param,
6460 &state->data, state->total_data,
6461 state->max_data_return);
6462 END_PROFILE(Trans2_qfsinfo);
6463 break;
6466 case TRANSACT2_SETFSINFO:
6468 START_PROFILE(Trans2_setfsinfo);
6469 outsize = call_trans2setfsinfo(
6470 conn, inbuf, outbuf, size, bufsize,
6471 &state->param, state->total_param,
6472 &state->data, state->total_data,
6473 state->max_data_return);
6474 END_PROFILE(Trans2_setfsinfo);
6475 break;
6478 case TRANSACT2_QPATHINFO:
6479 case TRANSACT2_QFILEINFO:
6481 START_PROFILE(Trans2_qpathinfo);
6482 outsize = call_trans2qfilepathinfo(
6483 conn, inbuf, outbuf, size, bufsize, state->call,
6484 &state->param, state->total_param,
6485 &state->data, state->total_data,
6486 state->max_data_return);
6487 END_PROFILE(Trans2_qpathinfo);
6488 break;
6491 case TRANSACT2_SETPATHINFO:
6492 case TRANSACT2_SETFILEINFO:
6494 START_PROFILE(Trans2_setpathinfo);
6495 outsize = call_trans2setfilepathinfo(
6496 conn, inbuf, outbuf, size, bufsize, state->call,
6497 &state->param, state->total_param,
6498 &state->data, state->total_data,
6499 state->max_data_return);
6500 END_PROFILE(Trans2_setpathinfo);
6501 break;
6504 case TRANSACT2_FINDNOTIFYFIRST:
6506 START_PROFILE(Trans2_findnotifyfirst);
6507 outsize = call_trans2findnotifyfirst(
6508 conn, inbuf, outbuf, size, bufsize,
6509 &state->param, state->total_param,
6510 &state->data, state->total_data,
6511 state->max_data_return);
6512 END_PROFILE(Trans2_findnotifyfirst);
6513 break;
6516 case TRANSACT2_FINDNOTIFYNEXT:
6518 START_PROFILE(Trans2_findnotifynext);
6519 outsize = call_trans2findnotifynext(
6520 conn, inbuf, outbuf, size, bufsize,
6521 &state->param, state->total_param,
6522 &state->data, state->total_data,
6523 state->max_data_return);
6524 END_PROFILE(Trans2_findnotifynext);
6525 break;
6528 case TRANSACT2_MKDIR:
6530 START_PROFILE(Trans2_mkdir);
6531 outsize = call_trans2mkdir(
6532 conn, inbuf, outbuf, size, bufsize,
6533 &state->param, state->total_param,
6534 &state->data, state->total_data,
6535 state->max_data_return);
6536 END_PROFILE(Trans2_mkdir);
6537 break;
6540 case TRANSACT2_GET_DFS_REFERRAL:
6542 START_PROFILE(Trans2_get_dfs_referral);
6543 outsize = call_trans2getdfsreferral(
6544 conn, inbuf, outbuf, size, bufsize,
6545 &state->param, state->total_param,
6546 &state->data, state->total_data,
6547 state->max_data_return);
6548 END_PROFILE(Trans2_get_dfs_referral);
6549 break;
6552 case TRANSACT2_IOCTL:
6554 START_PROFILE(Trans2_ioctl);
6555 outsize = call_trans2ioctl(
6556 conn, inbuf, outbuf, size, bufsize,
6557 &state->param, state->total_param,
6558 &state->data, state->total_data,
6559 state->max_data_return);
6560 END_PROFILE(Trans2_ioctl);
6561 break;
6564 default:
6565 /* Error in request */
6566 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6567 outsize = ERROR_DOS(ERRSRV,ERRerror);
6570 return outsize;
6573 /****************************************************************************
6574 Reply to a SMBtrans2.
6575 ****************************************************************************/
6577 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6578 int size, int bufsize)
6580 int outsize = 0;
6581 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6582 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6583 unsigned int psoff = SVAL(inbuf, smb_psoff);
6584 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6585 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6586 unsigned int av_size = size-4;
6587 struct trans_state *state;
6588 NTSTATUS result;
6590 START_PROFILE(SMBtrans2);
6592 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6593 if (!NT_STATUS_IS_OK(result)) {
6594 DEBUG(2, ("Got invalid trans2 request: %s\n",
6595 nt_errstr(result)));
6596 END_PROFILE(SMBtrans2);
6597 return ERROR_NT(result);
6600 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6601 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6602 END_PROFILE(SMBtrans2);
6603 return ERROR_DOS(ERRSRV,ERRaccess);
6606 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6607 DEBUG(0, ("talloc failed\n"));
6608 END_PROFILE(SMBtrans2);
6609 return ERROR_NT(NT_STATUS_NO_MEMORY);
6612 state->cmd = SMBtrans2;
6614 state->mid = SVAL(inbuf, smb_mid);
6615 state->vuid = SVAL(inbuf, smb_uid);
6616 state->setup_count = SVAL(inbuf, smb_suwcnt);
6617 state->setup = NULL;
6618 state->total_param = SVAL(inbuf, smb_tpscnt);
6619 state->param = NULL;
6620 state->total_data = SVAL(inbuf, smb_tdscnt);
6621 state->data = NULL;
6622 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6623 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6624 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6625 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6626 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6628 state->call = tran_call;
6630 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6631 is so as a sanity check */
6632 if (state->setup_count != 1) {
6634 * Need to have rc=0 for ioctl to get job id for OS/2.
6635 * Network printing will fail if function is not successful.
6636 * Similar function in reply.c will be used if protocol
6637 * is LANMAN1.0 instead of LM1.2X002.
6638 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6639 * outbuf doesn't have to be set(only job id is used).
6641 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6642 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6643 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6644 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6645 } else {
6646 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6647 DEBUG(2,("Transaction is %d\n",tran_call));
6648 TALLOC_FREE(state);
6649 END_PROFILE(SMBtrans2);
6650 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6654 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6655 goto bad_param;
6657 if (state->total_data) {
6658 /* Can't use talloc here, the core routines do realloc on the
6659 * params and data. */
6660 state->data = (char *)SMB_MALLOC(state->total_data);
6661 if (state->data == NULL) {
6662 DEBUG(0,("reply_trans2: data malloc fail for %u "
6663 "bytes !\n", (unsigned int)state->total_data));
6664 TALLOC_FREE(state);
6665 END_PROFILE(SMBtrans2);
6666 return(ERROR_DOS(ERRDOS,ERRnomem));
6669 if (dscnt > state->total_data ||
6670 dsoff+dscnt < dsoff) {
6671 goto bad_param;
6674 if (dsoff > av_size ||
6675 dscnt > av_size ||
6676 dsoff+dscnt > av_size) {
6677 goto bad_param;
6680 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6683 if (state->total_param) {
6684 /* Can't use talloc here, the core routines do realloc on the
6685 * params and data. */
6686 state->param = (char *)SMB_MALLOC(state->total_param);
6687 if (state->param == NULL) {
6688 DEBUG(0,("reply_trans: param malloc fail for %u "
6689 "bytes !\n", (unsigned int)state->total_param));
6690 SAFE_FREE(state->data);
6691 TALLOC_FREE(state);
6692 END_PROFILE(SMBtrans2);
6693 return(ERROR_DOS(ERRDOS,ERRnomem));
6696 if (pscnt > state->total_param ||
6697 psoff+pscnt < psoff) {
6698 goto bad_param;
6701 if (psoff > av_size ||
6702 pscnt > av_size ||
6703 psoff+pscnt > av_size) {
6704 goto bad_param;
6707 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6710 state->received_data = dscnt;
6711 state->received_param = pscnt;
6713 if ((state->received_param == state->total_param) &&
6714 (state->received_data == state->total_data)) {
6716 outsize = handle_trans2(conn, state, inbuf, outbuf,
6717 size, bufsize);
6718 SAFE_FREE(state->data);
6719 SAFE_FREE(state->param);
6720 TALLOC_FREE(state);
6721 END_PROFILE(SMBtrans2);
6722 return outsize;
6725 DLIST_ADD(conn->pending_trans, state);
6727 /* We need to send an interim response then receive the rest
6728 of the parameter/data bytes */
6729 outsize = set_message(outbuf,0,0,False);
6730 show_msg(outbuf);
6731 END_PROFILE(SMBtrans2);
6732 return outsize;
6734 bad_param:
6736 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6737 SAFE_FREE(state->data);
6738 SAFE_FREE(state->param);
6739 TALLOC_FREE(state);
6740 END_PROFILE(SMBtrans2);
6741 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6745 /****************************************************************************
6746 Reply to a SMBtranss2
6747 ****************************************************************************/
6749 int reply_transs2(connection_struct *conn,
6750 char *inbuf,char *outbuf,int size,int bufsize)
6752 int outsize = 0;
6753 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6754 unsigned int av_size = size-4;
6755 struct trans_state *state;
6757 START_PROFILE(SMBtranss2);
6759 show_msg(inbuf);
6761 for (state = conn->pending_trans; state != NULL;
6762 state = state->next) {
6763 if (state->mid == SVAL(inbuf,smb_mid)) {
6764 break;
6768 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6769 END_PROFILE(SMBtranss2);
6770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6773 /* Revise state->total_param and state->total_data in case they have
6774 changed downwards */
6776 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6777 state->total_param = SVAL(inbuf, smb_tpscnt);
6778 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6779 state->total_data = SVAL(inbuf, smb_tdscnt);
6781 pcnt = SVAL(inbuf, smb_spscnt);
6782 poff = SVAL(inbuf, smb_spsoff);
6783 pdisp = SVAL(inbuf, smb_spsdisp);
6785 dcnt = SVAL(inbuf, smb_sdscnt);
6786 doff = SVAL(inbuf, smb_sdsoff);
6787 ddisp = SVAL(inbuf, smb_sdsdisp);
6789 state->received_param += pcnt;
6790 state->received_data += dcnt;
6792 if ((state->received_data > state->total_data) ||
6793 (state->received_param > state->total_param))
6794 goto bad_param;
6796 if (pcnt) {
6797 if (pdisp > state->total_param ||
6798 pcnt > state->total_param ||
6799 pdisp+pcnt > state->total_param ||
6800 pdisp+pcnt < pdisp) {
6801 goto bad_param;
6804 if (poff > av_size ||
6805 pcnt > av_size ||
6806 poff+pcnt > av_size ||
6807 poff+pcnt < poff) {
6808 goto bad_param;
6811 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6812 pcnt);
6815 if (dcnt) {
6816 if (ddisp > state->total_data ||
6817 dcnt > state->total_data ||
6818 ddisp+dcnt > state->total_data ||
6819 ddisp+dcnt < ddisp) {
6820 goto bad_param;
6823 if (doff > av_size ||
6824 dcnt > av_size ||
6825 doff+dcnt > av_size ||
6826 doff+dcnt < doff) {
6827 goto bad_param;
6830 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6831 dcnt);
6834 if ((state->received_param < state->total_param) ||
6835 (state->received_data < state->total_data)) {
6836 END_PROFILE(SMBtranss2);
6837 return -1;
6840 /* construct_reply_common has done us the favor to pre-fill the
6841 * command field with SMBtranss2 which is wrong :-)
6843 SCVAL(outbuf,smb_com,SMBtrans2);
6845 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6847 DLIST_REMOVE(conn->pending_trans, state);
6848 SAFE_FREE(state->data);
6849 SAFE_FREE(state->param);
6850 TALLOC_FREE(state);
6852 if (outsize == 0) {
6853 END_PROFILE(SMBtranss2);
6854 return(ERROR_DOS(ERRSRV,ERRnosupport));
6857 END_PROFILE(SMBtranss2);
6858 return(outsize);
6860 bad_param:
6862 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6863 DLIST_REMOVE(conn->pending_trans, state);
6864 SAFE_FREE(state->data);
6865 SAFE_FREE(state->param);
6866 TALLOC_FREE(state);
6867 END_PROFILE(SMBtranss2);
6868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);