r21972: - add string_term_tdb_data() it creates a null-terminates tdb key from a...
[Samba/nascimento.git] / source3 / smbd / trans2.c
blob007ad50b10f947d2344855e59c74e420f05024dc
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "includes.h"
29 extern int max_send;
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
62 return val;
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
67 account sparse files.
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 SMB_BIG_UINT ret;
74 if(S_ISDIR(sbuf->st_mode)) {
75 return 0;
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 #else
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 #endif
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
97 NULL
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
106 int i;
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 return True;
112 return False;
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
124 char *val = NULL;
125 ssize_t sizeret;
127 again:
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
130 if (!val) {
131 return False;
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 } else {
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
141 attr_size = 65536;
142 goto again;
145 if (sizeret == -1) {
146 return False;
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, val, sizeret);
152 pea->flags = 0;
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
155 } else {
156 pea->name = ea_name;
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
160 return True;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
172 char *ea_namelist;
173 char *p;
174 ssize_t sizeret;
175 int i;
176 struct ea_list *ea_list_head = NULL;
178 *pea_total_len = 0;
180 if (!lp_ea_support(SNUM(conn))) {
181 return NULL;
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
187 if (!ea_namelist) {
188 return NULL;
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 } else {
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
199 } else {
200 break;
204 if (sizeret == -1)
205 return NULL;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 if (sizeret) {
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 continue;
216 listp = TALLOC_P(mem_ctx, struct ea_list);
217 if (!listp)
218 return NULL;
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
221 return NULL;
225 fstring dos_ea_name;
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
236 *pea_total_len += 4;
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
241 return ea_list_head;
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 that was filled.
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
253 char *p = pdata;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
258 SIVAL(pdata,4,0);
259 return 4;
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 size_t dos_namelen;
264 fstring dos_ea_name;
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
268 break;
270 if (ea_list->ea.value.length > 65535) {
271 break;
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274 break;
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
300 return 0;
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
305 return total_ea_len;
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 size_t total_ea_len;
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
323 break;
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
340 int ret;
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 } else {
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 #ifdef ENOATTR
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
370 unix_ea_name));
371 ret = 0;
373 #endif
374 } else {
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 } else {
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (ret == -1) {
389 #ifdef ENOTSUP
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
393 #endif
394 return map_nt_error_from_unix(errno);
398 return NT_STATUS_OK;
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
407 size_t offset = 0;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
419 break;
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
423 return NULL;
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
426 if (!eal->ea.name) {
427 return NULL;
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
435 return ea_list_head;
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 uint16 val_len;
446 unsigned int namelen;
448 if (!eal) {
449 return NULL;
452 if (data_size < 6) {
453 return NULL;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
461 return NULL;
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
466 return NULL;
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
469 if (!eal->ea.name) {
470 return NULL;
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
475 return NULL;
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
485 if (pbytes_used) {
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
492 return eal;
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
502 size_t offset = 0;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
508 if (!eal) {
509 return NULL;
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
516 return ea_list_head;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
525 fstring dos_ea_name;
526 struct ea_list *listp;
527 size_t ret = 0;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
534 if (ret) {
535 ret += 4;
538 return ret;
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
554 break;
558 if (flistp) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
562 } else {
563 /* Null entry. */
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
570 return name_list;
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(char *outbuf,
581 int bufsize,
582 const char *params,
583 int paramsize,
584 const char *pdata,
585 int datasize,
586 int max_data_bytes)
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
596 int useable_space;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
610 for OS/2. */
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
622 show_msg(outbuf);
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
625 return 0;
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
685 else
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
693 } else {
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
717 show_msg(outbuf);
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
727 /* Sanity check */
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
731 return -1;
735 return 0;
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
748 int deny_mode;
749 int32 open_attr;
750 BOOL oplock_request;
751 #if 0
752 BOOL return_additional_info;
753 int16 open_sattr;
754 time_t open_time;
755 #endif
756 int open_ofun;
757 uint32 open_size;
758 char *pname;
759 pstring fname;
760 SMB_OFF_T size=0;
761 int fattr=0,mtime=0;
762 SMB_INO_T inode = 0;
763 SMB_STRUCT_STAT sbuf;
764 int smb_action = 0;
765 files_struct *fsp;
766 struct ea_list *ea_list = NULL;
767 uint16 flags = 0;
768 NTSTATUS status;
769 uint32 access_mask;
770 uint32 share_mode;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
790 #if 0
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
794 #endif
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
797 pname = &params[28];
799 if (IS_IPC(conn)) {
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
829 &access_mask,
830 &share_mode,
831 &create_disposition,
832 &create_options)) {
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
853 total_data - 4);
854 if (!ea_list) {
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
862 access_mask,
863 share_mode,
864 create_disposition,
865 create_options,
866 open_attr,
867 oplock_request,
868 &smb_action, &fsp);
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
873 return -1;
875 return ERROR_NT(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
881 inode = sbuf.st_ino;
882 if (fattr & aDIR) {
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
906 } else {
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
924 params = *pparams;
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
945 if (flags & 8) {
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
948 } else {
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
955 return -1;
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
968 return False;
969 if (conn->case_sensitive)
970 return strcmp(str,mask)==0;
971 if (StrCaseCmp(str,mask) != 0) {
972 return False;
974 if (dptr_has_wild(conn->dirptr)) {
975 return False;
977 return True;
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32 unix_filetype(mode_t mode)
986 if(S_ISREG(mode))
987 return UNIX_TYPE_FILE;
988 else if(S_ISDIR(mode))
989 return UNIX_TYPE_DIR;
990 #ifdef S_ISLNK
991 else if(S_ISLNK(mode))
992 return UNIX_TYPE_SYMLINK;
993 #endif
994 #ifdef S_ISCHR
995 else if(S_ISCHR(mode))
996 return UNIX_TYPE_CHARDEV;
997 #endif
998 #ifdef S_ISBLK
999 else if(S_ISBLK(mode))
1000 return UNIX_TYPE_BLKDEV;
1001 #endif
1002 #ifdef S_ISFIFO
1003 else if(S_ISFIFO(mode))
1004 return UNIX_TYPE_FIFO;
1005 #endif
1006 #ifdef S_ISSOCK
1007 else if(S_ISSOCK(mode))
1008 return UNIX_TYPE_SOCKET;
1009 #endif
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012 return UNIX_TYPE_UNKNOWN;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022 SMB_STRUCT_STAT *psbuf,
1023 uint32 perms,
1024 enum perm_type ptype,
1025 mode_t *ret_perms)
1027 mode_t ret = 0;
1029 if (perms == SMB_MODE_NO_CHANGE) {
1030 if (!VALID_STAT(*psbuf)) {
1031 return NT_STATUS_INVALID_PARAMETER;
1032 } else {
1033 *ret_perms = psbuf->st_mode;
1034 return NT_STATUS_OK;
1038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1047 #ifdef S_ISVTX
1048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1049 #endif
1050 #ifdef S_ISGID
1051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1052 #endif
1053 #ifdef S_ISUID
1054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1055 #endif
1057 switch (ptype) {
1058 case PERM_NEW_FILE:
1059 /* Apply mode mask */
1060 ret &= lp_create_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_create_mode(SNUM(conn));
1063 break;
1064 case PERM_NEW_DIR:
1065 ret &= lp_dir_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_dir_mode(SNUM(conn));
1068 break;
1069 case PERM_EXISTING_FILE:
1070 /* Apply mode mask */
1071 ret &= lp_security_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_security_mode(SNUM(conn));
1074 break;
1075 case PERM_EXISTING_DIR:
1076 /* Apply mode mask */
1077 ret &= lp_dir_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_dir_security_mode(SNUM(conn));
1080 break;
1083 *ret_perms = ret;
1084 return NT_STATUS_OK;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092 void *inbuf, char *outbuf,
1093 char *path_mask,uint32 dirtype,int info_level,
1094 int requires_resume_key,
1095 BOOL dont_descend,char **ppdata,
1096 char *base_data, int space_remaining,
1097 BOOL *out_of_space, BOOL *got_exact_match,
1098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1100 const char *dname;
1101 BOOL found = False;
1102 SMB_STRUCT_STAT sbuf;
1103 pstring mask;
1104 pstring pathreal;
1105 pstring fname;
1106 char *p, *q, *pdata = *ppdata;
1107 uint32 reskey=0;
1108 long prev_dirpos=0;
1109 uint32 mode=0;
1110 SMB_OFF_T file_size = 0;
1111 SMB_BIG_UINT allocation_size = 0;
1112 uint32 len;
1113 struct timespec mdate_ts, adate_ts, create_date_ts;
1114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1115 char *nameptr;
1116 char *last_entry_ptr;
1117 BOOL was_8_3;
1118 uint32 nt_extmode; /* Used for NT connections instead of mode */
1119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120 BOOL check_mangled_names = lp_manglednames(conn->params);
1122 *fname = 0;
1123 *out_of_space = False;
1124 *got_exact_match = False;
1126 ZERO_STRUCT(mdate_ts);
1127 ZERO_STRUCT(adate_ts);
1128 ZERO_STRUCT(create_date_ts);
1130 if (!conn->dirptr)
1131 return(False);
1133 p = strrchr_m(path_mask,'/');
1134 if(p != NULL) {
1135 if(p[1] == '\0')
1136 pstrcpy(mask,"*.*");
1137 else
1138 pstrcpy(mask, p+1);
1139 } else
1140 pstrcpy(mask, path_mask);
1143 while (!found) {
1144 BOOL got_match;
1145 BOOL ms_dfs_link = False;
1147 /* Needed if we run out of space */
1148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1155 * JRA.
1158 reskey = 0;
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn->dirptr,curr_dirpos));
1163 if (!dname)
1164 return(False);
1166 pstrcpy(fname,dname);
1168 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1169 got_match = mask_match(fname, mask, conn->case_sensitive);
1171 if(!got_match && check_mangled_names &&
1172 !mangle_is_8_3(fname, False, conn->params)) {
1175 * It turns out that NT matches wildcards against
1176 * both long *and* short names. This may explain some
1177 * of the wildcard wierdness from old DOS clients
1178 * that some people have been seeing.... JRA.
1181 pstring newname;
1182 pstrcpy( newname, fname);
1183 mangle_map( newname, True, False, conn->params);
1184 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1185 got_match = mask_match(newname, mask, conn->case_sensitive);
1188 if(got_match) {
1189 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1190 if (dont_descend && !isdots)
1191 continue;
1193 pstrcpy(pathreal,conn->dirpath);
1194 if(needslash)
1195 pstrcat(pathreal,"/");
1196 pstrcat(pathreal,dname);
1198 if (INFO_LEVEL_IS_UNIX(info_level)) {
1199 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201 pathreal,strerror(errno)));
1202 continue;
1204 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1205 pstring link_target;
1207 /* Needed to show the msdfs symlinks as
1208 * directories */
1210 if(lp_host_msdfs() &&
1211 lp_msdfs_root(SNUM(conn)) &&
1212 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1214 "as a directory\n",
1215 pathreal));
1216 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1218 } else {
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1221 pathreal,strerror(errno)));
1222 continue;
1226 if (ms_dfs_link) {
1227 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1228 } else {
1229 mode = dos_mode(conn,pathreal,&sbuf);
1232 if (!dir_check_ftype(conn,mode,dirtype)) {
1233 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1234 continue;
1237 if (!(mode & aDIR))
1238 file_size = get_file_size(sbuf);
1239 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1241 mdate_ts = get_mtimespec(&sbuf);
1242 adate_ts = get_atimespec(&sbuf);
1243 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1245 if (lp_dos_filetime_resolution(SNUM(conn))) {
1246 dos_filetime_timespec(&create_date_ts);
1247 dos_filetime_timespec(&mdate_ts);
1248 dos_filetime_timespec(&adate_ts);
1251 create_date = convert_timespec_to_time_t(create_date_ts);
1252 mdate = convert_timespec_to_time_t(mdate_ts);
1253 adate = convert_timespec_to_time_t(adate_ts);
1255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1257 found = True;
1259 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1263 mangle_map(fname,False,True,conn->params);
1265 p = pdata;
1266 last_entry_ptr = p;
1268 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1270 switch (info_level) {
1271 case SMB_FIND_INFO_STANDARD:
1272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1273 if(requires_resume_key) {
1274 SIVAL(p,0,reskey);
1275 p += 4;
1277 srv_put_dos_date2(p,0,create_date);
1278 srv_put_dos_date2(p,4,adate);
1279 srv_put_dos_date2(p,8,mdate);
1280 SIVAL(p,12,(uint32)file_size);
1281 SIVAL(p,16,(uint32)allocation_size);
1282 SSVAL(p,20,mode);
1283 p += 23;
1284 nameptr = p;
1285 p += align_string(outbuf, p, 0);
1286 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1288 if (len > 2) {
1289 SCVAL(nameptr, -1, len - 2);
1290 } else {
1291 SCVAL(nameptr, -1, 0);
1293 } else {
1294 if (len > 1) {
1295 SCVAL(nameptr, -1, len - 1);
1296 } else {
1297 SCVAL(nameptr, -1, 0);
1300 p += len;
1301 break;
1303 case SMB_FIND_EA_SIZE:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1305 if(requires_resume_key) {
1306 SIVAL(p,0,reskey);
1307 p += 4;
1309 srv_put_dos_date2(p,0,create_date);
1310 srv_put_dos_date2(p,4,adate);
1311 srv_put_dos_date2(p,8,mdate);
1312 SIVAL(p,12,(uint32)file_size);
1313 SIVAL(p,16,(uint32)allocation_size);
1314 SSVAL(p,20,mode);
1316 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1317 SIVAL(p,22,ea_size); /* Extended attributes */
1319 p += 27;
1320 nameptr = p - 1;
1321 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1322 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1323 if (len > 2) {
1324 len -= 2;
1325 } else {
1326 len = 0;
1328 } else {
1329 if (len > 1) {
1330 len -= 1;
1331 } else {
1332 len = 0;
1335 SCVAL(nameptr,0,len);
1336 p += len;
1337 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1338 break;
1340 case SMB_FIND_EA_LIST:
1342 struct ea_list *file_list = NULL;
1343 size_t ea_len = 0;
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1346 if (!name_list) {
1347 return False;
1349 if(requires_resume_key) {
1350 SIVAL(p,0,reskey);
1351 p += 4;
1353 srv_put_dos_date2(p,0,create_date);
1354 srv_put_dos_date2(p,4,adate);
1355 srv_put_dos_date2(p,8,mdate);
1356 SIVAL(p,12,(uint32)file_size);
1357 SIVAL(p,16,(uint32)allocation_size);
1358 SSVAL(p,20,mode);
1359 p += 22; /* p now points to the EA area. */
1361 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1362 name_list = ea_list_union(name_list, file_list, &ea_len);
1364 /* We need to determine if this entry will fit in the space available. */
1365 /* Max string size is 255 bytes. */
1366 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1367 /* Move the dirptr back to prev_dirpos */
1368 dptr_SeekDir(conn->dirptr, prev_dirpos);
1369 *out_of_space = True;
1370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1371 return False; /* Not finished - just out of space */
1374 /* Push the ea_data followed by the name. */
1375 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1376 nameptr = p;
1377 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1378 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1379 if (len > 2) {
1380 len -= 2;
1381 } else {
1382 len = 0;
1384 } else {
1385 if (len > 1) {
1386 len -= 1;
1387 } else {
1388 len = 0;
1391 SCVAL(nameptr,0,len);
1392 p += len + 1;
1393 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1394 break;
1397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1399 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1400 p += 4;
1401 SIVAL(p,0,reskey); p += 4;
1402 put_long_date_timespec(p,create_date_ts); p += 8;
1403 put_long_date_timespec(p,adate_ts); p += 8;
1404 put_long_date_timespec(p,mdate_ts); p += 8;
1405 put_long_date_timespec(p,mdate_ts); p += 8;
1406 SOFF_T(p,0,file_size); p += 8;
1407 SOFF_T(p,0,allocation_size); p += 8;
1408 SIVAL(p,0,nt_extmode); p += 4;
1409 q = p; p += 4; /* q is placeholder for name length. */
1411 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1412 SIVAL(p,0,ea_size); /* Extended attributes */
1413 p += 4;
1415 /* Clear the short name buffer. This is
1416 * IMPORTANT as not doing so will trigger
1417 * a Win2k client bug. JRA.
1419 if (!was_8_3 && check_mangled_names) {
1420 pstring mangled_name;
1421 pstrcpy(mangled_name, fname);
1422 mangle_map(mangled_name,True,True,
1423 conn->params);
1424 mangled_name[12] = 0;
1425 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1426 if (len < 24) {
1427 memset(p + 2 + len,'\0',24 - len);
1429 SSVAL(p, 0, len);
1430 } else {
1431 memset(p,'\0',26);
1433 p += 2 + 24;
1434 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1435 SIVAL(q,0,len);
1436 p += len;
1437 SIVAL(p,0,0); /* Ensure any padding is null. */
1438 len = PTR_DIFF(p, pdata);
1439 len = (len + 3) & ~3;
1440 SIVAL(pdata,0,len);
1441 p = pdata + len;
1442 break;
1444 case SMB_FIND_FILE_DIRECTORY_INFO:
1445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1446 p += 4;
1447 SIVAL(p,0,reskey); p += 4;
1448 put_long_date_timespec(p,create_date_ts); p += 8;
1449 put_long_date_timespec(p,adate_ts); p += 8;
1450 put_long_date_timespec(p,mdate_ts); p += 8;
1451 put_long_date_timespec(p,mdate_ts); p += 8;
1452 SOFF_T(p,0,file_size); p += 8;
1453 SOFF_T(p,0,allocation_size); p += 8;
1454 SIVAL(p,0,nt_extmode); p += 4;
1455 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1456 SIVAL(p,0,len);
1457 p += 4 + len;
1458 SIVAL(p,0,0); /* Ensure any padding is null. */
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1461 SIVAL(pdata,0,len);
1462 p = pdata + len;
1463 break;
1465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1467 p += 4;
1468 SIVAL(p,0,reskey); p += 4;
1469 put_long_date_timespec(p,create_date_ts); p += 8;
1470 put_long_date_timespec(p,adate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 put_long_date_timespec(p,mdate_ts); p += 8;
1473 SOFF_T(p,0,file_size); p += 8;
1474 SOFF_T(p,0,allocation_size); p += 8;
1475 SIVAL(p,0,nt_extmode); p += 4;
1476 q = p; p += 4; /* q is placeholder for name length. */
1478 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1479 SIVAL(p,0,ea_size); /* Extended attributes */
1480 p +=4;
1482 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1483 SIVAL(q, 0, len);
1484 p += len;
1486 SIVAL(p,0,0); /* Ensure any padding is null. */
1487 len = PTR_DIFF(p, pdata);
1488 len = (len + 3) & ~3;
1489 SIVAL(pdata,0,len);
1490 p = pdata + len;
1491 break;
1493 case SMB_FIND_FILE_NAMES_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1495 p += 4;
1496 SIVAL(p,0,reskey); p += 4;
1497 p += 4;
1498 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1499 acl on a dir (tridge) */
1500 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1501 SIVAL(p, -4, len);
1502 p += len;
1503 SIVAL(p,0,0); /* Ensure any padding is null. */
1504 len = PTR_DIFF(p, pdata);
1505 len = (len + 3) & ~3;
1506 SIVAL(pdata,0,len);
1507 p = pdata + len;
1508 break;
1510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1512 p += 4;
1513 SIVAL(p,0,reskey); p += 4;
1514 put_long_date_timespec(p,create_date_ts); p += 8;
1515 put_long_date_timespec(p,adate_ts); p += 8;
1516 put_long_date_timespec(p,mdate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 SOFF_T(p,0,file_size); p += 8;
1519 SOFF_T(p,0,allocation_size); p += 8;
1520 SIVAL(p,0,nt_extmode); p += 4;
1521 q = p; p += 4; /* q is placeholder for name length. */
1523 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1524 SIVAL(p,0,ea_size); /* Extended attributes */
1525 p +=4;
1527 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1528 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1529 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1530 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1531 SIVAL(q, 0, len);
1532 p += len;
1533 SIVAL(p,0,0); /* Ensure any padding is null. */
1534 len = PTR_DIFF(p, pdata);
1535 len = (len + 3) & ~3;
1536 SIVAL(pdata,0,len);
1537 p = pdata + len;
1538 break;
1540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1542 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1543 p += 4;
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1556 p +=4;
1558 /* Clear the short name buffer. This is
1559 * IMPORTANT as not doing so will trigger
1560 * a Win2k client bug. JRA.
1562 if (!was_8_3 && check_mangled_names) {
1563 pstring mangled_name;
1564 pstrcpy(mangled_name, fname);
1565 mangle_map(mangled_name,True,True,
1566 conn->params);
1567 mangled_name[12] = 0;
1568 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1569 SSVAL(p, 0, len);
1570 if (len < 24) {
1571 memset(p + 2 + len,'\0',24 - len);
1573 SSVAL(p, 0, len);
1574 } else {
1575 memset(p,'\0',26);
1577 p += 26;
1578 SSVAL(p,0,0); p += 2; /* Reserved ? */
1579 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1580 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1581 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1582 SIVAL(q,0,len);
1583 p += len;
1584 SIVAL(p,0,0); /* Ensure any padding is null. */
1585 len = PTR_DIFF(p, pdata);
1586 len = (len + 3) & ~3;
1587 SIVAL(pdata,0,len);
1588 p = pdata + len;
1589 break;
1591 /* CIFS UNIX Extension. */
1593 case SMB_FIND_FILE_UNIX:
1594 case SMB_FIND_FILE_UNIX_INFO2:
1595 p+= 4;
1596 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1598 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (info_level == SMB_FIND_FILE_UNIX) {
1601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1602 p = store_file_unix_basic(conn, p,
1603 NULL, &sbuf);
1604 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1605 } else {
1606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1607 p = store_file_unix_basic_info2(conn, p,
1608 NULL, &sbuf);
1609 nameptr = p;
1610 p += 4;
1611 len = srvstr_push(outbuf, p, fname, -1, 0);
1612 SIVAL(nameptr, 0, len);
1615 p += len;
1616 SIVAL(p,0,0); /* Ensure any padding is null. */
1618 len = PTR_DIFF(p, pdata);
1619 len = (len + 3) & ~3;
1620 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1621 p = pdata + len;
1622 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1624 break;
1626 default:
1627 return(False);
1631 if (PTR_DIFF(p,pdata) > space_remaining) {
1632 /* Move the dirptr back to prev_dirpos */
1633 dptr_SeekDir(conn->dirptr, prev_dirpos);
1634 *out_of_space = True;
1635 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1636 return False; /* Not finished - just out of space */
1639 /* Setup the last entry pointer, as an offset from base_data */
1640 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1641 /* Advance the data pointer to the next slot */
1642 *ppdata = p;
1644 return(found);
1647 /****************************************************************************
1648 Reply to a TRANS2_FINDFIRST.
1649 ****************************************************************************/
1651 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1652 char **pparams, int total_params, char **ppdata, int total_data,
1653 unsigned int max_data_bytes)
1655 /* We must be careful here that we don't return more than the
1656 allowed number of data bytes. If this means returning fewer than
1657 maxentries then so be it. We assume that the redirector has
1658 enough room for the fixed number of parameter bytes it has
1659 requested. */
1660 char *params = *pparams;
1661 char *pdata = *ppdata;
1662 uint32 dirtype;
1663 int maxentries;
1664 uint16 findfirst_flags;
1665 BOOL close_after_first;
1666 BOOL close_if_end;
1667 BOOL requires_resume_key;
1668 int info_level;
1669 pstring directory;
1670 pstring mask;
1671 char *p;
1672 int last_entry_off=0;
1673 int dptr_num = -1;
1674 int numentries = 0;
1675 int i;
1676 BOOL finished = False;
1677 BOOL dont_descend = False;
1678 BOOL out_of_space = False;
1679 int space_remaining;
1680 BOOL mask_contains_wcard = False;
1681 SMB_STRUCT_STAT sbuf;
1682 TALLOC_CTX *ea_ctx = NULL;
1683 struct ea_list *ea_list = NULL;
1684 NTSTATUS ntstatus = NT_STATUS_OK;
1686 if (total_params < 13) {
1687 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1690 dirtype = SVAL(params,0);
1691 maxentries = SVAL(params,2);
1692 findfirst_flags = SVAL(params,4);
1693 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1694 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1695 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1696 info_level = SVAL(params,6);
1698 *directory = *mask = 0;
1700 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1701 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1702 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1703 info_level, max_data_bytes));
1705 if (!maxentries) {
1706 /* W2K3 seems to treat zero as 1. */
1707 maxentries = 1;
1710 switch (info_level) {
1711 case SMB_FIND_INFO_STANDARD:
1712 case SMB_FIND_EA_SIZE:
1713 case SMB_FIND_EA_LIST:
1714 case SMB_FIND_FILE_DIRECTORY_INFO:
1715 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1716 case SMB_FIND_FILE_NAMES_INFO:
1717 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1718 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1719 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1720 break;
1721 case SMB_FIND_FILE_UNIX:
1722 case SMB_FIND_FILE_UNIX_INFO2:
1723 if (!lp_unix_extensions()) {
1724 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1726 break;
1727 default:
1728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1731 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1732 if (!NT_STATUS_IS_OK(ntstatus)) {
1733 return ERROR_NT(ntstatus);
1736 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1737 if (!NT_STATUS_IS_OK(ntstatus)) {
1738 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1739 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1741 return ERROR_NT(ntstatus);
1744 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1745 if (!NT_STATUS_IS_OK(ntstatus)) {
1746 return ERROR_NT(ntstatus);
1748 ntstatus = check_name(conn, directory);
1749 if (!NT_STATUS_IS_OK(ntstatus)) {
1750 return ERROR_NT(ntstatus);
1753 p = strrchr_m(directory,'/');
1754 if(p == NULL) {
1755 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1756 if((directory[0] == '.') && (directory[1] == '\0')) {
1757 pstrcpy(mask,"*");
1758 mask_contains_wcard = True;
1759 } else {
1760 pstrcpy(mask,directory);
1762 pstrcpy(directory,"./");
1763 } else {
1764 pstrcpy(mask,p+1);
1765 *p = 0;
1768 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1770 if (info_level == SMB_FIND_EA_LIST) {
1771 uint32 ea_size;
1773 if (total_data < 4) {
1774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1777 ea_size = IVAL(pdata,0);
1778 if (ea_size != total_data) {
1779 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1780 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1784 if (!lp_ea_support(SNUM(conn))) {
1785 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1788 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1789 return ERROR_NT(NT_STATUS_NO_MEMORY);
1792 /* Pull out the list of names. */
1793 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1794 if (!ea_list) {
1795 talloc_destroy(ea_ctx);
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 *ppdata = (char *)SMB_REALLOC(
1801 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1802 if(*ppdata == NULL ) {
1803 talloc_destroy(ea_ctx);
1804 return ERROR_NT(NT_STATUS_NO_MEMORY);
1806 pdata = *ppdata;
1808 /* Realloc the params space */
1809 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1810 if (*pparams == NULL) {
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_NO_MEMORY);
1814 params = *pparams;
1816 /* Save the wildcard match and attribs we are using on this directory -
1817 needed as lanman2 assumes these are being saved between calls */
1819 ntstatus = dptr_create(conn,
1820 directory,
1821 False,
1822 True,
1823 SVAL(inbuf,smb_pid),
1824 mask,
1825 mask_contains_wcard,
1826 dirtype,
1827 &conn->dirptr);
1829 if (!NT_STATUS_IS_OK(ntstatus)) {
1830 talloc_destroy(ea_ctx);
1831 return ERROR_NT(ntstatus);
1834 dptr_num = dptr_dnum(conn->dirptr);
1835 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1837 /* We don't need to check for VOL here as this is returned by
1838 a different TRANS2 call. */
1840 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1841 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1842 dont_descend = True;
1844 p = pdata;
1845 space_remaining = max_data_bytes;
1846 out_of_space = False;
1848 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1849 BOOL got_exact_match = False;
1851 /* this is a heuristic to avoid seeking the dirptr except when
1852 absolutely necessary. It allows for a filename of about 40 chars */
1853 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1854 out_of_space = True;
1855 finished = False;
1856 } else {
1857 finished = !get_lanman2_dir_entry(conn,
1858 inbuf, outbuf,
1859 mask,dirtype,info_level,
1860 requires_resume_key,dont_descend,
1861 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1862 &last_entry_off, ea_list, ea_ctx);
1865 if (finished && out_of_space)
1866 finished = False;
1868 if (!finished && !out_of_space)
1869 numentries++;
1872 * As an optimisation if we know we aren't looking
1873 * for a wildcard name (ie. the name matches the wildcard exactly)
1874 * then we can finish on any (first) match.
1875 * This speeds up large directory searches. JRA.
1878 if(got_exact_match)
1879 finished = True;
1881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1884 talloc_destroy(ea_ctx);
1886 /* Check if we can close the dirptr */
1887 if(close_after_first || (finished && close_if_end)) {
1888 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1889 dptr_close(&dptr_num);
1893 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1894 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1895 * the protocol level is less than NT1. Tested with smbclient. JRA.
1896 * This should fix the OS/2 client bug #2335.
1899 if(numentries == 0) {
1900 dptr_close(&dptr_num);
1901 if (Protocol < PROTOCOL_NT1) {
1902 return ERROR_DOS(ERRDOS,ERRnofiles);
1903 } else {
1904 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1908 /* At this point pdata points to numentries directory entries. */
1910 /* Set up the return parameter block */
1911 SSVAL(params,0,dptr_num);
1912 SSVAL(params,2,numentries);
1913 SSVAL(params,4,finished);
1914 SSVAL(params,6,0); /* Never an EA error */
1915 SSVAL(params,8,last_entry_off);
1917 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1919 if ((! *directory) && dptr_path(dptr_num))
1920 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1922 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1923 smb_fn_name(CVAL(inbuf,smb_com)),
1924 mask, directory, dirtype, numentries ) );
1927 * Force a name mangle here to ensure that the
1928 * mask as an 8.3 name is top of the mangled cache.
1929 * The reasons for this are subtle. Don't remove
1930 * this code unless you know what you are doing
1931 * (see PR#13758). JRA.
1934 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1935 mangle_map(mask, True, True, conn->params);
1937 return(-1);
1940 /****************************************************************************
1941 Reply to a TRANS2_FINDNEXT.
1942 ****************************************************************************/
1944 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1945 char **pparams, int total_params, char **ppdata, int total_data,
1946 unsigned int max_data_bytes)
1948 /* We must be careful here that we don't return more than the
1949 allowed number of data bytes. If this means returning fewer than
1950 maxentries then so be it. We assume that the redirector has
1951 enough room for the fixed number of parameter bytes it has
1952 requested. */
1953 char *params = *pparams;
1954 char *pdata = *ppdata;
1955 int dptr_num;
1956 int maxentries;
1957 uint16 info_level;
1958 uint32 resume_key;
1959 uint16 findnext_flags;
1960 BOOL close_after_request;
1961 BOOL close_if_end;
1962 BOOL requires_resume_key;
1963 BOOL continue_bit;
1964 BOOL mask_contains_wcard = False;
1965 pstring resume_name;
1966 pstring mask;
1967 pstring directory;
1968 char *p;
1969 uint16 dirtype;
1970 int numentries = 0;
1971 int i, last_entry_off=0;
1972 BOOL finished = False;
1973 BOOL dont_descend = False;
1974 BOOL out_of_space = False;
1975 int space_remaining;
1976 TALLOC_CTX *ea_ctx = NULL;
1977 struct ea_list *ea_list = NULL;
1978 NTSTATUS ntstatus = NT_STATUS_OK;
1980 if (total_params < 13) {
1981 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1984 dptr_num = SVAL(params,0);
1985 maxentries = SVAL(params,2);
1986 info_level = SVAL(params,4);
1987 resume_key = IVAL(params,6);
1988 findnext_flags = SVAL(params,10);
1989 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1990 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1991 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1992 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1994 *mask = *directory = *resume_name = 0;
1996 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1997 if (!NT_STATUS_IS_OK(ntstatus)) {
1998 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1999 complain (it thinks we're asking for the directory above the shared
2000 path or an invalid name). Catch this as the resume name is only compared, never used in
2001 a file access. JRA. */
2002 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2003 pstrcpy(resume_name, "..");
2004 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2005 pstrcpy(resume_name, ".");
2006 } else {
2007 return ERROR_NT(ntstatus);
2011 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2012 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2013 resume_key = %d resume name = %s continue=%d level = %d\n",
2014 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2015 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2017 if (!maxentries) {
2018 /* W2K3 seems to treat zero as 1. */
2019 maxentries = 1;
2022 switch (info_level) {
2023 case SMB_FIND_INFO_STANDARD:
2024 case SMB_FIND_EA_SIZE:
2025 case SMB_FIND_EA_LIST:
2026 case SMB_FIND_FILE_DIRECTORY_INFO:
2027 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2028 case SMB_FIND_FILE_NAMES_INFO:
2029 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2030 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2031 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2032 break;
2033 case SMB_FIND_FILE_UNIX:
2034 case SMB_FIND_FILE_UNIX_INFO2:
2035 if (!lp_unix_extensions()) {
2036 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2038 break;
2039 default:
2040 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2043 if (info_level == SMB_FIND_EA_LIST) {
2044 uint32 ea_size;
2046 if (total_data < 4) {
2047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2050 ea_size = IVAL(pdata,0);
2051 if (ea_size != total_data) {
2052 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2053 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2057 if (!lp_ea_support(SNUM(conn))) {
2058 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2061 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2062 return ERROR_NT(NT_STATUS_NO_MEMORY);
2065 /* Pull out the list of names. */
2066 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2067 if (!ea_list) {
2068 talloc_destroy(ea_ctx);
2069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 *ppdata = (char *)SMB_REALLOC(
2074 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2075 if(*ppdata == NULL) {
2076 talloc_destroy(ea_ctx);
2077 return ERROR_NT(NT_STATUS_NO_MEMORY);
2080 pdata = *ppdata;
2082 /* Realloc the params space */
2083 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2084 if(*pparams == NULL ) {
2085 talloc_destroy(ea_ctx);
2086 return ERROR_NT(NT_STATUS_NO_MEMORY);
2089 params = *pparams;
2091 /* Check that the dptr is valid */
2092 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2093 talloc_destroy(ea_ctx);
2094 return ERROR_DOS(ERRDOS,ERRnofiles);
2097 string_set(&conn->dirpath,dptr_path(dptr_num));
2099 /* Get the wildcard mask from the dptr */
2100 if((p = dptr_wcard(dptr_num))== NULL) {
2101 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2102 talloc_destroy(ea_ctx);
2103 return ERROR_DOS(ERRDOS,ERRnofiles);
2106 pstrcpy(mask, p);
2107 pstrcpy(directory,conn->dirpath);
2109 /* Get the attr mask from the dptr */
2110 dirtype = dptr_attr(dptr_num);
2112 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2113 dptr_num, mask, dirtype,
2114 (long)conn->dirptr,
2115 dptr_TellDir(conn->dirptr)));
2117 /* We don't need to check for VOL here as this is returned by
2118 a different TRANS2 call. */
2120 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2121 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2122 dont_descend = True;
2124 p = pdata;
2125 space_remaining = max_data_bytes;
2126 out_of_space = False;
2129 * Seek to the correct position. We no longer use the resume key but
2130 * depend on the last file name instead.
2133 if(*resume_name && !continue_bit) {
2134 SMB_STRUCT_STAT st;
2136 long current_pos = 0;
2138 * Remember, mangle_map is called by
2139 * get_lanman2_dir_entry(), so the resume name
2140 * could be mangled. Ensure we check the unmangled name.
2143 if (mangle_is_mangled(resume_name, conn->params)) {
2144 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2145 conn->params);
2149 * Fix for NT redirector problem triggered by resume key indexes
2150 * changing between directory scans. We now return a resume key of 0
2151 * and instead look for the filename to continue from (also given
2152 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2153 * findfirst/findnext (as is usual) then the directory pointer
2154 * should already be at the correct place.
2157 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2158 } /* end if resume_name && !continue_bit */
2160 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2161 BOOL got_exact_match = False;
2163 /* this is a heuristic to avoid seeking the dirptr except when
2164 absolutely necessary. It allows for a filename of about 40 chars */
2165 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2166 out_of_space = True;
2167 finished = False;
2168 } else {
2169 finished = !get_lanman2_dir_entry(conn,
2170 inbuf, outbuf,
2171 mask,dirtype,info_level,
2172 requires_resume_key,dont_descend,
2173 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2174 &last_entry_off, ea_list, ea_ctx);
2177 if (finished && out_of_space)
2178 finished = False;
2180 if (!finished && !out_of_space)
2181 numentries++;
2184 * As an optimisation if we know we aren't looking
2185 * for a wildcard name (ie. the name matches the wildcard exactly)
2186 * then we can finish on any (first) match.
2187 * This speeds up large directory searches. JRA.
2190 if(got_exact_match)
2191 finished = True;
2193 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2196 talloc_destroy(ea_ctx);
2198 /* Check if we can close the dirptr */
2199 if(close_after_request || (finished && close_if_end)) {
2200 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2201 dptr_close(&dptr_num); /* This frees up the saved mask */
2204 /* Set up the return parameter block */
2205 SSVAL(params,0,numentries);
2206 SSVAL(params,2,finished);
2207 SSVAL(params,4,0); /* Never an EA error */
2208 SSVAL(params,6,last_entry_off);
2210 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2212 if ((! *directory) && dptr_path(dptr_num))
2213 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2215 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2216 smb_fn_name(CVAL(inbuf,smb_com)),
2217 mask, directory, dirtype, numentries ) );
2219 return(-1);
2222 /****************************************************************************
2223 Reply to a TRANS2_QFSINFO (query filesystem info).
2224 ****************************************************************************/
2226 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2227 char **pparams, int total_params, char **ppdata, int total_data,
2228 unsigned int max_data_bytes)
2230 char *pdata;
2231 char *params = *pparams;
2232 uint16 info_level;
2233 int data_len, len;
2234 SMB_STRUCT_STAT st;
2235 char *vname = volume_label(SNUM(conn));
2236 int snum = SNUM(conn);
2237 char *fstype = lp_fstype(SNUM(conn));
2238 int quota_flag = 0;
2240 if (total_params < 2) {
2241 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2244 info_level = SVAL(params,0);
2246 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2248 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2249 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2250 return ERROR_DOS(ERRSRV,ERRinvdevice);
2253 *ppdata = (char *)SMB_REALLOC(
2254 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2255 if (*ppdata == NULL ) {
2256 return ERROR_NT(NT_STATUS_NO_MEMORY);
2259 pdata = *ppdata;
2260 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2262 switch (info_level) {
2263 case SMB_INFO_ALLOCATION:
2265 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2266 data_len = 18;
2267 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2268 return(UNIXERROR(ERRHRD,ERRgeneral));
2271 block_size = lp_block_size(snum);
2272 if (bsize < block_size) {
2273 SMB_BIG_UINT factor = block_size/bsize;
2274 bsize = block_size;
2275 dsize /= factor;
2276 dfree /= factor;
2278 if (bsize > block_size) {
2279 SMB_BIG_UINT factor = bsize/block_size;
2280 bsize = block_size;
2281 dsize *= factor;
2282 dfree *= factor;
2284 bytes_per_sector = 512;
2285 sectors_per_unit = bsize/bytes_per_sector;
2287 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2289 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2291 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2292 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2293 SIVAL(pdata,l1_cUnit,dsize);
2294 SIVAL(pdata,l1_cUnitAvail,dfree);
2295 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2296 break;
2299 case SMB_INFO_VOLUME:
2300 /* Return volume name */
2302 * Add volume serial number - hash of a combination of
2303 * the called hostname and the service name.
2305 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2307 * Win2k3 and previous mess this up by sending a name length
2308 * one byte short. I believe only older clients (OS/2 Win9x) use
2309 * this call so try fixing this by adding a terminating null to
2310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2312 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2313 SCVAL(pdata,l2_vol_cch,len);
2314 data_len = l2_vol_szVolLabel + len;
2315 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2316 (unsigned)st.st_ctime, len, vname));
2317 break;
2319 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2320 case SMB_FS_ATTRIBUTE_INFORMATION:
2323 #if defined(HAVE_SYS_QUOTAS)
2324 quota_flag = FILE_VOLUME_QUOTAS;
2325 #endif
2327 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2328 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2329 quota_flag); /* FS ATTRIBUTES */
2331 SIVAL(pdata,4,255); /* Max filename component length */
2332 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2333 and will think we can't do long filenames */
2334 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2335 SIVAL(pdata,8,len);
2336 data_len = 12 + len;
2337 break;
2339 case SMB_QUERY_FS_LABEL_INFO:
2340 case SMB_FS_LABEL_INFORMATION:
2341 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2342 data_len = 4 + len;
2343 SIVAL(pdata,0,len);
2344 break;
2346 case SMB_QUERY_FS_VOLUME_INFO:
2347 case SMB_FS_VOLUME_INFORMATION:
2350 * Add volume serial number - hash of a combination of
2351 * the called hostname and the service name.
2353 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2354 (str_checksum(get_local_machine_name())<<16));
2356 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2357 SIVAL(pdata,12,len);
2358 data_len = 18+len;
2359 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2360 (int)strlen(vname),vname, lp_servicename(snum)));
2361 break;
2363 case SMB_QUERY_FS_SIZE_INFO:
2364 case SMB_FS_SIZE_INFORMATION:
2366 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2367 data_len = 24;
2368 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2369 return(UNIXERROR(ERRHRD,ERRgeneral));
2371 block_size = lp_block_size(snum);
2372 if (bsize < block_size) {
2373 SMB_BIG_UINT factor = block_size/bsize;
2374 bsize = block_size;
2375 dsize /= factor;
2376 dfree /= factor;
2378 if (bsize > block_size) {
2379 SMB_BIG_UINT factor = bsize/block_size;
2380 bsize = block_size;
2381 dsize *= factor;
2382 dfree *= factor;
2384 bytes_per_sector = 512;
2385 sectors_per_unit = bsize/bytes_per_sector;
2386 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2387 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2388 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2389 SBIG_UINT(pdata,0,dsize);
2390 SBIG_UINT(pdata,8,dfree);
2391 SIVAL(pdata,16,sectors_per_unit);
2392 SIVAL(pdata,20,bytes_per_sector);
2393 break;
2396 case SMB_FS_FULL_SIZE_INFORMATION:
2398 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2399 data_len = 32;
2400 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2401 return(UNIXERROR(ERRHRD,ERRgeneral));
2403 block_size = lp_block_size(snum);
2404 if (bsize < block_size) {
2405 SMB_BIG_UINT factor = block_size/bsize;
2406 bsize = block_size;
2407 dsize /= factor;
2408 dfree /= factor;
2410 if (bsize > block_size) {
2411 SMB_BIG_UINT factor = bsize/block_size;
2412 bsize = block_size;
2413 dsize *= factor;
2414 dfree *= factor;
2416 bytes_per_sector = 512;
2417 sectors_per_unit = bsize/bytes_per_sector;
2418 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2419 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2420 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2421 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2422 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2423 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2424 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2425 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2426 break;
2429 case SMB_QUERY_FS_DEVICE_INFO:
2430 case SMB_FS_DEVICE_INFORMATION:
2431 data_len = 8;
2432 SIVAL(pdata,0,0); /* dev type */
2433 SIVAL(pdata,4,0); /* characteristics */
2434 break;
2436 #ifdef HAVE_SYS_QUOTAS
2437 case SMB_FS_QUOTA_INFORMATION:
2439 * what we have to send --metze:
2441 * Unknown1: 24 NULL bytes
2442 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2443 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2444 * Quota Flags: 2 byte :
2445 * Unknown3: 6 NULL bytes
2447 * 48 bytes total
2449 * details for Quota Flags:
2451 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2452 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2453 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2454 * 0x0001 Enable Quotas: enable quota for this fs
2458 /* we need to fake up a fsp here,
2459 * because its not send in this call
2461 files_struct fsp;
2462 SMB_NTQUOTA_STRUCT quotas;
2464 ZERO_STRUCT(fsp);
2465 ZERO_STRUCT(quotas);
2467 fsp.conn = conn;
2468 fsp.fnum = -1;
2470 /* access check */
2471 if (current_user.ut.uid != 0) {
2472 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2473 lp_servicename(SNUM(conn)),conn->user));
2474 return ERROR_DOS(ERRDOS,ERRnoaccess);
2477 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2478 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2479 return ERROR_DOS(ERRSRV,ERRerror);
2482 data_len = 48;
2484 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2486 /* Unknown1 24 NULL bytes*/
2487 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2488 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2489 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2491 /* Default Soft Quota 8 bytes */
2492 SBIG_UINT(pdata,24,quotas.softlim);
2494 /* Default Hard Quota 8 bytes */
2495 SBIG_UINT(pdata,32,quotas.hardlim);
2497 /* Quota flag 2 bytes */
2498 SSVAL(pdata,40,quotas.qflags);
2500 /* Unknown3 6 NULL bytes */
2501 SSVAL(pdata,42,0);
2502 SIVAL(pdata,44,0);
2504 break;
2506 #endif /* HAVE_SYS_QUOTAS */
2507 case SMB_FS_OBJECTID_INFORMATION:
2508 data_len = 64;
2509 break;
2512 * Query the version and capabilities of the CIFS UNIX extensions
2513 * in use.
2516 case SMB_QUERY_CIFS_UNIX_INFO:
2517 if (!lp_unix_extensions()) {
2518 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2520 data_len = 12;
2521 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2522 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2523 /* We have POSIX ACLs, pathname and locking capability. */
2524 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2525 CIFS_UNIX_POSIX_ACLS_CAP|
2526 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2527 CIFS_UNIX_FCNTL_LOCKS_CAP|
2528 CIFS_UNIX_EXTATTR_CAP|
2529 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2530 break;
2532 case SMB_QUERY_POSIX_FS_INFO:
2534 int rc;
2535 vfs_statvfs_struct svfs;
2537 if (!lp_unix_extensions()) {
2538 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2541 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2543 if (!rc) {
2544 data_len = 56;
2545 SIVAL(pdata,0,svfs.OptimalTransferSize);
2546 SIVAL(pdata,4,svfs.BlockSize);
2547 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2548 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2549 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2550 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2551 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2552 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2553 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2554 #ifdef EOPNOTSUPP
2555 } else if (rc == EOPNOTSUPP) {
2556 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2557 #endif /* EOPNOTSUPP */
2558 } else {
2559 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2560 return ERROR_DOS(ERRSRV,ERRerror);
2562 break;
2565 case SMB_QUERY_POSIX_WHOAMI:
2567 uint32_t flags = 0;
2568 uint32_t sid_bytes;
2569 int i;
2571 if (!lp_unix_extensions()) {
2572 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2575 if (max_data_bytes < 40) {
2576 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2579 /* We ARE guest if global_sid_Builtin_Guests is
2580 * in our list of SIDs.
2582 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2583 current_user.nt_user_token)) {
2584 flags |= SMB_WHOAMI_GUEST;
2587 /* We are NOT guest if global_sid_Authenticated_Users
2588 * is in our list of SIDs.
2590 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2591 current_user.nt_user_token)) {
2592 flags &= ~SMB_WHOAMI_GUEST;
2595 /* NOTE: 8 bytes for UID/GID, irrespective of native
2596 * platform size. This matches
2597 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2599 data_len = 4 /* flags */
2600 + 4 /* flag mask */
2601 + 8 /* uid */
2602 + 8 /* gid */
2603 + 4 /* ngroups */
2604 + 4 /* num_sids */
2605 + 4 /* SID bytes */
2606 + 4 /* pad/reserved */
2607 + (current_user.ut.ngroups * 8)
2608 /* groups list */
2609 + (current_user.nt_user_token->num_sids *
2610 SID_MAX_SIZE)
2611 /* SID list */;
2613 SIVAL(pdata, 0, flags);
2614 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2615 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2616 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2619 if (data_len >= max_data_bytes) {
2620 /* Potential overflow, skip the GIDs and SIDs. */
2622 SIVAL(pdata, 24, 0); /* num_groups */
2623 SIVAL(pdata, 28, 0); /* num_sids */
2624 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2625 SIVAL(pdata, 36, 0); /* reserved */
2627 data_len = 40;
2628 break;
2631 SIVAL(pdata, 24, current_user.ut.ngroups);
2632 SIVAL(pdata, 28,
2633 current_user.nt_user_token->num_sids);
2635 /* We walk the SID list twice, but this call is fairly
2636 * infrequent, and I don't expect that it's performance
2637 * sensitive -- jpeach
2639 for (i = 0, sid_bytes = 0;
2640 i < current_user.nt_user_token->num_sids; ++i) {
2641 sid_bytes +=
2642 sid_size(&current_user.nt_user_token->user_sids[i]);
2645 /* SID list byte count */
2646 SIVAL(pdata, 32, sid_bytes);
2648 /* 4 bytes pad/reserved - must be zero */
2649 SIVAL(pdata, 36, 0);
2650 data_len = 40;
2652 /* GID list */
2653 for (i = 0; i < current_user.ut.ngroups; ++i) {
2654 SBIG_UINT(pdata, data_len,
2655 (SMB_BIG_UINT)current_user.ut.groups[i]);
2656 data_len += 8;
2659 /* SID list */
2660 for (i = 0;
2661 i < current_user.nt_user_token->num_sids; ++i) {
2662 int sid_len =
2663 sid_size(&current_user.nt_user_token->user_sids[i]);
2665 sid_linearize(pdata + data_len, sid_len,
2666 &current_user.nt_user_token->user_sids[i]);
2667 data_len += sid_len;
2670 break;
2673 case SMB_MAC_QUERY_FS_INFO:
2675 * Thursby MAC extension... ONLY on NTFS filesystems
2676 * once we do streams then we don't need this
2678 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2679 data_len = 88;
2680 SIVAL(pdata,84,0x100); /* Don't support mac... */
2681 break;
2683 /* drop through */
2684 default:
2685 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2689 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2691 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2693 return -1;
2696 /****************************************************************************
2697 Reply to a TRANS2_SETFSINFO (set filesystem info).
2698 ****************************************************************************/
2700 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2701 char **pparams, int total_params, char **ppdata, int total_data,
2702 unsigned int max_data_bytes)
2704 char *pdata = *ppdata;
2705 char *params = *pparams;
2706 uint16 info_level;
2707 int outsize;
2709 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2711 /* */
2712 if (total_params < 4) {
2713 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2714 total_params));
2715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2718 info_level = SVAL(params,2);
2720 switch(info_level) {
2721 case SMB_SET_CIFS_UNIX_INFO:
2723 uint16 client_unix_major;
2724 uint16 client_unix_minor;
2725 uint32 client_unix_cap_low;
2726 uint32 client_unix_cap_high;
2728 if (!lp_unix_extensions()) {
2729 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2732 /* There should be 12 bytes of capabilities set. */
2733 if (total_data < 8) {
2734 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2736 client_unix_major = SVAL(pdata,0);
2737 client_unix_minor = SVAL(pdata,2);
2738 client_unix_cap_low = IVAL(pdata,4);
2739 client_unix_cap_high = IVAL(pdata,8);
2740 /* Just print these values for now. */
2741 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2742 cap_low = 0x%x, cap_high = 0x%x\n",
2743 (unsigned int)client_unix_major,
2744 (unsigned int)client_unix_minor,
2745 (unsigned int)client_unix_cap_low,
2746 (unsigned int)client_unix_cap_high ));
2748 /* Here is where we must switch to posix pathname processing... */
2749 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2750 lp_set_posix_pathnames();
2751 mangle_change_to_posix();
2754 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2755 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2756 /* Client that knows how to do posix locks,
2757 * but not posix open/mkdir operations. Set a
2758 * default type for read/write checks. */
2760 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2763 break;
2765 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2767 NTSTATUS status;
2768 size_t data_len = total_data;
2770 if (!lp_unix_extensions()) {
2771 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2774 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2776 status = srv_request_encryption_setup((unsigned char **)ppdata, &data_len);
2778 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2779 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2780 } else if (!NT_STATUS_IS_OK(status)) {
2781 return ERROR_NT(status);
2784 send_trans2_replies( outbuf, bufsize, params, 0, *ppdata, data_len, max_data_bytes);
2786 if (NT_STATUS_IS_OK(status)) {
2787 /* Server-side transport encryption is now *on*. */
2788 status = srv_encryption_start();
2789 if (!NT_STATUS_IS_OK(status)) {
2790 exit_server_cleanly("Failure in setting up encrypted transport");
2793 return -1;
2795 case SMB_FS_QUOTA_INFORMATION:
2797 files_struct *fsp = NULL;
2798 SMB_NTQUOTA_STRUCT quotas;
2800 ZERO_STRUCT(quotas);
2802 /* access check */
2803 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2804 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2805 lp_servicename(SNUM(conn)),conn->user));
2806 return ERROR_DOS(ERRSRV,ERRaccess);
2809 /* note: normaly there're 48 bytes,
2810 * but we didn't use the last 6 bytes for now
2811 * --metze
2813 fsp = file_fsp(params,0);
2814 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2815 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2816 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2819 if (total_data < 42) {
2820 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2821 total_data));
2822 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2825 /* unknown_1 24 NULL bytes in pdata*/
2827 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2828 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2829 #ifdef LARGE_SMB_OFF_T
2830 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2831 #else /* LARGE_SMB_OFF_T */
2832 if ((IVAL(pdata,28) != 0)&&
2833 ((quotas.softlim != 0xFFFFFFFF)||
2834 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2835 /* more than 32 bits? */
2836 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2838 #endif /* LARGE_SMB_OFF_T */
2840 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2841 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2842 #ifdef LARGE_SMB_OFF_T
2843 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2844 #else /* LARGE_SMB_OFF_T */
2845 if ((IVAL(pdata,36) != 0)&&
2846 ((quotas.hardlim != 0xFFFFFFFF)||
2847 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2848 /* more than 32 bits? */
2849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2851 #endif /* LARGE_SMB_OFF_T */
2853 /* quota_flags 2 bytes **/
2854 quotas.qflags = SVAL(pdata,40);
2856 /* unknown_2 6 NULL bytes follow*/
2858 /* now set the quotas */
2859 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2860 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2861 return ERROR_DOS(ERRSRV,ERRerror);
2864 break;
2866 default:
2867 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2868 info_level));
2869 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2870 break;
2874 * sending this reply works fine,
2875 * but I'm not sure it's the same
2876 * like windows do...
2877 * --metze
2879 outsize = set_message(outbuf,10,0,True);
2881 return outsize;
2884 #if defined(HAVE_POSIX_ACLS)
2885 /****************************************************************************
2886 Utility function to count the number of entries in a POSIX acl.
2887 ****************************************************************************/
2889 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2891 unsigned int ace_count = 0;
2892 int entry_id = SMB_ACL_FIRST_ENTRY;
2893 SMB_ACL_ENTRY_T entry;
2895 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2896 /* get_next... */
2897 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2898 entry_id = SMB_ACL_NEXT_ENTRY;
2900 ace_count++;
2902 return ace_count;
2905 /****************************************************************************
2906 Utility function to marshall a POSIX acl into wire format.
2907 ****************************************************************************/
2909 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2911 int entry_id = SMB_ACL_FIRST_ENTRY;
2912 SMB_ACL_ENTRY_T entry;
2914 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2915 SMB_ACL_TAG_T tagtype;
2916 SMB_ACL_PERMSET_T permset;
2917 unsigned char perms = 0;
2918 unsigned int own_grp;
2920 /* get_next... */
2921 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2922 entry_id = SMB_ACL_NEXT_ENTRY;
2925 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2926 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2927 return False;
2930 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2931 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2932 return False;
2935 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2936 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2937 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2939 SCVAL(pdata,1,perms);
2941 switch (tagtype) {
2942 case SMB_ACL_USER_OBJ:
2943 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2944 own_grp = (unsigned int)pst->st_uid;
2945 SIVAL(pdata,2,own_grp);
2946 SIVAL(pdata,6,0);
2947 break;
2948 case SMB_ACL_USER:
2950 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2951 if (!puid) {
2952 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2954 own_grp = (unsigned int)*puid;
2955 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2956 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2957 SIVAL(pdata,2,own_grp);
2958 SIVAL(pdata,6,0);
2959 break;
2961 case SMB_ACL_GROUP_OBJ:
2962 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2963 own_grp = (unsigned int)pst->st_gid;
2964 SIVAL(pdata,2,own_grp);
2965 SIVAL(pdata,6,0);
2966 break;
2967 case SMB_ACL_GROUP:
2969 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2970 if (!pgid) {
2971 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2973 own_grp = (unsigned int)*pgid;
2974 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2975 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2976 SIVAL(pdata,2,own_grp);
2977 SIVAL(pdata,6,0);
2978 break;
2980 case SMB_ACL_MASK:
2981 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2982 SIVAL(pdata,2,0xFFFFFFFF);
2983 SIVAL(pdata,6,0xFFFFFFFF);
2984 break;
2985 case SMB_ACL_OTHER:
2986 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2987 SIVAL(pdata,2,0xFFFFFFFF);
2988 SIVAL(pdata,6,0xFFFFFFFF);
2989 break;
2990 default:
2991 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2992 return False;
2994 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2997 return True;
2999 #endif
3001 /****************************************************************************
3002 Store the FILE_UNIX_BASIC info.
3003 ****************************************************************************/
3005 static char *store_file_unix_basic(connection_struct *conn,
3006 char *pdata,
3007 files_struct *fsp,
3008 const SMB_STRUCT_STAT *psbuf)
3010 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3011 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3013 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3014 pdata += 8;
3016 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3017 pdata += 8;
3019 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3020 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3021 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3022 pdata += 24;
3024 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3025 SIVAL(pdata,4,0);
3026 pdata += 8;
3028 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3029 SIVAL(pdata,4,0);
3030 pdata += 8;
3032 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3033 pdata += 4;
3035 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3036 SIVAL(pdata,4,0);
3037 pdata += 8;
3039 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3040 SIVAL(pdata,4,0);
3041 pdata += 8;
3043 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3044 pdata += 8;
3046 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3047 SIVAL(pdata,4,0);
3048 pdata += 8;
3050 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3051 SIVAL(pdata,4,0);
3052 pdata += 8;
3054 return pdata;
3057 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3058 * the chflags(2) (or equivalent) flags.
3060 * XXX: this really should be behind the VFS interface. To do this, we would
3061 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3062 * Each VFS module could then implement it's own mapping as appropriate for the
3063 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3065 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3066 info2_flags_map[] =
3068 #ifdef UF_NODUMP
3069 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3070 #endif
3072 #ifdef UF_IMMUTABLE
3073 { UF_IMMUTABLE, EXT_IMMUTABLE },
3074 #endif
3076 #ifdef UF_APPEND
3077 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3078 #endif
3080 #ifdef UF_HIDDEN
3081 { UF_HIDDEN, EXT_HIDDEN },
3082 #endif
3084 /* Do not remove. We need to guarantee that this array has at least one
3085 * entry to build on HP-UX.
3087 { 0, 0 }
3091 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3092 uint32 *smb_fflags, uint32 *smb_fmask)
3094 #ifdef HAVE_STAT_ST_FLAGS
3095 int i;
3097 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3098 *smb_fmask |= info2_flags_map[i].smb_fflag;
3099 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3100 *smb_fflags |= info2_flags_map[i].smb_fflag;
3103 #endif /* HAVE_STAT_ST_FLAGS */
3106 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3107 const uint32 smb_fflags,
3108 const uint32 smb_fmask,
3109 int *stat_fflags)
3111 #ifdef HAVE_STAT_ST_FLAGS
3112 uint32 max_fmask = 0;
3113 int i;
3115 *stat_fflags = psbuf->st_flags;
3117 /* For each flags requested in smb_fmask, check the state of the
3118 * corresponding flag in smb_fflags and set or clear the matching
3119 * stat flag.
3122 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3123 max_fmask |= info2_flags_map[i].smb_fflag;
3124 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3125 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3126 *stat_fflags |= info2_flags_map[i].stat_fflag;
3127 } else {
3128 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3133 /* If smb_fmask is asking to set any bits that are not supported by
3134 * our flag mappings, we should fail.
3136 if ((smb_fmask & max_fmask) != smb_fmask) {
3137 return False;
3140 return True;
3141 #else
3142 return False;
3143 #endif /* HAVE_STAT_ST_FLAGS */
3147 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3148 * of file flags and birth (create) time.
3150 static char *store_file_unix_basic_info2(connection_struct *conn,
3151 char *pdata,
3152 files_struct *fsp,
3153 const SMB_STRUCT_STAT *psbuf)
3155 uint32 file_flags = 0;
3156 uint32 flags_mask = 0;
3158 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3160 /* Create (birth) time 64 bit */
3161 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3162 pdata += 8;
3164 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3165 SIVAL(pdata, 0, file_flags); /* flags */
3166 SIVAL(pdata, 4, flags_mask); /* mask */
3167 pdata += 8;
3169 return pdata;
3172 /****************************************************************************
3173 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3174 file name or file id).
3175 ****************************************************************************/
3177 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3178 unsigned int tran_call,
3179 char **pparams, int total_params, char **ppdata, int total_data,
3180 unsigned int max_data_bytes)
3182 char *params = *pparams;
3183 char *pdata = *ppdata;
3184 uint16 info_level;
3185 int mode=0;
3186 int nlink;
3187 SMB_OFF_T file_size=0;
3188 SMB_BIG_UINT allocation_size=0;
3189 unsigned int data_size = 0;
3190 unsigned int param_size = 2;
3191 SMB_STRUCT_STAT sbuf;
3192 pstring fname, dos_fname;
3193 char *fullpathname;
3194 char *base_name;
3195 char *p;
3196 SMB_OFF_T pos = 0;
3197 BOOL delete_pending = False;
3198 int len;
3199 time_t create_time, mtime, atime;
3200 struct timespec create_time_ts, mtime_ts, atime_ts;
3201 files_struct *fsp = NULL;
3202 TALLOC_CTX *data_ctx = NULL;
3203 struct ea_list *ea_list = NULL;
3204 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3205 char *lock_data = NULL;
3207 if (!params)
3208 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3210 ZERO_STRUCT(sbuf);
3212 if (tran_call == TRANSACT2_QFILEINFO) {
3213 if (total_params < 4) {
3214 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3217 fsp = file_fsp(params,0);
3218 info_level = SVAL(params,2);
3220 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3222 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3223 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3226 if(fsp && (fsp->fake_file_handle)) {
3228 * This is actually for the QUOTA_FAKE_FILE --metze
3231 pstrcpy(fname, fsp->fsp_name);
3232 /* We know this name is ok, it's already passed the checks. */
3234 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3236 * This is actually a QFILEINFO on a directory
3237 * handle (returned from an NT SMB). NT5.0 seems
3238 * to do this call. JRA.
3240 /* We know this name is ok, it's already passed the checks. */
3241 pstrcpy(fname, fsp->fsp_name);
3243 if (INFO_LEVEL_IS_UNIX(info_level)) {
3244 /* Always do lstat for UNIX calls. */
3245 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3246 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3247 return UNIXERROR(ERRDOS,ERRbadpath);
3249 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3250 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3251 return UNIXERROR(ERRDOS,ERRbadpath);
3254 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3255 } else {
3257 * Original code - this is an open file.
3259 CHECK_FSP(fsp,conn);
3261 pstrcpy(fname, fsp->fsp_name);
3262 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3263 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3264 return(UNIXERROR(ERRDOS,ERRbadfid));
3266 pos = fsp->fh->position_information;
3267 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3268 access_mask = fsp->access_mask;
3270 } else {
3271 NTSTATUS status = NT_STATUS_OK;
3273 /* qpathinfo */
3274 if (total_params < 7) {
3275 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3278 info_level = SVAL(params,0);
3280 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3282 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3283 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3286 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3287 if (!NT_STATUS_IS_OK(status)) {
3288 return ERROR_NT(status);
3291 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3292 if (!NT_STATUS_IS_OK(status)) {
3293 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3294 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3296 return ERROR_NT(status);
3299 status = unix_convert(conn, fname, False, NULL, &sbuf);
3300 if (!NT_STATUS_IS_OK(status)) {
3301 return ERROR_NT(status);
3303 status = check_name(conn, fname);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3306 return ERROR_NT(status);
3309 if (INFO_LEVEL_IS_UNIX(info_level)) {
3310 /* Always do lstat for UNIX calls. */
3311 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3312 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3313 return UNIXERROR(ERRDOS,ERRbadpath);
3315 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3316 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3317 return UNIXERROR(ERRDOS,ERRbadpath);
3320 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3321 if (delete_pending) {
3322 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3326 nlink = sbuf.st_nlink;
3328 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3329 /* NTFS does not seem to count ".." */
3330 nlink -= 1;
3333 if ((nlink > 0) && delete_pending) {
3334 nlink -= 1;
3337 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3338 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3341 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3342 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3344 p = strrchr_m(fname,'/');
3345 if (!p)
3346 base_name = fname;
3347 else
3348 base_name = p+1;
3350 mode = dos_mode(conn,fname,&sbuf);
3351 if (!mode)
3352 mode = FILE_ATTRIBUTE_NORMAL;
3354 fullpathname = fname;
3355 if (!(mode & aDIR))
3356 file_size = get_file_size(sbuf);
3358 /* Pull out any data sent here before we realloc. */
3359 switch (info_level) {
3360 case SMB_INFO_QUERY_EAS_FROM_LIST:
3362 /* Pull any EA list from the data portion. */
3363 uint32 ea_size;
3365 if (total_data < 4) {
3366 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3368 ea_size = IVAL(pdata,0);
3370 if (total_data > 0 && ea_size != total_data) {
3371 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3372 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3373 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3376 if (!lp_ea_support(SNUM(conn))) {
3377 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3380 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3381 return ERROR_NT(NT_STATUS_NO_MEMORY);
3384 /* Pull out the list of names. */
3385 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3386 if (!ea_list) {
3387 talloc_destroy(data_ctx);
3388 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3390 break;
3393 case SMB_QUERY_POSIX_LOCK:
3395 if (fsp == NULL || fsp->fh->fd == -1) {
3396 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3399 if (total_data != POSIX_LOCK_DATA_SIZE) {
3400 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3403 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3404 return ERROR_NT(NT_STATUS_NO_MEMORY);
3407 /* Copy the lock range data. */
3408 lock_data = (char *)talloc_memdup(
3409 data_ctx, pdata, total_data);
3410 if (!lock_data) {
3411 talloc_destroy(data_ctx);
3412 return ERROR_NT(NT_STATUS_NO_MEMORY);
3415 default:
3416 break;
3419 *pparams = (char *)SMB_REALLOC(*pparams,2);
3420 if (*pparams == NULL) {
3421 talloc_destroy(data_ctx);
3422 return ERROR_NT(NT_STATUS_NO_MEMORY);
3424 params = *pparams;
3425 SSVAL(params,0,0);
3426 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3427 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3428 if (*ppdata == NULL ) {
3429 talloc_destroy(data_ctx);
3430 return ERROR_NT(NT_STATUS_NO_MEMORY);
3432 pdata = *ppdata;
3434 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3435 mtime_ts = get_mtimespec(&sbuf);
3436 atime_ts = get_atimespec(&sbuf);
3438 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3440 if (fsp) {
3441 if (!null_timespec(fsp->pending_modtime)) {
3442 /* the pending modtime overrides the current modtime */
3443 mtime_ts = fsp->pending_modtime;
3445 } else {
3446 /* Do we have this path open ? */
3447 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3448 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3449 /* the pending modtime overrides the current modtime */
3450 mtime_ts = fsp1->pending_modtime;
3452 if (fsp1 && fsp1->initial_allocation_size) {
3453 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3457 if (lp_dos_filetime_resolution(SNUM(conn))) {
3458 dos_filetime_timespec(&create_time_ts);
3459 dos_filetime_timespec(&mtime_ts);
3460 dos_filetime_timespec(&atime_ts);
3463 create_time = convert_timespec_to_time_t(create_time_ts);
3464 mtime = convert_timespec_to_time_t(mtime_ts);
3465 atime = convert_timespec_to_time_t(atime_ts);
3467 /* NT expects the name to be in an exact form of the *full*
3468 filename. See the trans2 torture test */
3469 if (strequal(base_name,".")) {
3470 pstrcpy(dos_fname, "\\");
3471 } else {
3472 pstr_sprintf(dos_fname, "\\%s", fname);
3473 string_replace(dos_fname, '/', '\\');
3476 switch (info_level) {
3477 case SMB_INFO_STANDARD:
3478 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3479 data_size = 22;
3480 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3481 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3482 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3483 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3484 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3485 SSVAL(pdata,l1_attrFile,mode);
3486 break;
3488 case SMB_INFO_QUERY_EA_SIZE:
3490 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3491 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3492 data_size = 26;
3493 srv_put_dos_date2(pdata,0,create_time);
3494 srv_put_dos_date2(pdata,4,atime);
3495 srv_put_dos_date2(pdata,8,mtime); /* write time */
3496 SIVAL(pdata,12,(uint32)file_size);
3497 SIVAL(pdata,16,(uint32)allocation_size);
3498 SSVAL(pdata,20,mode);
3499 SIVAL(pdata,22,ea_size);
3500 break;
3503 case SMB_INFO_IS_NAME_VALID:
3504 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3505 if (tran_call == TRANSACT2_QFILEINFO) {
3506 /* os/2 needs this ? really ?*/
3507 return ERROR_DOS(ERRDOS,ERRbadfunc);
3509 data_size = 0;
3510 param_size = 0;
3511 break;
3513 case SMB_INFO_QUERY_EAS_FROM_LIST:
3515 size_t total_ea_len = 0;
3516 struct ea_list *ea_file_list = NULL;
3518 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3520 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3521 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3523 if (!ea_list || (total_ea_len > data_size)) {
3524 talloc_destroy(data_ctx);
3525 data_size = 4;
3526 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3527 break;
3530 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3531 talloc_destroy(data_ctx);
3532 break;
3535 case SMB_INFO_QUERY_ALL_EAS:
3537 /* We have data_size bytes to put EA's into. */
3538 size_t total_ea_len = 0;
3540 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3542 data_ctx = talloc_init("ea_ctx");
3543 if (!data_ctx) {
3544 return ERROR_NT(NT_STATUS_NO_MEMORY);
3547 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3548 if (!ea_list || (total_ea_len > data_size)) {
3549 talloc_destroy(data_ctx);
3550 data_size = 4;
3551 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3552 break;
3555 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3556 talloc_destroy(data_ctx);
3557 break;
3560 case SMB_FILE_BASIC_INFORMATION:
3561 case SMB_QUERY_FILE_BASIC_INFO:
3563 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3564 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3565 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3566 } else {
3567 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3568 data_size = 40;
3569 SIVAL(pdata,36,0);
3571 put_long_date_timespec(pdata,create_time_ts);
3572 put_long_date_timespec(pdata+8,atime_ts);
3573 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3574 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3575 SIVAL(pdata,32,mode);
3577 DEBUG(5,("SMB_QFBI - "));
3578 DEBUG(5,("create: %s ", ctime(&create_time)));
3579 DEBUG(5,("access: %s ", ctime(&atime)));
3580 DEBUG(5,("write: %s ", ctime(&mtime)));
3581 DEBUG(5,("change: %s ", ctime(&mtime)));
3582 DEBUG(5,("mode: %x\n", mode));
3583 break;
3585 case SMB_FILE_STANDARD_INFORMATION:
3586 case SMB_QUERY_FILE_STANDARD_INFO:
3588 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3589 data_size = 24;
3590 SOFF_T(pdata,0,allocation_size);
3591 SOFF_T(pdata,8,file_size);
3592 SIVAL(pdata,16,nlink);
3593 SCVAL(pdata,20,delete_pending?1:0);
3594 SCVAL(pdata,21,(mode&aDIR)?1:0);
3595 SSVAL(pdata,22,0); /* Padding. */
3596 break;
3598 case SMB_FILE_EA_INFORMATION:
3599 case SMB_QUERY_FILE_EA_INFO:
3601 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3602 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3603 data_size = 4;
3604 SIVAL(pdata,0,ea_size);
3605 break;
3608 /* Get the 8.3 name - used if NT SMB was negotiated. */
3609 case SMB_QUERY_FILE_ALT_NAME_INFO:
3610 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3612 pstring short_name;
3614 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3615 pstrcpy(short_name,base_name);
3616 /* Mangle if not already 8.3 */
3617 if(!mangle_is_8_3(short_name, True, conn->params)) {
3618 mangle_map(short_name,True,True,conn->params);
3620 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3621 data_size = 4 + len;
3622 SIVAL(pdata,0,len);
3623 break;
3626 case SMB_QUERY_FILE_NAME_INFO:
3628 this must be *exactly* right for ACLs on mapped drives to work
3630 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3631 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3632 data_size = 4 + len;
3633 SIVAL(pdata,0,len);
3634 break;
3636 case SMB_FILE_ALLOCATION_INFORMATION:
3637 case SMB_QUERY_FILE_ALLOCATION_INFO:
3638 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3639 data_size = 8;
3640 SOFF_T(pdata,0,allocation_size);
3641 break;
3643 case SMB_FILE_END_OF_FILE_INFORMATION:
3644 case SMB_QUERY_FILE_END_OF_FILEINFO:
3645 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3646 data_size = 8;
3647 SOFF_T(pdata,0,file_size);
3648 break;
3650 case SMB_QUERY_FILE_ALL_INFO:
3651 case SMB_FILE_ALL_INFORMATION:
3653 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3654 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3655 put_long_date_timespec(pdata,create_time_ts);
3656 put_long_date_timespec(pdata+8,atime_ts);
3657 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3658 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3659 SIVAL(pdata,32,mode);
3660 SIVAL(pdata,36,0); /* padding. */
3661 pdata += 40;
3662 SOFF_T(pdata,0,allocation_size);
3663 SOFF_T(pdata,8,file_size);
3664 SIVAL(pdata,16,nlink);
3665 SCVAL(pdata,20,delete_pending);
3666 SCVAL(pdata,21,(mode&aDIR)?1:0);
3667 SSVAL(pdata,22,0);
3668 pdata += 24;
3669 SIVAL(pdata,0,ea_size);
3670 pdata += 4; /* EA info */
3671 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3672 SIVAL(pdata,0,len);
3673 pdata += 4 + len;
3674 data_size = PTR_DIFF(pdata,(*ppdata));
3675 break;
3677 case SMB_FILE_INTERNAL_INFORMATION:
3678 /* This should be an index number - looks like
3679 dev/ino to me :-)
3681 I think this causes us to fail the IFSKIT
3682 BasicFileInformationTest. -tpot */
3684 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3685 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3686 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3687 data_size = 8;
3688 break;
3690 case SMB_FILE_ACCESS_INFORMATION:
3691 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3692 SIVAL(pdata,0,access_mask);
3693 data_size = 4;
3694 break;
3696 case SMB_FILE_NAME_INFORMATION:
3697 /* Pathname with leading '\'. */
3699 size_t byte_len;
3700 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3701 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3702 SIVAL(pdata,0,byte_len);
3703 data_size = 4 + byte_len;
3704 break;
3707 case SMB_FILE_DISPOSITION_INFORMATION:
3708 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3709 data_size = 1;
3710 SCVAL(pdata,0,delete_pending);
3711 break;
3713 case SMB_FILE_POSITION_INFORMATION:
3714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3715 data_size = 8;
3716 SOFF_T(pdata,0,pos);
3717 break;
3719 case SMB_FILE_MODE_INFORMATION:
3720 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3721 SIVAL(pdata,0,mode);
3722 data_size = 4;
3723 break;
3725 case SMB_FILE_ALIGNMENT_INFORMATION:
3726 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3727 SIVAL(pdata,0,0); /* No alignment needed. */
3728 data_size = 4;
3729 break;
3731 #if 0
3733 * NT4 server just returns "invalid query" to this - if we try to answer
3734 * it then NTws gets a BSOD! (tridge).
3735 * W2K seems to want this. JRA.
3737 case SMB_QUERY_FILE_STREAM_INFO:
3738 #endif
3739 case SMB_FILE_STREAM_INFORMATION:
3740 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3741 if (mode & aDIR) {
3742 data_size = 0;
3743 } else {
3744 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3745 SIVAL(pdata,0,0); /* ??? */
3746 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3747 SOFF_T(pdata,8,file_size);
3748 SIVAL(pdata,16,allocation_size);
3749 SIVAL(pdata,20,0); /* ??? */
3750 data_size = 24 + byte_len;
3752 break;
3754 case SMB_QUERY_COMPRESSION_INFO:
3755 case SMB_FILE_COMPRESSION_INFORMATION:
3756 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3757 SOFF_T(pdata,0,file_size);
3758 SIVAL(pdata,8,0); /* ??? */
3759 SIVAL(pdata,12,0); /* ??? */
3760 data_size = 16;
3761 break;
3763 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3764 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3765 put_long_date_timespec(pdata,create_time_ts);
3766 put_long_date_timespec(pdata+8,atime_ts);
3767 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3768 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3769 SIVAL(pdata,32,allocation_size);
3770 SOFF_T(pdata,40,file_size);
3771 SIVAL(pdata,48,mode);
3772 SIVAL(pdata,52,0); /* ??? */
3773 data_size = 56;
3774 break;
3776 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3777 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3778 SIVAL(pdata,0,mode);
3779 SIVAL(pdata,4,0);
3780 data_size = 8;
3781 break;
3784 * CIFS UNIX Extensions.
3787 case SMB_QUERY_FILE_UNIX_BASIC:
3789 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3790 data_size = PTR_DIFF(pdata,(*ppdata));
3793 int i;
3794 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3796 for (i=0; i<100; i++)
3797 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3798 DEBUG(4,("\n"));
3801 break;
3803 case SMB_QUERY_FILE_UNIX_INFO2:
3805 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3806 data_size = PTR_DIFF(pdata,(*ppdata));
3809 int i;
3810 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3812 for (i=0; i<100; i++)
3813 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3814 DEBUG(4,("\n"));
3817 break;
3819 case SMB_QUERY_FILE_UNIX_LINK:
3821 pstring buffer;
3823 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3824 #ifdef S_ISLNK
3825 if(!S_ISLNK(sbuf.st_mode))
3826 return(UNIXERROR(ERRSRV,ERRbadlink));
3827 #else
3828 return(UNIXERROR(ERRDOS,ERRbadlink));
3829 #endif
3830 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3831 if (len == -1)
3832 return(UNIXERROR(ERRDOS,ERRnoaccess));
3833 buffer[len] = 0;
3834 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3835 pdata += len;
3836 data_size = PTR_DIFF(pdata,(*ppdata));
3838 break;
3841 #if defined(HAVE_POSIX_ACLS)
3842 case SMB_QUERY_POSIX_ACL:
3844 SMB_ACL_T file_acl = NULL;
3845 SMB_ACL_T def_acl = NULL;
3846 uint16 num_file_acls = 0;
3847 uint16 num_def_acls = 0;
3849 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3850 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3851 } else {
3852 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3855 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3856 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3857 fname ));
3858 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3861 if (S_ISDIR(sbuf.st_mode)) {
3862 if (fsp && fsp->is_directory) {
3863 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3864 } else {
3865 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3867 def_acl = free_empty_sys_acl(conn, def_acl);
3870 num_file_acls = count_acl_entries(conn, file_acl);
3871 num_def_acls = count_acl_entries(conn, def_acl);
3873 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3874 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3875 data_size,
3876 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3877 SMB_POSIX_ACL_HEADER_SIZE) ));
3878 if (file_acl) {
3879 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3881 if (def_acl) {
3882 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3884 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3887 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3888 SSVAL(pdata,2,num_file_acls);
3889 SSVAL(pdata,4,num_def_acls);
3890 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3891 if (file_acl) {
3892 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3894 if (def_acl) {
3895 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3897 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3899 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3900 if (file_acl) {
3901 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3903 if (def_acl) {
3904 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3906 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3909 if (file_acl) {
3910 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3912 if (def_acl) {
3913 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3915 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3916 break;
3918 #endif
3921 case SMB_QUERY_POSIX_LOCK:
3923 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3924 SMB_BIG_UINT count;
3925 SMB_BIG_UINT offset;
3926 uint32 lock_pid;
3927 enum brl_type lock_type;
3929 if (total_data != POSIX_LOCK_DATA_SIZE) {
3930 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3933 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3934 case POSIX_LOCK_TYPE_READ:
3935 lock_type = READ_LOCK;
3936 break;
3937 case POSIX_LOCK_TYPE_WRITE:
3938 lock_type = WRITE_LOCK;
3939 break;
3940 case POSIX_LOCK_TYPE_UNLOCK:
3941 default:
3942 /* There's no point in asking for an unlock... */
3943 talloc_destroy(data_ctx);
3944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3947 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3948 #if defined(HAVE_LONGLONG)
3949 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3950 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3951 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3952 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3953 #else /* HAVE_LONGLONG */
3954 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3955 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3956 #endif /* HAVE_LONGLONG */
3958 status = query_lock(fsp,
3959 &lock_pid,
3960 &count,
3961 &offset,
3962 &lock_type,
3963 POSIX_LOCK);
3965 if (ERROR_WAS_LOCK_DENIED(status)) {
3966 /* Here we need to report who has it locked... */
3967 data_size = POSIX_LOCK_DATA_SIZE;
3969 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3970 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3971 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3972 #if defined(HAVE_LONGLONG)
3973 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3974 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3975 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3976 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3977 #else /* HAVE_LONGLONG */
3978 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3979 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3980 #endif /* HAVE_LONGLONG */
3982 } else if (NT_STATUS_IS_OK(status)) {
3983 /* For success we just return a copy of what we sent
3984 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3985 data_size = POSIX_LOCK_DATA_SIZE;
3986 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3987 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3988 } else {
3989 return ERROR_NT(status);
3991 break;
3994 default:
3995 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3998 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4000 return(-1);
4003 /****************************************************************************
4004 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4005 code.
4006 ****************************************************************************/
4008 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4010 SMB_STRUCT_STAT sbuf1, sbuf2;
4011 pstring last_component_oldname;
4012 pstring last_component_newname;
4013 NTSTATUS status = NT_STATUS_OK;
4015 ZERO_STRUCT(sbuf1);
4016 ZERO_STRUCT(sbuf2);
4018 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4019 if (!NT_STATUS_IS_OK(status)) {
4020 return status;
4023 status = check_name(conn, oldname);
4024 if (!NT_STATUS_IS_OK(status)) {
4025 return status;
4028 /* source must already exist. */
4029 if (!VALID_STAT(sbuf1)) {
4030 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4033 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4034 if (!NT_STATUS_IS_OK(status)) {
4035 return status;
4038 status = check_name(conn, newname);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 return status;
4043 /* Disallow if newname already exists. */
4044 if (VALID_STAT(sbuf2)) {
4045 return NT_STATUS_OBJECT_NAME_COLLISION;
4048 /* No links from a directory. */
4049 if (S_ISDIR(sbuf1.st_mode)) {
4050 return NT_STATUS_FILE_IS_A_DIRECTORY;
4053 /* Ensure this is within the share. */
4054 status = reduce_name(conn, oldname);
4055 if (!NT_STATUS_IS_OK(status)) {
4056 return status;
4059 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4061 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4062 status = map_nt_error_from_unix(errno);
4063 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4064 nt_errstr(status), newname, oldname));
4067 return status;
4070 /****************************************************************************
4071 Deal with setting the time from any of the setfilepathinfo functions.
4072 ****************************************************************************/
4074 static NTSTATUS smb_set_file_time(connection_struct *conn,
4075 files_struct *fsp,
4076 const char *fname,
4077 const SMB_STRUCT_STAT *psbuf,
4078 struct timespec ts[2])
4080 uint32 action =
4081 FILE_NOTIFY_CHANGE_LAST_ACCESS
4082 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4085 if (!VALID_STAT(*psbuf)) {
4086 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4089 /* get some defaults (no modifications) if any info is zero or -1. */
4090 if (null_timespec(ts[0])) {
4091 ts[0] = get_atimespec(psbuf);
4092 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4095 if (null_timespec(ts[1])) {
4096 ts[1] = get_mtimespec(psbuf);
4097 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4100 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4101 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4104 * Try and set the times of this file if
4105 * they are different from the current values.
4109 struct timespec mts = get_mtimespec(psbuf);
4110 struct timespec ats = get_atimespec(psbuf);
4111 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4112 return NT_STATUS_OK;
4116 if(fsp != NULL) {
4118 * This was a setfileinfo on an open file.
4119 * NT does this a lot. We also need to
4120 * set the time here, as it can be read by
4121 * FindFirst/FindNext and with the patch for bug #2045
4122 * in smbd/fileio.c it ensures that this timestamp is
4123 * kept sticky even after a write. We save the request
4124 * away and will set it on file close and after a write. JRA.
4127 if (!null_timespec(ts[1])) {
4128 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4129 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4130 fsp_set_pending_modtime(fsp, ts[1]);
4134 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4136 if(file_ntimes(conn, fname, ts)!=0) {
4137 return map_nt_error_from_unix(errno);
4139 if (action != 0) {
4140 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4142 return NT_STATUS_OK;
4145 /****************************************************************************
4146 Deal with setting the dosmode from any of the setfilepathinfo functions.
4147 ****************************************************************************/
4149 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4150 const char *fname,
4151 SMB_STRUCT_STAT *psbuf,
4152 uint32 dosmode)
4154 if (!VALID_STAT(*psbuf)) {
4155 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4158 if (dosmode) {
4159 if (S_ISDIR(psbuf->st_mode)) {
4160 dosmode |= aDIR;
4161 } else {
4162 dosmode &= ~aDIR;
4166 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4168 /* check the mode isn't different, before changing it */
4169 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4171 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4172 fname, (unsigned int)dosmode ));
4174 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4175 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4176 fname, strerror(errno)));
4177 return map_nt_error_from_unix(errno);
4180 return NT_STATUS_OK;
4183 /****************************************************************************
4184 Deal with setting the size from any of the setfilepathinfo functions.
4185 ****************************************************************************/
4187 static NTSTATUS smb_set_file_size(connection_struct *conn,
4188 files_struct *fsp,
4189 const char *fname,
4190 SMB_STRUCT_STAT *psbuf,
4191 SMB_OFF_T size)
4193 NTSTATUS status = NT_STATUS_OK;
4194 files_struct *new_fsp = NULL;
4196 if (!VALID_STAT(*psbuf)) {
4197 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4200 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4202 if (size == get_file_size(*psbuf)) {
4203 return NT_STATUS_OK;
4206 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4207 fname, (double)size ));
4209 if (fsp && fsp->fh->fd != -1) {
4210 /* Handle based call. */
4211 if (vfs_set_filelen(fsp, size) == -1) {
4212 return map_nt_error_from_unix(errno);
4214 return NT_STATUS_OK;
4217 status = open_file_ntcreate(conn, fname, psbuf,
4218 FILE_WRITE_DATA,
4219 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4220 FILE_OPEN,
4222 FILE_ATTRIBUTE_NORMAL,
4223 FORCE_OPLOCK_BREAK_TO_NONE,
4224 NULL, &new_fsp);
4226 if (!NT_STATUS_IS_OK(status)) {
4227 /* NB. We check for open_was_deferred in the caller. */
4228 return status;
4231 if (vfs_set_filelen(new_fsp, size) == -1) {
4232 status = map_nt_error_from_unix(errno);
4233 close_file(new_fsp,NORMAL_CLOSE);
4234 return status;
4237 close_file(new_fsp,NORMAL_CLOSE);
4238 return NT_STATUS_OK;
4241 /****************************************************************************
4242 Deal with SMB_INFO_SET_EA.
4243 ****************************************************************************/
4245 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4246 const char *pdata,
4247 int total_data,
4248 files_struct *fsp,
4249 const char *fname)
4251 struct ea_list *ea_list = NULL;
4252 TALLOC_CTX *ctx = NULL;
4253 NTSTATUS status = NT_STATUS_OK;
4255 if (total_data < 10) {
4257 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4258 length. They seem to have no effect. Bug #3212. JRA */
4260 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4261 /* We're done. We only get EA info in this call. */
4262 return NT_STATUS_OK;
4265 return NT_STATUS_INVALID_PARAMETER;
4268 if (IVAL(pdata,0) > total_data) {
4269 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4270 IVAL(pdata,0), (unsigned int)total_data));
4271 return NT_STATUS_INVALID_PARAMETER;
4274 ctx = talloc_init("SMB_INFO_SET_EA");
4275 if (!ctx) {
4276 return NT_STATUS_NO_MEMORY;
4278 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4279 if (!ea_list) {
4280 talloc_destroy(ctx);
4281 return NT_STATUS_INVALID_PARAMETER;
4283 status = set_ea(conn, fsp, fname, ea_list);
4284 talloc_destroy(ctx);
4286 return status;
4289 /****************************************************************************
4290 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4291 ****************************************************************************/
4293 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4294 const char *pdata,
4295 int total_data,
4296 files_struct *fsp,
4297 const char *fname,
4298 SMB_STRUCT_STAT *psbuf)
4300 NTSTATUS status = NT_STATUS_OK;
4301 BOOL delete_on_close;
4302 uint32 dosmode = 0;
4304 if (total_data < 1) {
4305 return NT_STATUS_INVALID_PARAMETER;
4308 if (fsp == NULL) {
4309 return NT_STATUS_INVALID_HANDLE;
4312 delete_on_close = (CVAL(pdata,0) ? True : False);
4313 dosmode = dos_mode(conn, fname, psbuf);
4315 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4316 "delete_on_close = %u\n",
4317 fsp->fsp_name,
4318 (unsigned int)dosmode,
4319 (unsigned int)delete_on_close ));
4321 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4323 if (!NT_STATUS_IS_OK(status)) {
4324 return status;
4327 /* The set is across all open files on this dev/inode pair. */
4328 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4329 return NT_STATUS_ACCESS_DENIED;
4331 return NT_STATUS_OK;
4334 /****************************************************************************
4335 Deal with SMB_FILE_POSITION_INFORMATION.
4336 ****************************************************************************/
4338 static NTSTATUS smb_file_position_information(connection_struct *conn,
4339 const char *pdata,
4340 int total_data,
4341 files_struct *fsp)
4343 SMB_BIG_UINT position_information;
4345 if (total_data < 8) {
4346 return NT_STATUS_INVALID_PARAMETER;
4349 if (fsp == NULL) {
4350 /* Ignore on pathname based set. */
4351 return NT_STATUS_OK;
4354 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4355 #ifdef LARGE_SMB_OFF_T
4356 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4357 #else /* LARGE_SMB_OFF_T */
4358 if (IVAL(pdata,4) != 0) {
4359 /* more than 32 bits? */
4360 return NT_STATUS_INVALID_PARAMETER;
4362 #endif /* LARGE_SMB_OFF_T */
4364 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4365 fsp->fsp_name, (double)position_information ));
4366 fsp->fh->position_information = position_information;
4367 return NT_STATUS_OK;
4370 /****************************************************************************
4371 Deal with SMB_FILE_MODE_INFORMATION.
4372 ****************************************************************************/
4374 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4375 const char *pdata,
4376 int total_data)
4378 uint32 mode;
4380 if (total_data < 4) {
4381 return NT_STATUS_INVALID_PARAMETER;
4383 mode = IVAL(pdata,0);
4384 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4385 return NT_STATUS_INVALID_PARAMETER;
4387 return NT_STATUS_OK;
4390 /****************************************************************************
4391 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4392 ****************************************************************************/
4394 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4395 char *inbuf,
4396 const char *pdata,
4397 int total_data,
4398 const char *fname)
4400 pstring link_target;
4401 const char *newname = fname;
4402 NTSTATUS status = NT_STATUS_OK;
4404 /* Set a symbolic link. */
4405 /* Don't allow this if follow links is false. */
4407 if (total_data == 0) {
4408 return NT_STATUS_INVALID_PARAMETER;
4411 if (!lp_symlinks(SNUM(conn))) {
4412 return NT_STATUS_ACCESS_DENIED;
4415 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4417 /* !widelinks forces the target path to be within the share. */
4418 /* This means we can interpret the target as a pathname. */
4419 if (!lp_widelinks(SNUM(conn))) {
4420 pstring rel_name;
4421 char *last_dirp = NULL;
4423 if (*link_target == '/') {
4424 /* No absolute paths allowed. */
4425 return NT_STATUS_ACCESS_DENIED;
4427 pstrcpy(rel_name, newname);
4428 last_dirp = strrchr_m(rel_name, '/');
4429 if (last_dirp) {
4430 last_dirp[1] = '\0';
4431 } else {
4432 pstrcpy(rel_name, "./");
4434 pstrcat(rel_name, link_target);
4436 status = check_name(conn, rel_name);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 return status;
4442 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4443 newname, link_target ));
4445 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4446 return map_nt_error_from_unix(errno);
4449 return NT_STATUS_OK;
4452 /****************************************************************************
4453 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4454 ****************************************************************************/
4456 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4457 char *inbuf,
4458 char *outbuf,
4459 const char *pdata,
4460 int total_data,
4461 pstring fname)
4463 pstring oldname;
4464 NTSTATUS status = NT_STATUS_OK;
4466 /* Set a hard link. */
4467 if (total_data == 0) {
4468 return NT_STATUS_INVALID_PARAMETER;
4471 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4472 if (!NT_STATUS_IS_OK(status)) {
4473 return status;
4476 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4477 if (!NT_STATUS_IS_OK(status)) {
4478 return status;
4481 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4482 fname, oldname));
4484 return hardlink_internals(conn, oldname, fname);
4487 /****************************************************************************
4488 Deal with SMB_FILE_RENAME_INFORMATION.
4489 ****************************************************************************/
4491 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4492 char *inbuf,
4493 char *outbuf,
4494 const char *pdata,
4495 int total_data,
4496 files_struct *fsp,
4497 pstring fname)
4499 BOOL overwrite;
4500 /* uint32 root_fid; */ /* Not used */
4501 uint32 len;
4502 pstring newname;
4503 pstring base_name;
4504 BOOL dest_has_wcard = False;
4505 NTSTATUS status = NT_STATUS_OK;
4506 char *p;
4508 if (total_data < 13) {
4509 return NT_STATUS_INVALID_PARAMETER;
4512 overwrite = (CVAL(pdata,0) ? True : False);
4513 /* root_fid = IVAL(pdata,4); */
4514 len = IVAL(pdata,8);
4516 if (len > (total_data - 12) || (len == 0)) {
4517 return NT_STATUS_INVALID_PARAMETER;
4520 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4521 if (!NT_STATUS_IS_OK(status)) {
4522 return status;
4525 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 return status;
4530 /* Check the new name has no '/' characters. */
4531 if (strchr_m(newname, '/')) {
4532 return NT_STATUS_NOT_SUPPORTED;
4535 /* Create the base directory. */
4536 pstrcpy(base_name, fname);
4537 p = strrchr_m(base_name, '/');
4538 if (p) {
4539 *p = '\0';
4541 /* Append the new name. */
4542 pstrcat(base_name, "/");
4543 pstrcat(base_name, newname);
4545 if (fsp) {
4546 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4547 fsp->fnum, fsp->fsp_name, base_name ));
4548 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4549 } else {
4550 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4551 fname, newname ));
4552 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4555 return status;
4558 /****************************************************************************
4559 Deal with SMB_SET_POSIX_ACL.
4560 ****************************************************************************/
4562 #if defined(HAVE_POSIX_ACLS)
4563 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4564 const char *pdata,
4565 int total_data,
4566 files_struct *fsp,
4567 const char *fname,
4568 SMB_STRUCT_STAT *psbuf)
4570 uint16 posix_acl_version;
4571 uint16 num_file_acls;
4572 uint16 num_def_acls;
4573 BOOL valid_file_acls = True;
4574 BOOL valid_def_acls = True;
4576 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4577 return NT_STATUS_INVALID_PARAMETER;
4579 posix_acl_version = SVAL(pdata,0);
4580 num_file_acls = SVAL(pdata,2);
4581 num_def_acls = SVAL(pdata,4);
4583 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4584 valid_file_acls = False;
4585 num_file_acls = 0;
4588 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4589 valid_def_acls = False;
4590 num_def_acls = 0;
4593 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4594 return NT_STATUS_INVALID_PARAMETER;
4597 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4598 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4599 return NT_STATUS_INVALID_PARAMETER;
4602 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4603 fname ? fname : fsp->fsp_name,
4604 (unsigned int)num_file_acls,
4605 (unsigned int)num_def_acls));
4607 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4608 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4609 return map_nt_error_from_unix(errno);
4612 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4613 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4614 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4615 return map_nt_error_from_unix(errno);
4617 return NT_STATUS_OK;
4619 #endif
4621 /****************************************************************************
4622 Deal with SMB_SET_POSIX_LOCK.
4623 ****************************************************************************/
4625 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4626 char *inbuf,
4627 int length,
4628 const char *pdata,
4629 int total_data,
4630 files_struct *fsp)
4632 SMB_BIG_UINT count;
4633 SMB_BIG_UINT offset;
4634 uint32 lock_pid;
4635 BOOL blocking_lock = False;
4636 enum brl_type lock_type;
4637 NTSTATUS status = NT_STATUS_OK;
4639 if (fsp == NULL || fsp->fh->fd == -1) {
4640 return NT_STATUS_INVALID_HANDLE;
4643 if (total_data != POSIX_LOCK_DATA_SIZE) {
4644 return NT_STATUS_INVALID_PARAMETER;
4647 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4648 case POSIX_LOCK_TYPE_READ:
4649 lock_type = READ_LOCK;
4650 break;
4651 case POSIX_LOCK_TYPE_WRITE:
4652 /* Return the right POSIX-mappable error code for files opened read-only. */
4653 if (!fsp->can_write) {
4654 return NT_STATUS_INVALID_HANDLE;
4656 lock_type = WRITE_LOCK;
4657 break;
4658 case POSIX_LOCK_TYPE_UNLOCK:
4659 lock_type = UNLOCK_LOCK;
4660 break;
4661 default:
4662 return NT_STATUS_INVALID_PARAMETER;
4665 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4666 blocking_lock = False;
4667 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4668 blocking_lock = True;
4669 } else {
4670 return NT_STATUS_INVALID_PARAMETER;
4673 if (!lp_blocking_locks(SNUM(conn))) {
4674 blocking_lock = False;
4677 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4678 #if defined(HAVE_LONGLONG)
4679 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4680 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4681 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4682 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4683 #else /* HAVE_LONGLONG */
4684 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4685 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4686 #endif /* HAVE_LONGLONG */
4688 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4689 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4690 fsp->fsp_name,
4691 (unsigned int)lock_type,
4692 (unsigned int)lock_pid,
4693 (double)count,
4694 (double)offset ));
4696 if (lock_type == UNLOCK_LOCK) {
4697 status = do_unlock(fsp,
4698 lock_pid,
4699 count,
4700 offset,
4701 POSIX_LOCK);
4702 } else {
4703 struct byte_range_lock *br_lck = do_lock(fsp,
4704 lock_pid,
4705 count,
4706 offset,
4707 lock_type,
4708 POSIX_LOCK,
4709 blocking_lock,
4710 &status);
4712 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4714 * A blocking lock was requested. Package up
4715 * this smb into a queued request and push it
4716 * onto the blocking lock queue.
4718 if(push_blocking_lock_request(br_lck,
4719 inbuf, length,
4720 fsp,
4721 -1, /* infinite timeout. */
4723 lock_pid,
4724 lock_type,
4725 POSIX_LOCK,
4726 offset,
4727 count)) {
4728 TALLOC_FREE(br_lck);
4729 return status;
4732 TALLOC_FREE(br_lck);
4735 return status;
4738 /****************************************************************************
4739 Deal with SMB_INFO_STANDARD.
4740 ****************************************************************************/
4742 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4743 const char *pdata,
4744 int total_data,
4745 files_struct *fsp,
4746 const char *fname,
4747 const SMB_STRUCT_STAT *psbuf)
4749 struct timespec ts[2];
4751 if (total_data < 12) {
4752 return NT_STATUS_INVALID_PARAMETER;
4755 /* access time */
4756 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4757 /* write time */
4758 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4760 DEBUG(10,("smb_set_info_standard: file %s\n",
4761 fname ? fname : fsp->fsp_name ));
4763 return smb_set_file_time(conn,
4764 fsp,
4765 fname,
4766 psbuf,
4767 ts);
4770 /****************************************************************************
4771 Deal with SMB_SET_FILE_BASIC_INFO.
4772 ****************************************************************************/
4774 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4775 const char *pdata,
4776 int total_data,
4777 files_struct *fsp,
4778 const char *fname,
4779 SMB_STRUCT_STAT *psbuf)
4781 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4782 struct timespec write_time;
4783 struct timespec changed_time;
4784 uint32 dosmode = 0;
4785 struct timespec ts[2];
4786 NTSTATUS status = NT_STATUS_OK;
4788 if (total_data < 36) {
4789 return NT_STATUS_INVALID_PARAMETER;
4792 /* Set the attributes */
4793 dosmode = IVAL(pdata,32);
4794 status = smb_set_file_dosmode(conn,
4795 fname,
4796 psbuf,
4797 dosmode);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 return status;
4802 /* Ignore create time at offset pdata. */
4804 /* access time */
4805 ts[0] = interpret_long_date(pdata+8);
4807 write_time = interpret_long_date(pdata+16);
4808 changed_time = interpret_long_date(pdata+24);
4810 /* mtime */
4811 ts[1] = timespec_min(&write_time, &changed_time);
4813 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4814 ts[1] = write_time;
4817 /* Prefer a defined time to an undefined one. */
4818 if (null_timespec(ts[1])) {
4819 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4822 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4823 fname ? fname : fsp->fsp_name ));
4825 return smb_set_file_time(conn,
4826 fsp,
4827 fname,
4828 psbuf,
4829 ts);
4832 /****************************************************************************
4833 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4834 ****************************************************************************/
4836 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4837 const char *pdata,
4838 int total_data,
4839 files_struct *fsp,
4840 const char *fname,
4841 SMB_STRUCT_STAT *psbuf)
4843 SMB_BIG_UINT allocation_size = 0;
4844 NTSTATUS status = NT_STATUS_OK;
4845 files_struct *new_fsp = NULL;
4847 if (!VALID_STAT(*psbuf)) {
4848 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4851 if (total_data < 8) {
4852 return NT_STATUS_INVALID_PARAMETER;
4855 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4856 #ifdef LARGE_SMB_OFF_T
4857 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4858 #else /* LARGE_SMB_OFF_T */
4859 if (IVAL(pdata,4) != 0) {
4860 /* more than 32 bits? */
4861 return NT_STATUS_INVALID_PARAMETER;
4863 #endif /* LARGE_SMB_OFF_T */
4865 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4866 fname, (double)allocation_size ));
4868 if (allocation_size) {
4869 allocation_size = smb_roundup(conn, allocation_size);
4872 if(allocation_size == get_file_size(*psbuf)) {
4873 return NT_STATUS_OK;
4876 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4877 fname, (double)allocation_size ));
4879 if (fsp && fsp->fh->fd != -1) {
4880 /* Open file handle. */
4881 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4882 return map_nt_error_from_unix(errno);
4884 return NT_STATUS_OK;
4887 /* Pathname or stat or directory file. */
4889 status = open_file_ntcreate(conn, fname, psbuf,
4890 FILE_WRITE_DATA,
4891 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4892 FILE_OPEN,
4894 FILE_ATTRIBUTE_NORMAL,
4895 FORCE_OPLOCK_BREAK_TO_NONE,
4896 NULL, &new_fsp);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 /* NB. We check for open_was_deferred in the caller. */
4900 return status;
4902 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4903 status = map_nt_error_from_unix(errno);
4904 close_file(new_fsp,NORMAL_CLOSE);
4905 return status;
4908 close_file(new_fsp,NORMAL_CLOSE);
4909 return NT_STATUS_OK;
4912 /****************************************************************************
4913 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4914 ****************************************************************************/
4916 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4917 const char *pdata,
4918 int total_data,
4919 files_struct *fsp,
4920 const char *fname,
4921 SMB_STRUCT_STAT *psbuf)
4923 SMB_OFF_T size;
4925 if (total_data < 8) {
4926 return NT_STATUS_INVALID_PARAMETER;
4929 size = IVAL(pdata,0);
4930 #ifdef LARGE_SMB_OFF_T
4931 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4932 #else /* LARGE_SMB_OFF_T */
4933 if (IVAL(pdata,4) != 0) {
4934 /* more than 32 bits? */
4935 return NT_STATUS_INVALID_PARAMETER;
4937 #endif /* LARGE_SMB_OFF_T */
4938 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4939 "file %s to %.0f\n", fname, (double)size ));
4941 return smb_set_file_size(conn,
4942 fsp,
4943 fname,
4944 psbuf,
4945 size);
4948 /****************************************************************************
4949 Allow a UNIX info mknod.
4950 ****************************************************************************/
4952 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4953 const char *pdata,
4954 int total_data,
4955 const char *fname,
4956 SMB_STRUCT_STAT *psbuf)
4958 uint32 file_type = IVAL(pdata,56);
4959 #if defined(HAVE_MAKEDEV)
4960 uint32 dev_major = IVAL(pdata,60);
4961 uint32 dev_minor = IVAL(pdata,68);
4962 #endif
4963 SMB_DEV_T dev = (SMB_DEV_T)0;
4964 uint32 raw_unixmode = IVAL(pdata,84);
4965 NTSTATUS status;
4966 mode_t unixmode;
4968 if (total_data < 100) {
4969 return NT_STATUS_INVALID_PARAMETER;
4972 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 return status;
4977 #if defined(HAVE_MAKEDEV)
4978 dev = makedev(dev_major, dev_minor);
4979 #endif
4981 switch (file_type) {
4982 #if defined(S_IFIFO)
4983 case UNIX_TYPE_FIFO:
4984 unixmode |= S_IFIFO;
4985 break;
4986 #endif
4987 #if defined(S_IFSOCK)
4988 case UNIX_TYPE_SOCKET:
4989 unixmode |= S_IFSOCK;
4990 break;
4991 #endif
4992 #if defined(S_IFCHR)
4993 case UNIX_TYPE_CHARDEV:
4994 unixmode |= S_IFCHR;
4995 break;
4996 #endif
4997 #if defined(S_IFBLK)
4998 case UNIX_TYPE_BLKDEV:
4999 unixmode |= S_IFBLK;
5000 break;
5001 #endif
5002 default:
5003 return NT_STATUS_INVALID_PARAMETER;
5006 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5007 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5009 /* Ok - do the mknod. */
5010 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5011 return map_nt_error_from_unix(errno);
5014 /* If any of the other "set" calls fail we
5015 * don't want to end up with a half-constructed mknod.
5018 if (lp_inherit_perms(SNUM(conn))) {
5019 inherit_access_acl(
5020 conn, parent_dirname(fname),
5021 fname, unixmode);
5024 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5025 status = map_nt_error_from_unix(errno);
5026 SMB_VFS_UNLINK(conn,fname);
5027 return status;
5029 return NT_STATUS_OK;
5032 /****************************************************************************
5033 Deal with SMB_SET_FILE_UNIX_BASIC.
5034 ****************************************************************************/
5036 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5037 const char *pdata,
5038 int total_data,
5039 files_struct *fsp,
5040 const char *fname,
5041 SMB_STRUCT_STAT *psbuf)
5043 struct timespec ts[2];
5044 uint32 raw_unixmode;
5045 mode_t unixmode;
5046 SMB_OFF_T size = 0;
5047 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5048 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5049 NTSTATUS status = NT_STATUS_OK;
5050 BOOL delete_on_fail = False;
5051 enum perm_type ptype;
5053 if (total_data < 100) {
5054 return NT_STATUS_INVALID_PARAMETER;
5057 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5058 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5059 size=IVAL(pdata,0); /* first 8 Bytes are size */
5060 #ifdef LARGE_SMB_OFF_T
5061 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5062 #else /* LARGE_SMB_OFF_T */
5063 if (IVAL(pdata,4) != 0) {
5064 /* more than 32 bits? */
5065 return NT_STATUS_INVALID_PARAMETER;
5067 #endif /* LARGE_SMB_OFF_T */
5070 ts[0] = interpret_long_date(pdata+24); /* access_time */
5071 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5072 set_owner = (uid_t)IVAL(pdata,40);
5073 set_grp = (gid_t)IVAL(pdata,48);
5074 raw_unixmode = IVAL(pdata,84);
5076 if (VALID_STAT(*psbuf)) {
5077 if (S_ISDIR(psbuf->st_mode)) {
5078 ptype = PERM_EXISTING_DIR;
5079 } else {
5080 ptype = PERM_EXISTING_FILE;
5082 } else {
5083 ptype = PERM_NEW_FILE;
5086 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5087 if (!NT_STATUS_IS_OK(status)) {
5088 return status;
5091 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5092 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5093 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5095 if (!VALID_STAT(*psbuf)) {
5097 * The only valid use of this is to create character and block
5098 * devices, and named pipes. This is deprecated (IMHO) and
5099 * a new info level should be used for mknod. JRA.
5102 status = smb_unix_mknod(conn,
5103 pdata,
5104 total_data,
5105 fname,
5106 psbuf);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 return status;
5111 /* Ensure we don't try and change anything else. */
5112 raw_unixmode = SMB_MODE_NO_CHANGE;
5113 size = get_file_size(*psbuf);
5114 ts[0] = get_atimespec(psbuf);
5115 ts[1] = get_mtimespec(psbuf);
5117 * We continue here as we might want to change the
5118 * owner uid/gid.
5120 delete_on_fail = True;
5123 #if 1
5124 /* Horrible backwards compatibility hack as an old server bug
5125 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5126 * */
5128 if (!size) {
5129 size = get_file_size(*psbuf);
5131 #endif
5134 * Deal with the UNIX specific mode set.
5137 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5138 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5139 (unsigned int)unixmode, fname ));
5140 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5141 return map_nt_error_from_unix(errno);
5146 * Deal with the UNIX specific uid set.
5149 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5150 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5151 (unsigned int)set_owner, fname ));
5152 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5153 status = map_nt_error_from_unix(errno);
5154 if (delete_on_fail) {
5155 SMB_VFS_UNLINK(conn,fname);
5157 return status;
5162 * Deal with the UNIX specific gid set.
5165 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5166 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5167 (unsigned int)set_owner, fname ));
5168 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5169 status = map_nt_error_from_unix(errno);
5170 if (delete_on_fail) {
5171 SMB_VFS_UNLINK(conn,fname);
5173 return status;
5177 /* Deal with any size changes. */
5179 status = smb_set_file_size(conn,
5180 fsp,
5181 fname,
5182 psbuf,
5183 size);
5184 if (!NT_STATUS_IS_OK(status)) {
5185 return status;
5188 /* Deal with any time changes. */
5190 return smb_set_file_time(conn,
5191 fsp,
5192 fname,
5193 psbuf,
5194 ts);
5197 /****************************************************************************
5198 Deal with SMB_SET_FILE_UNIX_INFO2.
5199 ****************************************************************************/
5201 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5202 const char *pdata,
5203 int total_data,
5204 files_struct *fsp,
5205 const char *fname,
5206 SMB_STRUCT_STAT *psbuf)
5208 NTSTATUS status;
5209 uint32 smb_fflags;
5210 uint32 smb_fmask;
5212 if (total_data < 116) {
5213 return NT_STATUS_INVALID_PARAMETER;
5216 /* Start by setting all the fields that are common between UNIX_BASIC
5217 * and UNIX_INFO2.
5219 status = smb_set_file_unix_basic(conn, pdata, total_data,
5220 fsp, fname, psbuf);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 return status;
5225 smb_fflags = IVAL(pdata, 108);
5226 smb_fmask = IVAL(pdata, 112);
5228 /* NB: We should only attempt to alter the file flags if the client
5229 * sends a non-zero mask.
5231 if (smb_fmask != 0) {
5232 int stat_fflags = 0;
5234 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5235 &stat_fflags)) {
5236 /* Client asked to alter a flag we don't understand. */
5237 return NT_STATUS_INVALID_PARAMETER;
5240 if (fsp && fsp->fh->fd != -1) {
5241 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5242 return NT_STATUS_NOT_SUPPORTED;
5243 } else {
5244 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5245 return map_nt_error_from_unix(errno);
5250 /* XXX: need to add support for changing the create_time here. You
5251 * can do this for paths on Darwin with setattrlist(2). The right way
5252 * to hook this up is probably by extending the VFS utimes interface.
5255 return NT_STATUS_OK;
5258 /****************************************************************************
5259 Create a directory with POSIX semantics.
5260 ****************************************************************************/
5262 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5263 char **ppdata,
5264 int total_data,
5265 const char *fname,
5266 SMB_STRUCT_STAT *psbuf,
5267 int *pdata_return_size)
5269 NTSTATUS status = NT_STATUS_OK;
5270 uint32 raw_unixmode = 0;
5271 uint32 mod_unixmode = 0;
5272 mode_t unixmode = (mode_t)0;
5273 files_struct *fsp = NULL;
5274 uint16 info_level_return = 0;
5275 int info;
5276 char *pdata = *ppdata;
5278 if (total_data < 18) {
5279 return NT_STATUS_INVALID_PARAMETER;
5282 raw_unixmode = IVAL(pdata,8);
5283 /* Next 4 bytes are not yet defined. */
5285 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5286 if (!NT_STATUS_IS_OK(status)) {
5287 return status;
5290 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5292 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5293 fname, (unsigned int)unixmode ));
5295 status = open_directory(conn,
5296 fname,
5297 psbuf,
5298 FILE_READ_ATTRIBUTES, /* Just a stat open */
5299 FILE_SHARE_NONE, /* Ignored for stat opens */
5300 FILE_CREATE,
5302 mod_unixmode,
5303 &info,
5304 &fsp);
5306 if (NT_STATUS_IS_OK(status)) {
5307 close_file(fsp, NORMAL_CLOSE);
5310 info_level_return = SVAL(pdata,16);
5312 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5313 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5314 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5315 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5316 } else {
5317 *pdata_return_size = 12;
5320 /* Realloc the data size */
5321 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5322 if (*ppdata == NULL) {
5323 *pdata_return_size = 0;
5324 return NT_STATUS_NO_MEMORY;
5327 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5328 SSVAL(pdata,2,0); /* No fnum. */
5329 SIVAL(pdata,4,info); /* Was directory created. */
5331 switch (info_level_return) {
5332 case SMB_QUERY_FILE_UNIX_BASIC:
5333 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5334 SSVAL(pdata,10,0); /* Padding. */
5335 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5336 break;
5337 case SMB_QUERY_FILE_UNIX_INFO2:
5338 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5339 SSVAL(pdata,10,0); /* Padding. */
5340 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5341 break;
5342 default:
5343 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5344 SSVAL(pdata,10,0); /* Padding. */
5345 break;
5348 return status;
5351 /****************************************************************************
5352 Open/Create a file with POSIX semantics.
5353 ****************************************************************************/
5355 static NTSTATUS smb_posix_open(connection_struct *conn,
5356 char **ppdata,
5357 int total_data,
5358 const char *fname,
5359 SMB_STRUCT_STAT *psbuf,
5360 int *pdata_return_size)
5362 BOOL extended_oplock_granted = False;
5363 char *pdata = *ppdata;
5364 uint32 flags = 0;
5365 uint32 wire_open_mode = 0;
5366 uint32 raw_unixmode = 0;
5367 uint32 mod_unixmode = 0;
5368 uint32 create_disp = 0;
5369 uint32 access_mask = 0;
5370 uint32 create_options = 0;
5371 NTSTATUS status = NT_STATUS_OK;
5372 mode_t unixmode = (mode_t)0;
5373 files_struct *fsp = NULL;
5374 int oplock_request = 0;
5375 int info = 0;
5376 uint16 info_level_return = 0;
5378 if (total_data < 18) {
5379 return NT_STATUS_INVALID_PARAMETER;
5382 flags = IVAL(pdata,0);
5383 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5384 if (oplock_request) {
5385 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5388 wire_open_mode = IVAL(pdata,4);
5390 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5391 return smb_posix_mkdir(conn,
5392 ppdata,
5393 total_data,
5394 fname,
5395 psbuf,
5396 pdata_return_size);
5399 switch (wire_open_mode & SMB_ACCMODE) {
5400 case SMB_O_RDONLY:
5401 access_mask = FILE_READ_DATA;
5402 break;
5403 case SMB_O_WRONLY:
5404 access_mask = FILE_WRITE_DATA;
5405 break;
5406 case SMB_O_RDWR:
5407 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5408 break;
5409 default:
5410 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5411 (unsigned int)wire_open_mode ));
5412 return NT_STATUS_INVALID_PARAMETER;
5415 wire_open_mode &= ~SMB_ACCMODE;
5417 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5418 create_disp = FILE_CREATE;
5419 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5420 create_disp = FILE_OVERWRITE_IF;
5421 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5422 create_disp = FILE_OPEN_IF;
5423 } else {
5424 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5425 (unsigned int)wire_open_mode ));
5426 return NT_STATUS_INVALID_PARAMETER;
5429 raw_unixmode = IVAL(pdata,8);
5430 /* Next 4 bytes are not yet defined. */
5432 status = unix_perms_from_wire(conn,
5433 psbuf,
5434 raw_unixmode,
5435 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5436 &unixmode);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 return status;
5442 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5444 if (wire_open_mode & SMB_O_SYNC) {
5445 create_options |= FILE_WRITE_THROUGH;
5447 if (wire_open_mode & SMB_O_APPEND) {
5448 access_mask |= FILE_APPEND_DATA;
5450 if (wire_open_mode & SMB_O_DIRECT) {
5451 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5454 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5455 fname,
5456 (unsigned int)wire_open_mode,
5457 (unsigned int)unixmode ));
5459 status = open_file_ntcreate(conn,
5460 fname,
5461 psbuf,
5462 access_mask,
5463 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5464 create_disp,
5465 0, /* no create options yet. */
5466 mod_unixmode,
5467 oplock_request,
5468 &info,
5469 &fsp);
5471 if (!NT_STATUS_IS_OK(status)) {
5472 return status;
5475 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5476 extended_oplock_granted = True;
5479 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5480 extended_oplock_granted = True;
5483 info_level_return = SVAL(pdata,16);
5485 /* Allocate the correct return size. */
5487 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5488 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5489 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5490 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5491 } else {
5492 *pdata_return_size = 12;
5495 /* Realloc the data size */
5496 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5497 if (*ppdata == NULL) {
5498 close_file(fsp,ERROR_CLOSE);
5499 *pdata_return_size = 0;
5500 return NT_STATUS_NO_MEMORY;
5503 if (extended_oplock_granted) {
5504 if (flags & REQUEST_BATCH_OPLOCK) {
5505 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5506 } else {
5507 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5509 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5510 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5511 } else {
5512 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5515 SSVAL(pdata,2,fsp->fnum);
5516 SIVAL(pdata,4,info); /* Was file created etc. */
5518 switch (info_level_return) {
5519 case SMB_QUERY_FILE_UNIX_BASIC:
5520 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5521 SSVAL(pdata,10,0); /* padding. */
5522 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5523 break;
5524 case SMB_QUERY_FILE_UNIX_INFO2:
5525 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5526 SSVAL(pdata,10,0); /* padding. */
5527 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5528 break;
5529 default:
5530 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5531 SSVAL(pdata,10,0); /* padding. */
5532 break;
5534 return NT_STATUS_OK;
5537 /****************************************************************************
5538 Delete a file with POSIX semantics.
5539 ****************************************************************************/
5541 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5542 const char *pdata,
5543 int total_data,
5544 const char *fname,
5545 SMB_STRUCT_STAT *psbuf)
5547 NTSTATUS status = NT_STATUS_OK;
5548 files_struct *fsp = NULL;
5549 uint16 flags = 0;
5550 int info = 0;
5552 if (total_data < 2) {
5553 return NT_STATUS_INVALID_PARAMETER;
5556 flags = SVAL(pdata,0);
5558 if (!VALID_STAT(*psbuf)) {
5559 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5562 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5563 !VALID_STAT_OF_DIR(*psbuf)) {
5564 return NT_STATUS_NOT_A_DIRECTORY;
5567 DEBUG(10,("smb_posix_unlink: %s %s\n",
5568 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5569 fname));
5571 if (VALID_STAT_OF_DIR(*psbuf)) {
5572 status = open_directory(conn,
5573 fname,
5574 psbuf,
5575 DELETE_ACCESS,
5576 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5577 FILE_OPEN,
5578 FILE_DELETE_ON_CLOSE,
5579 FILE_FLAG_POSIX_SEMANTICS|0777,
5580 &info,
5581 &fsp);
5582 } else {
5583 char del = 1;
5585 status = open_file_ntcreate(conn,
5586 fname,
5587 psbuf,
5588 DELETE_ACCESS,
5589 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5590 FILE_OPEN,
5592 FILE_FLAG_POSIX_SEMANTICS|0777,
5593 0, /* No oplock, but break existing ones. */
5594 &info,
5595 &fsp);
5597 * For file opens we must set the delete on close
5598 * after the open.
5601 if (!NT_STATUS_IS_OK(status)) {
5602 return status;
5605 status = smb_set_file_disposition_info(conn,
5606 &del,
5608 fsp,
5609 fname,
5610 psbuf);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 return status;
5616 return close_file(fsp, NORMAL_CLOSE);
5619 /****************************************************************************
5620 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5621 ****************************************************************************/
5623 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5624 unsigned int tran_call,
5625 char **pparams, int total_params, char **ppdata, int total_data,
5626 unsigned int max_data_bytes)
5628 char *params = *pparams;
5629 char *pdata = *ppdata;
5630 uint16 info_level;
5631 SMB_STRUCT_STAT sbuf;
5632 pstring fname;
5633 files_struct *fsp = NULL;
5634 NTSTATUS status = NT_STATUS_OK;
5635 int data_return_size = 0;
5637 if (!params) {
5638 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5641 ZERO_STRUCT(sbuf);
5643 if (tran_call == TRANSACT2_SETFILEINFO) {
5644 if (total_params < 4) {
5645 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5648 fsp = file_fsp(params,0);
5649 info_level = SVAL(params,2);
5651 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5653 * This is actually a SETFILEINFO on a directory
5654 * handle (returned from an NT SMB). NT5.0 seems
5655 * to do this call. JRA.
5657 pstrcpy(fname, fsp->fsp_name);
5658 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5659 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5660 return UNIXERROR(ERRDOS,ERRbadpath);
5662 } else if (fsp && fsp->print_file) {
5664 * Doing a DELETE_ON_CLOSE should cancel a print job.
5666 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5667 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5669 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5671 SSVAL(params,0,0);
5672 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5673 return(-1);
5674 } else
5675 return (UNIXERROR(ERRDOS,ERRbadpath));
5676 } else {
5678 * Original code - this is an open file.
5680 CHECK_FSP(fsp,conn);
5682 pstrcpy(fname, fsp->fsp_name);
5684 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5685 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5686 return(UNIXERROR(ERRDOS,ERRbadfid));
5689 } else {
5690 /* set path info */
5691 if (total_params < 7) {
5692 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5695 info_level = SVAL(params,0);
5696 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5697 if (!NT_STATUS_IS_OK(status)) {
5698 return ERROR_NT(status);
5701 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5702 if (!NT_STATUS_IS_OK(status)) {
5703 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5704 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5706 return ERROR_NT(status);
5709 status = unix_convert(conn, fname, False, NULL, &sbuf);
5710 if (!NT_STATUS_IS_OK(status)) {
5711 return ERROR_NT(status);
5714 status = check_name(conn, fname);
5715 if (!NT_STATUS_IS_OK(status)) {
5716 return ERROR_NT(status);
5720 * For CIFS UNIX extensions the target name may not exist.
5723 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5724 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5725 return UNIXERROR(ERRDOS,ERRbadpath);
5729 if (!CAN_WRITE(conn)) {
5730 return ERROR_DOS(ERRSRV,ERRaccess);
5733 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5734 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5737 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5738 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5740 /* Realloc the parameter size */
5741 *pparams = (char *)SMB_REALLOC(*pparams,2);
5742 if (*pparams == NULL) {
5743 return ERROR_NT(NT_STATUS_NO_MEMORY);
5745 params = *pparams;
5747 SSVAL(params,0,0);
5749 if (fsp && !null_timespec(fsp->pending_modtime)) {
5750 /* the pending modtime overrides the current modtime */
5751 set_mtimespec(&sbuf, fsp->pending_modtime);
5754 switch (info_level) {
5756 case SMB_INFO_STANDARD:
5758 status = smb_set_info_standard(conn,
5759 pdata,
5760 total_data,
5761 fsp,
5762 fname,
5763 &sbuf);
5764 break;
5767 case SMB_INFO_SET_EA:
5769 status = smb_info_set_ea(conn,
5770 pdata,
5771 total_data,
5772 fsp,
5773 fname);
5774 break;
5777 case SMB_SET_FILE_BASIC_INFO:
5778 case SMB_FILE_BASIC_INFORMATION:
5780 status = smb_set_file_basic_info(conn,
5781 pdata,
5782 total_data,
5783 fsp,
5784 fname,
5785 &sbuf);
5786 break;
5789 case SMB_FILE_ALLOCATION_INFORMATION:
5790 case SMB_SET_FILE_ALLOCATION_INFO:
5792 status = smb_set_file_allocation_info(conn,
5793 pdata,
5794 total_data,
5795 fsp,
5796 fname,
5797 &sbuf);
5798 break;
5801 case SMB_FILE_END_OF_FILE_INFORMATION:
5802 case SMB_SET_FILE_END_OF_FILE_INFO:
5804 status = smb_set_file_end_of_file_info(conn,
5805 pdata,
5806 total_data,
5807 fsp,
5808 fname,
5809 &sbuf);
5810 break;
5813 case SMB_FILE_DISPOSITION_INFORMATION:
5814 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5816 #if 0
5817 /* JRA - We used to just ignore this on a path ?
5818 * Shouldn't this be invalid level on a pathname
5819 * based call ?
5821 if (tran_call != TRANSACT2_SETFILEINFO) {
5822 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5824 #endif
5825 status = smb_set_file_disposition_info(conn,
5826 pdata,
5827 total_data,
5828 fsp,
5829 fname,
5830 &sbuf);
5831 break;
5834 case SMB_FILE_POSITION_INFORMATION:
5836 status = smb_file_position_information(conn,
5837 pdata,
5838 total_data,
5839 fsp);
5840 break;
5843 /* From tridge Samba4 :
5844 * MODE_INFORMATION in setfileinfo (I have no
5845 * idea what "mode information" on a file is - it takes a value of 0,
5846 * 2, 4 or 6. What could it be?).
5849 case SMB_FILE_MODE_INFORMATION:
5851 status = smb_file_mode_information(conn,
5852 pdata,
5853 total_data);
5854 break;
5858 * CIFS UNIX extensions.
5861 case SMB_SET_FILE_UNIX_BASIC:
5863 status = smb_set_file_unix_basic(conn,
5864 pdata,
5865 total_data,
5866 fsp,
5867 fname,
5868 &sbuf);
5869 break;
5872 case SMB_SET_FILE_UNIX_INFO2:
5874 status = smb_set_file_unix_info2(conn,
5875 pdata,
5876 total_data,
5877 fsp,
5878 fname,
5879 &sbuf);
5880 break;
5883 case SMB_SET_FILE_UNIX_LINK:
5885 if (tran_call != TRANSACT2_SETPATHINFO) {
5886 /* We must have a pathname for this. */
5887 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5889 status = smb_set_file_unix_link(conn,
5890 inbuf,
5891 pdata,
5892 total_data,
5893 fname);
5894 break;
5897 case SMB_SET_FILE_UNIX_HLINK:
5899 if (tran_call != TRANSACT2_SETPATHINFO) {
5900 /* We must have a pathname for this. */
5901 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5903 status = smb_set_file_unix_hlink(conn,
5904 inbuf,
5905 outbuf,
5906 pdata,
5907 total_data,
5908 fname);
5909 break;
5912 case SMB_FILE_RENAME_INFORMATION:
5914 status = smb_file_rename_information(conn,
5915 inbuf,
5916 outbuf,
5917 pdata,
5918 total_data,
5919 fsp,
5920 fname);
5921 break;
5924 #if defined(HAVE_POSIX_ACLS)
5925 case SMB_SET_POSIX_ACL:
5927 status = smb_set_posix_acl(conn,
5928 pdata,
5929 total_data,
5930 fsp,
5931 fname,
5932 &sbuf);
5933 break;
5935 #endif
5937 case SMB_SET_POSIX_LOCK:
5939 if (tran_call != TRANSACT2_SETFILEINFO) {
5940 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5942 status = smb_set_posix_lock(conn,
5943 inbuf,
5944 length,
5945 pdata,
5946 total_data,
5947 fsp);
5948 break;
5951 case SMB_POSIX_PATH_OPEN:
5953 if (tran_call != TRANSACT2_SETPATHINFO) {
5954 /* We must have a pathname for this. */
5955 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5958 status = smb_posix_open(conn,
5959 ppdata,
5960 total_data,
5961 fname,
5962 &sbuf,
5963 &data_return_size);
5964 break;
5967 case SMB_POSIX_PATH_UNLINK:
5969 if (tran_call != TRANSACT2_SETPATHINFO) {
5970 /* We must have a pathname for this. */
5971 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5974 status = smb_posix_unlink(conn,
5975 pdata,
5976 total_data,
5977 fname,
5978 &sbuf);
5979 break;
5982 default:
5983 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5987 if (!NT_STATUS_IS_OK(status)) {
5988 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5989 /* We have re-scheduled this call. */
5990 return -1;
5992 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5993 /* We have re-scheduled this call. */
5994 return -1;
5996 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5997 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5999 return ERROR_NT(status);
6002 SSVAL(params,0,0);
6003 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6005 return -1;
6008 /****************************************************************************
6009 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6010 ****************************************************************************/
6012 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6013 char **pparams, int total_params, char **ppdata, int total_data,
6014 unsigned int max_data_bytes)
6016 char *params = *pparams;
6017 char *pdata = *ppdata;
6018 pstring directory;
6019 SMB_STRUCT_STAT sbuf;
6020 NTSTATUS status = NT_STATUS_OK;
6021 struct ea_list *ea_list = NULL;
6023 if (!CAN_WRITE(conn))
6024 return ERROR_DOS(ERRSRV,ERRaccess);
6026 if (total_params < 5) {
6027 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6030 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 return ERROR_NT(status);
6035 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6037 status = unix_convert(conn, directory, False, NULL, &sbuf);
6038 if (!NT_STATUS_IS_OK(status)) {
6039 return ERROR_NT(status);
6042 status = check_name(conn, directory);
6043 if (!NT_STATUS_IS_OK(status)) {
6044 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6045 return ERROR_NT(status);
6048 /* Any data in this call is an EA list. */
6049 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6050 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6054 * OS/2 workplace shell seems to send SET_EA requests of "null"
6055 * length (4 bytes containing IVAL 4).
6056 * They seem to have no effect. Bug #3212. JRA.
6059 if (total_data != 4) {
6060 if (total_data < 10) {
6061 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6064 if (IVAL(pdata,0) > total_data) {
6065 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6066 IVAL(pdata,0), (unsigned int)total_data));
6067 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6070 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6071 total_data - 4);
6072 if (!ea_list) {
6073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6075 } else if (IVAL(pdata,0) != 4) {
6076 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6079 status = create_directory(conn, directory);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 return ERROR_NT(status);
6085 /* Try and set any given EA. */
6086 if (ea_list) {
6087 status = set_ea(conn, NULL, directory, ea_list);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 return ERROR_NT(status);
6093 /* Realloc the parameter and data sizes */
6094 *pparams = (char *)SMB_REALLOC(*pparams,2);
6095 if(*pparams == NULL) {
6096 return ERROR_NT(NT_STATUS_NO_MEMORY);
6098 params = *pparams;
6100 SSVAL(params,0,0);
6102 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6104 return(-1);
6107 /****************************************************************************
6108 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6109 We don't actually do this - we just send a null response.
6110 ****************************************************************************/
6112 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6113 char **pparams, int total_params, char **ppdata, int total_data,
6114 unsigned int max_data_bytes)
6116 static uint16 fnf_handle = 257;
6117 char *params = *pparams;
6118 uint16 info_level;
6120 if (total_params < 6) {
6121 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6124 info_level = SVAL(params,4);
6125 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6127 switch (info_level) {
6128 case 1:
6129 case 2:
6130 break;
6131 default:
6132 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6135 /* Realloc the parameter and data sizes */
6136 *pparams = (char *)SMB_REALLOC(*pparams,6);
6137 if (*pparams == NULL) {
6138 return ERROR_NT(NT_STATUS_NO_MEMORY);
6140 params = *pparams;
6142 SSVAL(params,0,fnf_handle);
6143 SSVAL(params,2,0); /* No changes */
6144 SSVAL(params,4,0); /* No EA errors */
6146 fnf_handle++;
6148 if(fnf_handle == 0)
6149 fnf_handle = 257;
6151 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6153 return(-1);
6156 /****************************************************************************
6157 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6158 changes). Currently this does nothing.
6159 ****************************************************************************/
6161 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6162 char **pparams, int total_params, char **ppdata, int total_data,
6163 unsigned int max_data_bytes)
6165 char *params = *pparams;
6167 DEBUG(3,("call_trans2findnotifynext\n"));
6169 /* Realloc the parameter and data sizes */
6170 *pparams = (char *)SMB_REALLOC(*pparams,4);
6171 if (*pparams == NULL) {
6172 return ERROR_NT(NT_STATUS_NO_MEMORY);
6174 params = *pparams;
6176 SSVAL(params,0,0); /* No changes */
6177 SSVAL(params,2,0); /* No EA errors */
6179 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6181 return(-1);
6184 /****************************************************************************
6185 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6186 ****************************************************************************/
6188 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6189 char **pparams, int total_params, char **ppdata, int total_data,
6190 unsigned int max_data_bytes)
6192 char *params = *pparams;
6193 pstring pathname;
6194 int reply_size = 0;
6195 int max_referral_level;
6197 DEBUG(10,("call_trans2getdfsreferral\n"));
6199 if (total_params < 3) {
6200 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6203 max_referral_level = SVAL(params,0);
6205 if(!lp_host_msdfs())
6206 return ERROR_DOS(ERRDOS,ERRbadfunc);
6208 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6209 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6210 return UNIXERROR(ERRDOS,ERRbadfile);
6212 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6213 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6215 return(-1);
6218 #define LMCAT_SPL 0x53
6219 #define LMFUNC_GETJOBID 0x60
6221 /****************************************************************************
6222 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6223 ****************************************************************************/
6225 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6226 char **pparams, int total_params, char **ppdata, int total_data,
6227 unsigned int max_data_bytes)
6229 char *pdata = *ppdata;
6230 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6232 /* check for an invalid fid before proceeding */
6234 if (!fsp)
6235 return(ERROR_DOS(ERRDOS,ERRbadfid));
6237 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6238 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6239 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6240 if (*ppdata == NULL) {
6241 return ERROR_NT(NT_STATUS_NO_MEMORY);
6243 pdata = *ppdata;
6245 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6246 CAN ACCEPT THIS IN UNICODE. JRA. */
6248 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6249 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6250 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6251 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6252 return(-1);
6253 } else {
6254 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6255 return ERROR_DOS(ERRSRV,ERRerror);
6259 /****************************************************************************
6260 Reply to a SMBfindclose (stop trans2 directory search).
6261 ****************************************************************************/
6263 int reply_findclose(connection_struct *conn,
6264 char *inbuf,char *outbuf,int length,int bufsize)
6266 int outsize = 0;
6267 int dptr_num=SVALS(inbuf,smb_vwv0);
6268 START_PROFILE(SMBfindclose);
6270 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6272 dptr_close(&dptr_num);
6274 outsize = set_message(outbuf,0,0,False);
6276 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6278 END_PROFILE(SMBfindclose);
6279 return(outsize);
6282 /****************************************************************************
6283 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6284 ****************************************************************************/
6286 int reply_findnclose(connection_struct *conn,
6287 char *inbuf,char *outbuf,int length,int bufsize)
6289 int outsize = 0;
6290 int dptr_num= -1;
6291 START_PROFILE(SMBfindnclose);
6293 dptr_num = SVAL(inbuf,smb_vwv0);
6295 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6297 /* We never give out valid handles for a
6298 findnotifyfirst - so any dptr_num is ok here.
6299 Just ignore it. */
6301 outsize = set_message(outbuf,0,0,False);
6303 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6305 END_PROFILE(SMBfindnclose);
6306 return(outsize);
6309 int handle_trans2(connection_struct *conn,
6310 struct trans_state *state,
6311 char *inbuf, char *outbuf, int size, int bufsize)
6313 int outsize;
6315 if (Protocol >= PROTOCOL_NT1) {
6316 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6319 /* Now we must call the relevant TRANS2 function */
6320 switch(state->call) {
6321 case TRANSACT2_OPEN:
6323 START_PROFILE(Trans2_open);
6324 outsize = call_trans2open(
6325 conn, inbuf, outbuf, bufsize,
6326 &state->param, state->total_param,
6327 &state->data, state->total_data,
6328 state->max_data_return);
6329 END_PROFILE(Trans2_open);
6330 break;
6333 case TRANSACT2_FINDFIRST:
6335 START_PROFILE(Trans2_findfirst);
6336 outsize = call_trans2findfirst(
6337 conn, inbuf, outbuf, bufsize,
6338 &state->param, state->total_param,
6339 &state->data, state->total_data,
6340 state->max_data_return);
6341 END_PROFILE(Trans2_findfirst);
6342 break;
6345 case TRANSACT2_FINDNEXT:
6347 START_PROFILE(Trans2_findnext);
6348 outsize = call_trans2findnext(
6349 conn, inbuf, outbuf, size, bufsize,
6350 &state->param, state->total_param,
6351 &state->data, state->total_data,
6352 state->max_data_return);
6353 END_PROFILE(Trans2_findnext);
6354 break;
6357 case TRANSACT2_QFSINFO:
6359 START_PROFILE(Trans2_qfsinfo);
6360 outsize = call_trans2qfsinfo(
6361 conn, inbuf, outbuf, size, bufsize,
6362 &state->param, state->total_param,
6363 &state->data, state->total_data,
6364 state->max_data_return);
6365 END_PROFILE(Trans2_qfsinfo);
6366 break;
6369 case TRANSACT2_SETFSINFO:
6371 START_PROFILE(Trans2_setfsinfo);
6372 outsize = call_trans2setfsinfo(
6373 conn, inbuf, outbuf, size, bufsize,
6374 &state->param, state->total_param,
6375 &state->data, state->total_data,
6376 state->max_data_return);
6377 END_PROFILE(Trans2_setfsinfo);
6378 break;
6381 case TRANSACT2_QPATHINFO:
6382 case TRANSACT2_QFILEINFO:
6384 START_PROFILE(Trans2_qpathinfo);
6385 outsize = call_trans2qfilepathinfo(
6386 conn, inbuf, outbuf, size, bufsize, state->call,
6387 &state->param, state->total_param,
6388 &state->data, state->total_data,
6389 state->max_data_return);
6390 END_PROFILE(Trans2_qpathinfo);
6391 break;
6394 case TRANSACT2_SETPATHINFO:
6395 case TRANSACT2_SETFILEINFO:
6397 START_PROFILE(Trans2_setpathinfo);
6398 outsize = call_trans2setfilepathinfo(
6399 conn, inbuf, outbuf, size, bufsize, state->call,
6400 &state->param, state->total_param,
6401 &state->data, state->total_data,
6402 state->max_data_return);
6403 END_PROFILE(Trans2_setpathinfo);
6404 break;
6407 case TRANSACT2_FINDNOTIFYFIRST:
6409 START_PROFILE(Trans2_findnotifyfirst);
6410 outsize = call_trans2findnotifyfirst(
6411 conn, inbuf, outbuf, size, bufsize,
6412 &state->param, state->total_param,
6413 &state->data, state->total_data,
6414 state->max_data_return);
6415 END_PROFILE(Trans2_findnotifyfirst);
6416 break;
6419 case TRANSACT2_FINDNOTIFYNEXT:
6421 START_PROFILE(Trans2_findnotifynext);
6422 outsize = call_trans2findnotifynext(
6423 conn, inbuf, outbuf, size, bufsize,
6424 &state->param, state->total_param,
6425 &state->data, state->total_data,
6426 state->max_data_return);
6427 END_PROFILE(Trans2_findnotifynext);
6428 break;
6431 case TRANSACT2_MKDIR:
6433 START_PROFILE(Trans2_mkdir);
6434 outsize = call_trans2mkdir(
6435 conn, inbuf, outbuf, size, bufsize,
6436 &state->param, state->total_param,
6437 &state->data, state->total_data,
6438 state->max_data_return);
6439 END_PROFILE(Trans2_mkdir);
6440 break;
6443 case TRANSACT2_GET_DFS_REFERRAL:
6445 START_PROFILE(Trans2_get_dfs_referral);
6446 outsize = call_trans2getdfsreferral(
6447 conn, inbuf, outbuf, size, bufsize,
6448 &state->param, state->total_param,
6449 &state->data, state->total_data,
6450 state->max_data_return);
6451 END_PROFILE(Trans2_get_dfs_referral);
6452 break;
6455 case TRANSACT2_IOCTL:
6457 START_PROFILE(Trans2_ioctl);
6458 outsize = call_trans2ioctl(
6459 conn, inbuf, outbuf, size, bufsize,
6460 &state->param, state->total_param,
6461 &state->data, state->total_data,
6462 state->max_data_return);
6463 END_PROFILE(Trans2_ioctl);
6464 break;
6467 default:
6468 /* Error in request */
6469 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6470 outsize = ERROR_DOS(ERRSRV,ERRerror);
6473 return outsize;
6476 /****************************************************************************
6477 Reply to a SMBtrans2.
6478 ****************************************************************************/
6480 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6481 int size, int bufsize)
6483 int outsize = 0;
6484 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6485 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6486 unsigned int psoff = SVAL(inbuf, smb_psoff);
6487 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6488 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6489 struct trans_state *state;
6490 NTSTATUS result;
6492 START_PROFILE(SMBtrans2);
6494 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6495 if (!NT_STATUS_IS_OK(result)) {
6496 DEBUG(2, ("Got invalid trans2 request: %s\n",
6497 nt_errstr(result)));
6498 END_PROFILE(SMBtrans2);
6499 return ERROR_NT(result);
6502 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6503 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6504 END_PROFILE(SMBtrans2);
6505 return ERROR_DOS(ERRSRV,ERRaccess);
6508 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6509 DEBUG(0, ("talloc failed\n"));
6510 END_PROFILE(SMBtrans2);
6511 return ERROR_NT(NT_STATUS_NO_MEMORY);
6514 state->cmd = SMBtrans2;
6516 state->mid = SVAL(inbuf, smb_mid);
6517 state->vuid = SVAL(inbuf, smb_uid);
6518 state->setup_count = SVAL(inbuf, smb_suwcnt);
6519 state->setup = NULL;
6520 state->total_param = SVAL(inbuf, smb_tpscnt);
6521 state->param = NULL;
6522 state->total_data = SVAL(inbuf, smb_tdscnt);
6523 state->data = NULL;
6524 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6525 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6526 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6527 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6528 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6530 state->call = tran_call;
6532 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6533 is so as a sanity check */
6534 if (state->setup_count != 1) {
6536 * Need to have rc=0 for ioctl to get job id for OS/2.
6537 * Network printing will fail if function is not successful.
6538 * Similar function in reply.c will be used if protocol
6539 * is LANMAN1.0 instead of LM1.2X002.
6540 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6541 * outbuf doesn't have to be set(only job id is used).
6543 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6544 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6545 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6546 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6547 } else {
6548 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6549 DEBUG(2,("Transaction is %d\n",tran_call));
6550 TALLOC_FREE(state);
6551 END_PROFILE(SMBtrans2);
6552 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6556 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6557 goto bad_param;
6559 if (state->total_data) {
6560 /* Can't use talloc here, the core routines do realloc on the
6561 * params and data. */
6562 state->data = (char *)SMB_MALLOC(state->total_data);
6563 if (state->data == NULL) {
6564 DEBUG(0,("reply_trans2: data malloc fail for %u "
6565 "bytes !\n", (unsigned int)state->total_data));
6566 TALLOC_FREE(state);
6567 END_PROFILE(SMBtrans2);
6568 return(ERROR_DOS(ERRDOS,ERRnomem));
6570 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6571 goto bad_param;
6572 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6573 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6574 goto bad_param;
6576 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6579 if (state->total_param) {
6580 /* Can't use talloc here, the core routines do realloc on the
6581 * params and data. */
6582 state->param = (char *)SMB_MALLOC(state->total_param);
6583 if (state->param == NULL) {
6584 DEBUG(0,("reply_trans: param malloc fail for %u "
6585 "bytes !\n", (unsigned int)state->total_param));
6586 SAFE_FREE(state->data);
6587 TALLOC_FREE(state);
6588 END_PROFILE(SMBtrans2);
6589 return(ERROR_DOS(ERRDOS,ERRnomem));
6591 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6592 goto bad_param;
6593 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6594 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6595 goto bad_param;
6597 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6600 state->received_data = dscnt;
6601 state->received_param = pscnt;
6603 if ((state->received_param == state->total_param) &&
6604 (state->received_data == state->total_data)) {
6606 outsize = handle_trans2(conn, state, inbuf, outbuf,
6607 size, bufsize);
6608 SAFE_FREE(state->data);
6609 SAFE_FREE(state->param);
6610 TALLOC_FREE(state);
6611 END_PROFILE(SMBtrans2);
6612 return outsize;
6615 DLIST_ADD(conn->pending_trans, state);
6617 /* We need to send an interim response then receive the rest
6618 of the parameter/data bytes */
6619 outsize = set_message(outbuf,0,0,False);
6620 show_msg(outbuf);
6621 END_PROFILE(SMBtrans2);
6622 return outsize;
6624 bad_param:
6626 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6627 SAFE_FREE(state->data);
6628 SAFE_FREE(state->param);
6629 TALLOC_FREE(state);
6630 END_PROFILE(SMBtrans2);
6631 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6635 /****************************************************************************
6636 Reply to a SMBtranss2
6637 ****************************************************************************/
6639 int reply_transs2(connection_struct *conn,
6640 char *inbuf,char *outbuf,int size,int bufsize)
6642 int outsize = 0;
6643 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6644 struct trans_state *state;
6646 START_PROFILE(SMBtranss2);
6648 show_msg(inbuf);
6650 for (state = conn->pending_trans; state != NULL;
6651 state = state->next) {
6652 if (state->mid == SVAL(inbuf,smb_mid)) {
6653 break;
6657 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6658 END_PROFILE(SMBtranss2);
6659 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6662 /* Revise state->total_param and state->total_data in case they have
6663 changed downwards */
6665 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6666 state->total_param = SVAL(inbuf, smb_tpscnt);
6667 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6668 state->total_data = SVAL(inbuf, smb_tdscnt);
6670 pcnt = SVAL(inbuf, smb_spscnt);
6671 poff = SVAL(inbuf, smb_spsoff);
6672 pdisp = SVAL(inbuf, smb_spsdisp);
6674 dcnt = SVAL(inbuf, smb_sdscnt);
6675 doff = SVAL(inbuf, smb_sdsoff);
6676 ddisp = SVAL(inbuf, smb_sdsdisp);
6678 state->received_param += pcnt;
6679 state->received_data += dcnt;
6681 if ((state->received_data > state->total_data) ||
6682 (state->received_param > state->total_param))
6683 goto bad_param;
6685 if (pcnt) {
6686 if (pdisp+pcnt > state->total_param)
6687 goto bad_param;
6688 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6689 goto bad_param;
6690 if (pdisp > state->total_param)
6691 goto bad_param;
6692 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6693 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6694 goto bad_param;
6695 if (state->param + pdisp < state->param)
6696 goto bad_param;
6698 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6699 pcnt);
6702 if (dcnt) {
6703 if (ddisp+dcnt > state->total_data)
6704 goto bad_param;
6705 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6706 goto bad_param;
6707 if (ddisp > state->total_data)
6708 goto bad_param;
6709 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6710 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6711 goto bad_param;
6712 if (state->data + ddisp < state->data)
6713 goto bad_param;
6715 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6716 dcnt);
6719 if ((state->received_param < state->total_param) ||
6720 (state->received_data < state->total_data)) {
6721 END_PROFILE(SMBtranss2);
6722 return -1;
6725 /* construct_reply_common has done us the favor to pre-fill the
6726 * command field with SMBtranss2 which is wrong :-)
6728 SCVAL(outbuf,smb_com,SMBtrans2);
6730 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6732 DLIST_REMOVE(conn->pending_trans, state);
6733 SAFE_FREE(state->data);
6734 SAFE_FREE(state->param);
6735 TALLOC_FREE(state);
6737 if (outsize == 0) {
6738 END_PROFILE(SMBtranss2);
6739 return(ERROR_DOS(ERRSRV,ERRnosupport));
6742 END_PROFILE(SMBtranss2);
6743 return(outsize);
6745 bad_param:
6747 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6748 DLIST_REMOVE(conn->pending_trans, state);
6749 SAFE_FREE(state->data);
6750 SAFE_FREE(state->param);
6751 TALLOC_FREE(state);
6752 END_PROFILE(SMBtranss2);
6753 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);