r16309: Fix Klocwork #1596. Check for NULL on talloc.
[Samba/gebeck_regimport.git] / source / smbd / trans2.c
blob27fd62be7fd94faad646caf8939991c55f7773d7
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
51 return val;
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
56 account sparse files.
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
61 SMB_BIG_UINT ret;
63 if(S_ISDIR(sbuf->st_mode)) {
64 return 0;
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
86 NULL
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
95 int i;
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return True;
101 return False;
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
113 char *val = NULL;
114 ssize_t sizeret;
116 again:
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119 if (!val) {
120 return False;
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125 } else {
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130 attr_size = 65536;
131 goto again;
134 if (sizeret == -1) {
135 return False;
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
141 pea->flags = 0;
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
144 } else {
145 pea->name = ea_name;
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
149 return True;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
161 char *ea_namelist;
162 char *p;
163 ssize_t sizeret;
164 int i;
165 struct ea_list *ea_list_head = NULL;
167 *pea_total_len = 0;
169 if (!lp_ea_support(SNUM(conn))) {
170 return NULL;
173 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
176 if (!ea_namelist) {
177 return NULL;
180 if (fsp && fsp->fh->fd != -1) {
181 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
182 } else {
183 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
186 if (sizeret == -1 && errno == ERANGE) {
187 ea_namelist_size *= 2;
188 } else {
189 break;
193 if (sizeret == -1)
194 return NULL;
196 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
198 if (sizeret) {
199 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200 struct ea_list *listp, *tmp;
202 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
203 continue;
205 listp = TALLOC_P(mem_ctx, struct ea_list);
206 if (!listp)
207 return NULL;
209 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
210 return NULL;
214 fstring dos_ea_name;
215 push_ascii_fstring(dos_ea_name, listp->ea.name);
216 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218 (unsigned int)*pea_total_len, dos_ea_name,
219 (unsigned int)listp->ea.value.length ));
221 DLIST_ADD_END(ea_list_head, listp, tmp);
223 /* Add on 4 for total length. */
224 if (*pea_total_len) {
225 *pea_total_len += 4;
229 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
230 return ea_list_head;
233 /****************************************************************************
234 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
235 that was filled.
236 ****************************************************************************/
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239 connection_struct *conn, struct ea_list *ea_list)
241 unsigned int ret_data_size = 4;
242 char *p = pdata;
244 SMB_ASSERT(total_data_size >= 4);
246 if (!lp_ea_support(SNUM(conn))) {
247 SIVAL(pdata,4,0);
248 return 4;
251 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
252 size_t dos_namelen;
253 fstring dos_ea_name;
254 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255 dos_namelen = strlen(dos_ea_name);
256 if (dos_namelen > 255 || dos_namelen == 0) {
257 break;
259 if (ea_list->ea.value.length > 65535) {
260 break;
262 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
263 break;
266 /* We know we have room. */
267 SCVAL(p,0,ea_list->ea.flags);
268 SCVAL(p,1,dos_namelen);
269 SSVAL(p,2,ea_list->ea.value.length);
270 fstrcpy(p+4, dos_ea_name);
271 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
273 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
277 ret_data_size = PTR_DIFF(p, pdata);
278 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279 SIVAL(pdata,0,ret_data_size);
280 return ret_data_size;
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
285 size_t total_ea_len = 0;
286 TALLOC_CTX *mem_ctx = NULL;
288 if (!lp_ea_support(SNUM(conn))) {
289 return 0;
291 mem_ctx = talloc_init("estimate_ea_size");
292 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293 talloc_destroy(mem_ctx);
294 return total_ea_len;
297 /****************************************************************************
298 Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
303 size_t total_ea_len;
304 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
307 for (; ea_list; ea_list = ea_list->next) {
308 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310 &unix_ea_name[5], ea_list->ea.name));
311 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
312 break;
315 talloc_destroy(mem_ctx);
318 /****************************************************************************
319 Set or delete an extended attribute.
320 ****************************************************************************/
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
324 if (!lp_ea_support(SNUM(conn))) {
325 return NT_STATUS_EAS_NOT_SUPPORTED;
328 for (;ea_list; ea_list = ea_list->next) {
329 int ret;
330 fstring unix_ea_name;
332 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333 fstrcat(unix_ea_name, ea_list->ea.name);
335 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
337 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
339 if (samba_private_attr_name(unix_ea_name)) {
340 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341 return NT_STATUS_ACCESS_DENIED;
344 if (ea_list->ea.value.length == 0) {
345 /* Remove the attribute. */
346 if (fsp && (fsp->fh->fd != -1)) {
347 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348 unix_ea_name, fsp->fsp_name));
349 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
350 } else {
351 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352 unix_ea_name, fname));
353 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
355 #ifdef ENOATTR
356 /* Removing a non existent attribute always succeeds. */
357 if (ret == -1 && errno == ENOATTR) {
358 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359 unix_ea_name));
360 ret = 0;
362 #endif
363 } else {
364 if (fsp && (fsp->fh->fd != -1)) {
365 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366 unix_ea_name, fsp->fsp_name));
367 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
369 } else {
370 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371 unix_ea_name, fname));
372 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373 ea_list->ea.value.data, ea_list->ea.value.length, 0);
377 if (ret == -1) {
378 #ifdef ENOTSUP
379 if (errno == ENOTSUP) {
380 return NT_STATUS_EAS_NOT_SUPPORTED;
382 #endif
383 return map_nt_error_from_unix(errno);
387 return NT_STATUS_OK;
389 /****************************************************************************
390 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
395 struct ea_list *ea_list_head = NULL;
396 size_t offset = 0;
398 while (offset + 2 < data_size) {
399 struct ea_list *tmp;
400 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
401 unsigned int namelen = CVAL(pdata,offset);
403 offset++; /* Go past the namelen byte. */
405 /* integer wrap paranioa. */
406 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
407 (offset > data_size) || (namelen > data_size) ||
408 (offset + namelen >= data_size)) {
409 break;
411 /* Ensure the name is null terminated. */
412 if (pdata[offset + namelen] != '\0') {
413 return NULL;
415 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
416 if (!eal->ea.name) {
417 return NULL;
420 offset += (namelen + 1); /* Go past the name + terminating zero. */
421 DLIST_ADD_END(ea_list_head, eal, tmp);
422 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
425 return ea_list_head;
428 /****************************************************************************
429 Read one EA list entry from the buffer.
430 ****************************************************************************/
432 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
434 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
435 uint16 val_len;
436 unsigned int namelen;
438 if (!eal) {
439 return NULL;
442 if (data_size < 6) {
443 return NULL;
446 eal->ea.flags = CVAL(pdata,0);
447 namelen = CVAL(pdata,1);
448 val_len = SVAL(pdata,2);
450 if (4 + namelen + 1 + val_len > data_size) {
451 return NULL;
454 /* Ensure the name is null terminated. */
455 if (pdata[namelen + 4] != '\0') {
456 return NULL;
458 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
459 if (!eal->ea.name) {
460 return NULL;
463 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
464 if (!eal->ea.value.data) {
465 return NULL;
468 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
470 /* Ensure we're null terminated just in case we print the value. */
471 eal->ea.value.data[val_len] = '\0';
472 /* But don't count the null. */
473 eal->ea.value.length--;
475 if (pbytes_used) {
476 *pbytes_used = 4 + namelen + 1 + val_len;
479 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
480 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
482 return eal;
485 /****************************************************************************
486 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
487 ****************************************************************************/
489 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
491 struct ea_list *ea_list_head = NULL;
492 size_t offset = 0;
493 size_t bytes_used = 0;
495 while (offset < data_size) {
496 struct ea_list *tmp;
497 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
499 if (!eal) {
500 return NULL;
503 DLIST_ADD_END(ea_list_head, eal, tmp);
504 offset += bytes_used;
507 return ea_list_head;
510 /****************************************************************************
511 Count the total EA size needed.
512 ****************************************************************************/
514 static size_t ea_list_size(struct ea_list *ealist)
516 fstring dos_ea_name;
517 struct ea_list *listp;
518 size_t ret = 0;
520 for (listp = ealist; listp; listp = listp->next) {
521 push_ascii_fstring(dos_ea_name, listp->ea.name);
522 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
524 /* Add on 4 for total length. */
525 if (ret) {
526 ret += 4;
529 return ret;
532 /****************************************************************************
533 Return a union of EA's from a file list and a list of names.
534 The TALLOC context for the two lists *MUST* be identical as we steal
535 memory from one list to add to another. JRA.
536 ****************************************************************************/
538 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
540 struct ea_list *nlistp, *flistp;
542 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
543 for (flistp = file_list; flistp; flistp = flistp->next) {
544 if (strequal(nlistp->ea.name, flistp->ea.name)) {
545 break;
549 if (flistp) {
550 /* Copy the data from this entry. */
551 nlistp->ea.flags = flistp->ea.flags;
552 nlistp->ea.value = flistp->ea.value;
553 } else {
554 /* Null entry. */
555 nlistp->ea.flags = 0;
556 ZERO_STRUCT(nlistp->ea.value);
560 *total_ea_len = ea_list_size(name_list);
561 return name_list;
564 /****************************************************************************
565 Send the required number of replies back.
566 We assume all fields other than the data fields are
567 set correctly for the type of call.
568 HACK ! Always assumes smb_setup field is zero.
569 ****************************************************************************/
571 int send_trans2_replies(char *outbuf,
572 int bufsize,
573 char *params,
574 int paramsize,
575 char *pdata,
576 int datasize)
578 /* As we are using a protocol > LANMAN1 then the max_send
579 variable must have been set in the sessetupX call.
580 This takes precedence over the max_xmit field in the
581 global struct. These different max_xmit variables should
582 be merged as this is now too confusing */
584 int data_to_send = datasize;
585 int params_to_send = paramsize;
586 int useable_space;
587 char *pp = params;
588 char *pd = pdata;
589 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
590 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
591 int data_alignment_offset = 0;
593 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
595 set_message(outbuf,10,0,True);
597 /* If there genuinely are no parameters or data to send just send the empty packet */
599 if(params_to_send == 0 && data_to_send == 0) {
600 show_msg(outbuf);
601 if (!send_smb(smbd_server_fd(),outbuf))
602 exit_server("send_trans2_replies: send_smb failed.");
603 return 0;
606 /* When sending params and data ensure that both are nicely aligned */
607 /* Only do this alignment when there is also data to send - else
608 can cause NT redirector problems. */
610 if (((params_to_send % 4) != 0) && (data_to_send != 0))
611 data_alignment_offset = 4 - (params_to_send % 4);
613 /* Space is bufsize minus Netbios over TCP header minus SMB header */
614 /* The alignment_offset is to align the param bytes on an even byte
615 boundary. NT 4.0 Beta needs this to work correctly. */
617 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
619 /* useable_space can never be more than max_send minus the alignment offset. */
621 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
623 while (params_to_send || data_to_send) {
624 /* Calculate whether we will totally or partially fill this packet */
626 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
628 /* We can never send more than useable_space */
630 * Note that 'useable_space' does not include the alignment offsets,
631 * but we must include the alignment offsets in the calculation of
632 * the length of the data we send over the wire, as the alignment offsets
633 * are sent here. Fix from Marc_Jacobsen@hp.com.
636 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
638 set_message(outbuf, 10, total_sent_thistime, True);
640 /* Set total params and data to be sent */
641 SSVAL(outbuf,smb_tprcnt,paramsize);
642 SSVAL(outbuf,smb_tdrcnt,datasize);
644 /* Calculate how many parameters and data we can fit into
645 * this packet. Parameters get precedence
648 params_sent_thistime = MIN(params_to_send,useable_space);
649 data_sent_thistime = useable_space - params_sent_thistime;
650 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
652 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
654 /* smb_proff is the offset from the start of the SMB header to the
655 parameter bytes, however the first 4 bytes of outbuf are
656 the Netbios over TCP header. Thus use smb_base() to subtract
657 them from the calculation */
659 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
661 if(params_sent_thistime == 0)
662 SSVAL(outbuf,smb_prdisp,0);
663 else
664 /* Absolute displacement of param bytes sent in this packet */
665 SSVAL(outbuf,smb_prdisp,pp - params);
667 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
668 if(data_sent_thistime == 0) {
669 SSVAL(outbuf,smb_droff,0);
670 SSVAL(outbuf,smb_drdisp, 0);
671 } else {
672 /* The offset of the data bytes is the offset of the
673 parameter bytes plus the number of parameters being sent this time */
674 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
675 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
676 SSVAL(outbuf,smb_drdisp, pd - pdata);
679 /* Copy the param bytes into the packet */
681 if(params_sent_thistime)
682 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
684 /* Copy in the data bytes */
685 if(data_sent_thistime)
686 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
687 data_alignment_offset,pd,data_sent_thistime);
689 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
690 params_sent_thistime, data_sent_thistime, useable_space));
691 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
692 params_to_send, data_to_send, paramsize, datasize));
694 /* Send the packet */
695 show_msg(outbuf);
696 if (!send_smb(smbd_server_fd(),outbuf))
697 exit_server("send_trans2_replies: send_smb failed.");
699 pp += params_sent_thistime;
700 pd += data_sent_thistime;
702 params_to_send -= params_sent_thistime;
703 data_to_send -= data_sent_thistime;
705 /* Sanity check */
706 if(params_to_send < 0 || data_to_send < 0) {
707 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
708 params_to_send, data_to_send));
709 return -1;
713 return 0;
716 /****************************************************************************
717 Reply to a TRANSACT2_OPEN.
718 ****************************************************************************/
720 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
721 char **pparams, int total_params, char **ppdata, int total_data,
722 unsigned int max_data_bytes)
724 char *params = *pparams;
725 char *pdata = *ppdata;
726 int deny_mode;
727 int32 open_attr;
728 BOOL oplock_request;
729 #if 0
730 BOOL return_additional_info;
731 int16 open_sattr;
732 time_t open_time;
733 #endif
734 int open_ofun;
735 uint32 open_size;
736 char *pname;
737 pstring fname;
738 SMB_OFF_T size=0;
739 int fattr=0,mtime=0;
740 SMB_INO_T inode = 0;
741 SMB_STRUCT_STAT sbuf;
742 int smb_action = 0;
743 BOOL bad_path = False;
744 files_struct *fsp;
745 TALLOC_CTX *ctx = NULL;
746 struct ea_list *ea_list = NULL;
747 uint16 flags = 0;
748 NTSTATUS status;
749 uint32 access_mask;
750 uint32 share_mode;
751 uint32 create_disposition;
752 uint32 create_options = 0;
755 * Ensure we have enough parameters to perform the operation.
758 if (total_params < 29) {
759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
762 flags = SVAL(params, 0);
763 deny_mode = SVAL(params, 2);
764 open_attr = SVAL(params,6);
765 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
766 if (oplock_request) {
767 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
770 #if 0
771 return_additional_info = BITSETW(params,0);
772 open_sattr = SVAL(params, 4);
773 open_time = make_unix_date3(params+8);
774 #endif
775 open_ofun = SVAL(params,12);
776 open_size = IVAL(params,14);
777 pname = &params[28];
779 if (IS_IPC(conn)) {
780 return(ERROR_DOS(ERRSRV,ERRaccess));
783 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
784 if (!NT_STATUS_IS_OK(status)) {
785 return ERROR_NT(status);
788 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
789 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
790 (unsigned int)open_ofun, open_size));
792 /* XXXX we need to handle passed times, sattr and flags */
794 unix_convert(fname,conn,0,&bad_path,&sbuf);
795 if (bad_path) {
796 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
799 if (!check_name(fname,conn)) {
800 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
803 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
804 &access_mask,
805 &share_mode,
806 &create_disposition,
807 &create_options)) {
808 return ERROR_DOS(ERRDOS, ERRbadaccess);
811 /* Any data in this call is an EA list. */
812 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
813 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
816 if (total_data != 4) {
817 if (total_data < 10) {
818 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
821 if (IVAL(pdata,0) > total_data) {
822 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
823 IVAL(pdata,0), (unsigned int)total_data));
824 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
827 ctx = talloc_init("TRANS2_OPEN_SET_EA");
828 if (!ctx) {
829 return ERROR_NT(NT_STATUS_NO_MEMORY);
831 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
832 if (!ea_list) {
833 talloc_destroy(ctx);
834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
836 } else if (IVAL(pdata,0) != 4) {
837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
840 fsp = open_file_ntcreate(conn,fname,&sbuf,
841 access_mask,
842 share_mode,
843 create_disposition,
844 create_options,
845 open_attr,
846 oplock_request,
847 &smb_action);
849 if (!fsp) {
850 talloc_destroy(ctx);
851 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
852 /* We have re-scheduled this call. */
853 return -1;
855 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
858 size = get_file_size(sbuf);
859 fattr = dos_mode(conn,fname,&sbuf);
860 mtime = sbuf.st_mtime;
861 inode = sbuf.st_ino;
862 if (fattr & aDIR) {
863 talloc_destroy(ctx);
864 close_file(fsp,ERROR_CLOSE);
865 return(ERROR_DOS(ERRDOS,ERRnoaccess));
868 /* Save the requested allocation size. */
869 /* Allocate space for the file if a size hint is supplied */
870 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
871 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
872 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
873 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
874 if (fsp->is_directory) {
875 close_file(fsp,ERROR_CLOSE);
876 /* Can't set allocation size on a directory. */
877 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
879 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
880 close_file(fsp,ERROR_CLOSE);
881 return ERROR_NT(NT_STATUS_DISK_FULL);
884 /* Adjust size here to return the right size in the reply.
885 Windows does it this way. */
886 size = fsp->initial_allocation_size;
887 } else {
888 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
892 if (total_data && smb_action == FILE_WAS_CREATED) {
893 status = set_ea(conn, fsp, fname, ea_list);
894 talloc_destroy(ctx);
895 if (!NT_STATUS_IS_OK(status)) {
896 close_file(fsp,ERROR_CLOSE);
897 return ERROR_NT(status);
901 /* Realloc the size of parameters and data we will return */
902 *pparams = SMB_REALLOC(*pparams, 30);
903 if(*pparams == NULL ) {
904 return ERROR_NT(NT_STATUS_NO_MEMORY);
906 params = *pparams;
908 SSVAL(params,0,fsp->fnum);
909 SSVAL(params,2,open_attr);
910 srv_put_dos_date2(params,4, mtime);
911 SIVAL(params,8, (uint32)size);
912 SSVAL(params,12,deny_mode);
913 SSVAL(params,14,0); /* open_type - file or directory. */
914 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
916 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
917 smb_action |= EXTENDED_OPLOCK_GRANTED;
920 SSVAL(params,18,smb_action);
923 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
925 SIVAL(params,20,inode);
926 SSVAL(params,24,0); /* Padding. */
927 if (flags & 8) {
928 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
929 SIVAL(params, 26, ea_size);
930 } else {
931 SIVAL(params, 26, 0);
934 /* Send the required number of replies */
935 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
937 return -1;
940 /*********************************************************
941 Routine to check if a given string matches exactly.
942 as a special case a mask of "." does NOT match. That
943 is required for correct wildcard semantics
944 Case can be significant or not.
945 **********************************************************/
947 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
949 if (mask[0] == '.' && mask[1] == 0)
950 return False;
951 if (case_sig)
952 return strcmp(str,mask)==0;
953 if (StrCaseCmp(str,mask) != 0) {
954 return False;
956 if (ms_has_wild(str)) {
957 return False;
959 return True;
962 /****************************************************************************
963 Return the filetype for UNIX extensions.
964 ****************************************************************************/
966 static uint32 unix_filetype(mode_t mode)
968 if(S_ISREG(mode))
969 return UNIX_TYPE_FILE;
970 else if(S_ISDIR(mode))
971 return UNIX_TYPE_DIR;
972 #ifdef S_ISLNK
973 else if(S_ISLNK(mode))
974 return UNIX_TYPE_SYMLINK;
975 #endif
976 #ifdef S_ISCHR
977 else if(S_ISCHR(mode))
978 return UNIX_TYPE_CHARDEV;
979 #endif
980 #ifdef S_ISBLK
981 else if(S_ISBLK(mode))
982 return UNIX_TYPE_BLKDEV;
983 #endif
984 #ifdef S_ISFIFO
985 else if(S_ISFIFO(mode))
986 return UNIX_TYPE_FIFO;
987 #endif
988 #ifdef S_ISSOCK
989 else if(S_ISSOCK(mode))
990 return UNIX_TYPE_SOCKET;
991 #endif
993 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
994 return UNIX_TYPE_UNKNOWN;
997 /****************************************************************************
998 Map wire perms onto standard UNIX permissions. Obey share restrictions.
999 ****************************************************************************/
1001 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1003 mode_t ret = 0;
1005 if (perms == SMB_MODE_NO_CHANGE)
1006 return pst->st_mode;
1008 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1009 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1010 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1011 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1012 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1013 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1014 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1015 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1016 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1017 #ifdef S_ISVTX
1018 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1019 #endif
1020 #ifdef S_ISGID
1021 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1022 #endif
1023 #ifdef S_ISUID
1024 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1025 #endif
1027 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1028 ret &= lp_dir_mask(SNUM(conn));
1029 /* Add in force bits */
1030 ret |= lp_force_dir_mode(SNUM(conn));
1031 } else {
1032 /* Apply mode mask */
1033 ret &= lp_create_mask(SNUM(conn));
1034 /* Add in force bits */
1035 ret |= lp_force_create_mode(SNUM(conn));
1038 return ret;
1041 /****************************************************************************
1042 Get a level dependent lanman2 dir entry.
1043 ****************************************************************************/
1045 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1046 void *inbuf, void *outbuf,
1047 char *path_mask,uint32 dirtype,int info_level,
1048 int requires_resume_key,
1049 BOOL dont_descend,char **ppdata,
1050 char *base_data, int space_remaining,
1051 BOOL *out_of_space, BOOL *got_exact_match,
1052 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1054 const char *dname;
1055 BOOL found = False;
1056 SMB_STRUCT_STAT sbuf;
1057 pstring mask;
1058 pstring pathreal;
1059 pstring fname;
1060 char *p, *q, *pdata = *ppdata;
1061 uint32 reskey=0;
1062 long prev_dirpos=0;
1063 uint32 mode=0;
1064 SMB_OFF_T file_size = 0;
1065 SMB_BIG_UINT allocation_size = 0;
1066 uint32 len;
1067 time_t mdate=0, adate=0, cdate=0;
1068 char *nameptr;
1069 char *last_entry_ptr;
1070 BOOL was_8_3;
1071 uint32 nt_extmode; /* Used for NT connections instead of mode */
1072 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1073 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1075 *fname = 0;
1076 *out_of_space = False;
1077 *got_exact_match = False;
1079 if (!conn->dirptr)
1080 return(False);
1082 p = strrchr_m(path_mask,'/');
1083 if(p != NULL) {
1084 if(p[1] == '\0')
1085 pstrcpy(mask,"*.*");
1086 else
1087 pstrcpy(mask, p+1);
1088 } else
1089 pstrcpy(mask, path_mask);
1092 while (!found) {
1093 BOOL got_match;
1094 /* Needed if we run out of space */
1095 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1096 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1099 * Due to bugs in NT client redirectors we are not using
1100 * resume keys any more - set them to zero.
1101 * Check out the related comments in findfirst/findnext.
1102 * JRA.
1105 reskey = 0;
1107 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1108 (long)conn->dirptr,curr_dirpos));
1110 if (!dname)
1111 return(False);
1113 pstrcpy(fname,dname);
1115 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1116 got_match = mask_match(fname, mask, conn->case_sensitive);
1118 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1121 * It turns out that NT matches wildcards against
1122 * both long *and* short names. This may explain some
1123 * of the wildcard wierdness from old DOS clients
1124 * that some people have been seeing.... JRA.
1127 pstring newname;
1128 pstrcpy( newname, fname);
1129 mangle_map( newname, True, False, SNUM(conn));
1130 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1131 got_match = mask_match(newname, mask, conn->case_sensitive);
1134 if(got_match) {
1135 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1136 if (dont_descend && !isdots)
1137 continue;
1139 pstrcpy(pathreal,conn->dirpath);
1140 if(needslash)
1141 pstrcat(pathreal,"/");
1142 pstrcat(pathreal,dname);
1144 if (INFO_LEVEL_IS_UNIX(info_level)) {
1145 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1146 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1147 pathreal,strerror(errno)));
1148 continue;
1150 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1152 /* Needed to show the msdfs symlinks as
1153 * directories */
1155 if(lp_host_msdfs() &&
1156 lp_msdfs_root(SNUM(conn)) &&
1157 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1158 &sbuf)) {
1160 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1161 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1163 } else {
1165 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1166 pathreal,strerror(errno)));
1167 continue;
1171 mode = dos_mode(conn,pathreal,&sbuf);
1173 if (!dir_check_ftype(conn,mode,dirtype)) {
1174 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1175 continue;
1178 if (!(mode & aDIR))
1179 file_size = get_file_size(sbuf);
1180 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1181 mdate = sbuf.st_mtime;
1182 adate = sbuf.st_atime;
1183 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1185 if (lp_dos_filetime_resolution(SNUM(conn))) {
1186 cdate &= ~1;
1187 mdate &= ~1;
1188 adate &= ~1;
1192 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1194 found = True;
1196 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1200 mangle_map(fname,False,True,SNUM(conn));
1202 p = pdata;
1203 last_entry_ptr = p;
1205 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1207 switch (info_level) {
1208 case SMB_FIND_INFO_STANDARD:
1209 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1210 if(requires_resume_key) {
1211 SIVAL(p,0,reskey);
1212 p += 4;
1214 srv_put_dos_date2(p,0,cdate);
1215 srv_put_dos_date2(p,4,adate);
1216 srv_put_dos_date2(p,8,mdate);
1217 SIVAL(p,12,(uint32)file_size);
1218 SIVAL(p,16,(uint32)allocation_size);
1219 SSVAL(p,20,mode);
1220 p += 23;
1221 nameptr = p;
1222 p += align_string(outbuf, p, 0);
1223 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1224 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1225 if (len > 2) {
1226 SCVAL(nameptr, -1, len - 2);
1227 } else {
1228 SCVAL(nameptr, -1, 0);
1230 } else {
1231 if (len > 1) {
1232 SCVAL(nameptr, -1, len - 1);
1233 } else {
1234 SCVAL(nameptr, -1, 0);
1237 p += len;
1238 break;
1240 case SMB_FIND_EA_SIZE:
1241 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1242 if(requires_resume_key) {
1243 SIVAL(p,0,reskey);
1244 p += 4;
1246 srv_put_dos_date2(p,0,cdate);
1247 srv_put_dos_date2(p,4,adate);
1248 srv_put_dos_date2(p,8,mdate);
1249 SIVAL(p,12,(uint32)file_size);
1250 SIVAL(p,16,(uint32)allocation_size);
1251 SSVAL(p,20,mode);
1253 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1254 SIVAL(p,22,ea_size); /* Extended attributes */
1256 p += 27;
1257 nameptr = p - 1;
1258 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1259 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1260 if (len > 2) {
1261 len -= 2;
1262 } else {
1263 len = 0;
1265 } else {
1266 if (len > 1) {
1267 len -= 1;
1268 } else {
1269 len = 0;
1272 SCVAL(nameptr,0,len);
1273 p += len;
1274 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1275 break;
1277 case SMB_FIND_EA_LIST:
1279 struct ea_list *file_list = NULL;
1280 size_t ea_len = 0;
1282 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1283 if (!name_list) {
1284 return False;
1286 if(requires_resume_key) {
1287 SIVAL(p,0,reskey);
1288 p += 4;
1290 srv_put_dos_date2(p,0,cdate);
1291 srv_put_dos_date2(p,4,adate);
1292 srv_put_dos_date2(p,8,mdate);
1293 SIVAL(p,12,(uint32)file_size);
1294 SIVAL(p,16,(uint32)allocation_size);
1295 SSVAL(p,20,mode);
1296 p += 22; /* p now points to the EA area. */
1298 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1299 name_list = ea_list_union(name_list, file_list, &ea_len);
1301 /* We need to determine if this entry will fit in the space available. */
1302 /* Max string size is 255 bytes. */
1303 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1304 /* Move the dirptr back to prev_dirpos */
1305 dptr_SeekDir(conn->dirptr, prev_dirpos);
1306 *out_of_space = True;
1307 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1308 return False; /* Not finished - just out of space */
1311 /* Push the ea_data followed by the name. */
1312 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1313 nameptr = p;
1314 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1315 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1316 if (len > 2) {
1317 len -= 2;
1318 } else {
1319 len = 0;
1321 } else {
1322 if (len > 1) {
1323 len -= 1;
1324 } else {
1325 len = 0;
1328 SCVAL(nameptr,0,len);
1329 p += len + 1;
1330 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1331 break;
1334 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1335 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1336 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1337 p += 4;
1338 SIVAL(p,0,reskey); p += 4;
1339 put_long_date(p,cdate); p += 8;
1340 put_long_date(p,adate); p += 8;
1341 put_long_date(p,mdate); p += 8;
1342 put_long_date(p,mdate); p += 8;
1343 SOFF_T(p,0,file_size); p += 8;
1344 SOFF_T(p,0,allocation_size); p += 8;
1345 SIVAL(p,0,nt_extmode); p += 4;
1346 q = p; p += 4; /* q is placeholder for name length. */
1348 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1349 SIVAL(p,0,ea_size); /* Extended attributes */
1350 p += 4;
1352 /* Clear the short name buffer. This is
1353 * IMPORTANT as not doing so will trigger
1354 * a Win2k client bug. JRA.
1356 if (!was_8_3 && check_mangled_names) {
1357 pstring mangled_name;
1358 pstrcpy(mangled_name, fname);
1359 mangle_map(mangled_name,True,True,SNUM(conn));
1360 mangled_name[12] = 0;
1361 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1362 if (len < 24) {
1363 memset(p + 2 + len,'\0',24 - len);
1365 SSVAL(p, 0, len);
1366 } else {
1367 memset(p,'\0',26);
1369 p += 2 + 24;
1370 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1371 SIVAL(q,0,len);
1372 p += len;
1373 SIVAL(p,0,0); /* Ensure any padding is null. */
1374 len = PTR_DIFF(p, pdata);
1375 len = (len + 3) & ~3;
1376 SIVAL(pdata,0,len);
1377 p = pdata + len;
1378 break;
1380 case SMB_FIND_FILE_DIRECTORY_INFO:
1381 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1382 p += 4;
1383 SIVAL(p,0,reskey); p += 4;
1384 put_long_date(p,cdate); p += 8;
1385 put_long_date(p,adate); p += 8;
1386 put_long_date(p,mdate); p += 8;
1387 put_long_date(p,mdate); p += 8;
1388 SOFF_T(p,0,file_size); p += 8;
1389 SOFF_T(p,0,allocation_size); p += 8;
1390 SIVAL(p,0,nt_extmode); p += 4;
1391 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1392 SIVAL(p,0,len);
1393 p += 4 + len;
1394 SIVAL(p,0,0); /* Ensure any padding is null. */
1395 len = PTR_DIFF(p, pdata);
1396 len = (len + 3) & ~3;
1397 SIVAL(pdata,0,len);
1398 p = pdata + len;
1399 break;
1401 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1402 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1403 p += 4;
1404 SIVAL(p,0,reskey); p += 4;
1405 put_long_date(p,cdate); p += 8;
1406 put_long_date(p,adate); p += 8;
1407 put_long_date(p,mdate); p += 8;
1408 put_long_date(p,mdate); p += 8;
1409 SOFF_T(p,0,file_size); p += 8;
1410 SOFF_T(p,0,allocation_size); p += 8;
1411 SIVAL(p,0,nt_extmode); p += 4;
1412 q = p; p += 4; /* q is placeholder for name length. */
1414 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1415 SIVAL(p,0,ea_size); /* Extended attributes */
1416 p +=4;
1418 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1419 SIVAL(q, 0, len);
1420 p += len;
1422 SIVAL(p,0,0); /* Ensure any padding is null. */
1423 len = PTR_DIFF(p, pdata);
1424 len = (len + 3) & ~3;
1425 SIVAL(pdata,0,len);
1426 p = pdata + len;
1427 break;
1429 case SMB_FIND_FILE_NAMES_INFO:
1430 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1431 p += 4;
1432 SIVAL(p,0,reskey); p += 4;
1433 p += 4;
1434 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1435 acl on a dir (tridge) */
1436 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1437 SIVAL(p, -4, len);
1438 p += len;
1439 SIVAL(p,0,0); /* Ensure any padding is null. */
1440 len = PTR_DIFF(p, pdata);
1441 len = (len + 3) & ~3;
1442 SIVAL(pdata,0,len);
1443 p = pdata + len;
1444 break;
1446 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1447 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1448 p += 4;
1449 SIVAL(p,0,reskey); p += 4;
1450 put_long_date(p,cdate); p += 8;
1451 put_long_date(p,adate); p += 8;
1452 put_long_date(p,mdate); p += 8;
1453 put_long_date(p,mdate); p += 8;
1454 SOFF_T(p,0,file_size); p += 8;
1455 SOFF_T(p,0,allocation_size); p += 8;
1456 SIVAL(p,0,nt_extmode); p += 4;
1457 q = p; p += 4; /* q is placeholder for name length. */
1459 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1460 SIVAL(p,0,ea_size); /* Extended attributes */
1461 p +=4;
1463 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1464 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1465 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1466 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1467 SIVAL(q, 0, len);
1468 p += len;
1469 SIVAL(p,0,0); /* Ensure any padding is null. */
1470 len = PTR_DIFF(p, pdata);
1471 len = (len + 3) & ~3;
1472 SIVAL(pdata,0,len);
1473 p = pdata + len;
1474 break;
1476 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1477 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1478 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1479 p += 4;
1480 SIVAL(p,0,reskey); p += 4;
1481 put_long_date(p,cdate); p += 8;
1482 put_long_date(p,adate); p += 8;
1483 put_long_date(p,mdate); p += 8;
1484 put_long_date(p,mdate); p += 8;
1485 SOFF_T(p,0,file_size); p += 8;
1486 SOFF_T(p,0,allocation_size); p += 8;
1487 SIVAL(p,0,nt_extmode); p += 4;
1488 q = p; p += 4; /* q is placeholder for name length */
1490 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1491 SIVAL(p,0,ea_size); /* Extended attributes */
1492 p +=4;
1494 /* Clear the short name buffer. This is
1495 * IMPORTANT as not doing so will trigger
1496 * a Win2k client bug. JRA.
1498 if (!was_8_3 && check_mangled_names) {
1499 pstring mangled_name;
1500 pstrcpy(mangled_name, fname);
1501 mangle_map(mangled_name,True,True,SNUM(conn));
1502 mangled_name[12] = 0;
1503 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1504 SSVAL(p, 0, len);
1505 if (len < 24) {
1506 memset(p + 2 + len,'\0',24 - len);
1508 SSVAL(p, 0, len);
1509 } else {
1510 memset(p,'\0',26);
1512 p += 26;
1513 SSVAL(p,0,0); p += 2; /* Reserved ? */
1514 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1515 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1516 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1517 SIVAL(q,0,len);
1518 p += len;
1519 SIVAL(p,0,0); /* Ensure any padding is null. */
1520 len = PTR_DIFF(p, pdata);
1521 len = (len + 3) & ~3;
1522 SIVAL(pdata,0,len);
1523 p = pdata + len;
1524 break;
1526 /* CIFS UNIX Extension. */
1528 case SMB_FIND_FILE_UNIX:
1529 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1530 p+= 4;
1531 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1533 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1534 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1535 p+= 8;
1537 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1538 p+= 8;
1540 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1541 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1542 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1543 p+= 24;
1545 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1546 SIVAL(p,4,0);
1547 p+= 8;
1549 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1550 SIVAL(p,4,0);
1551 p+= 8;
1553 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1554 p+= 4;
1556 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1557 SIVAL(p,4,0);
1558 p+= 8;
1560 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1561 SIVAL(p,4,0);
1562 p+= 8;
1564 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1565 p+= 8;
1567 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1568 SIVAL(p,4,0);
1569 p+= 8;
1571 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1572 SIVAL(p,4,0);
1573 p+= 8;
1575 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1576 p += len;
1577 SIVAL(p,0,0); /* Ensure any padding is null. */
1579 len = PTR_DIFF(p, pdata);
1580 len = (len + 3) & ~3;
1581 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1582 p = pdata + len;
1583 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1585 break;
1587 default:
1588 return(False);
1592 if (PTR_DIFF(p,pdata) > space_remaining) {
1593 /* Move the dirptr back to prev_dirpos */
1594 dptr_SeekDir(conn->dirptr, prev_dirpos);
1595 *out_of_space = True;
1596 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1597 return False; /* Not finished - just out of space */
1600 /* Setup the last entry pointer, as an offset from base_data */
1601 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1602 /* Advance the data pointer to the next slot */
1603 *ppdata = p;
1605 return(found);
1608 /****************************************************************************
1609 Reply to a TRANS2_FINDFIRST.
1610 ****************************************************************************/
1612 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1613 char **pparams, int total_params, char **ppdata, int total_data,
1614 unsigned int max_data_bytes)
1616 /* We must be careful here that we don't return more than the
1617 allowed number of data bytes. If this means returning fewer than
1618 maxentries then so be it. We assume that the redirector has
1619 enough room for the fixed number of parameter bytes it has
1620 requested. */
1621 char *params = *pparams;
1622 char *pdata = *ppdata;
1623 uint32 dirtype = SVAL(params,0);
1624 int maxentries = SVAL(params,2);
1625 uint16 findfirst_flags = SVAL(params,4);
1626 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1627 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1628 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1629 int info_level = SVAL(params,6);
1630 pstring directory;
1631 pstring mask;
1632 char *p;
1633 int last_entry_off=0;
1634 int dptr_num = -1;
1635 int numentries = 0;
1636 int i;
1637 BOOL finished = False;
1638 BOOL dont_descend = False;
1639 BOOL out_of_space = False;
1640 int space_remaining;
1641 BOOL bad_path = False;
1642 BOOL mask_contains_wcard = False;
1643 SMB_STRUCT_STAT sbuf;
1644 TALLOC_CTX *ea_ctx = NULL;
1645 struct ea_list *ea_list = NULL;
1646 NTSTATUS ntstatus = NT_STATUS_OK;
1648 if (total_params < 12) {
1649 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1652 *directory = *mask = 0;
1654 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1655 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1656 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1657 info_level, max_data_bytes));
1659 if (!maxentries) {
1660 /* W2K3 seems to treat zero as 1. */
1661 maxentries = 1;
1664 switch (info_level) {
1665 case SMB_FIND_INFO_STANDARD:
1666 case SMB_FIND_EA_SIZE:
1667 case SMB_FIND_EA_LIST:
1668 case SMB_FIND_FILE_DIRECTORY_INFO:
1669 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1670 case SMB_FIND_FILE_NAMES_INFO:
1671 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1672 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1673 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1674 break;
1675 case SMB_FIND_FILE_UNIX:
1676 if (!lp_unix_extensions()) {
1677 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1679 break;
1680 default:
1681 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1684 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1685 if (!NT_STATUS_IS_OK(ntstatus)) {
1686 return ERROR_NT(ntstatus);
1689 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1691 unix_convert(directory,conn,0,&bad_path,&sbuf);
1692 if (bad_path) {
1693 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1695 if(!check_name(directory,conn)) {
1696 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1699 p = strrchr_m(directory,'/');
1700 if(p == NULL) {
1701 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1702 if((directory[0] == '.') && (directory[1] == '\0')) {
1703 pstrcpy(mask,"*");
1704 mask_contains_wcard = True;
1705 } else {
1706 pstrcpy(mask,directory);
1708 pstrcpy(directory,"./");
1709 } else {
1710 pstrcpy(mask,p+1);
1711 *p = 0;
1714 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1716 if (info_level == SMB_FIND_EA_LIST) {
1717 uint32 ea_size;
1719 if (total_data < 4) {
1720 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1723 ea_size = IVAL(pdata,0);
1724 if (ea_size != total_data) {
1725 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1726 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1727 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1730 if (!lp_ea_support(SNUM(conn))) {
1731 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1734 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1735 return ERROR_NT(NT_STATUS_NO_MEMORY);
1738 /* Pull out the list of names. */
1739 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1740 if (!ea_list) {
1741 talloc_destroy(ea_ctx);
1742 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1746 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1747 if(*ppdata == NULL ) {
1748 talloc_destroy(ea_ctx);
1749 return ERROR_NT(NT_STATUS_NO_MEMORY);
1751 pdata = *ppdata;
1753 /* Realloc the params space */
1754 *pparams = SMB_REALLOC(*pparams, 10);
1755 if (*pparams == NULL) {
1756 talloc_destroy(ea_ctx);
1757 return ERROR_NT(NT_STATUS_NO_MEMORY);
1759 params = *pparams;
1761 /* Save the wildcard match and attribs we are using on this directory -
1762 needed as lanman2 assumes these are being saved between calls */
1764 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1765 if (dptr_num < 0) {
1766 talloc_destroy(ea_ctx);
1767 return(UNIXERROR(ERRDOS,ERRbadfile));
1770 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1772 /* We don't need to check for VOL here as this is returned by
1773 a different TRANS2 call. */
1775 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1776 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1777 dont_descend = True;
1779 p = pdata;
1780 space_remaining = max_data_bytes;
1781 out_of_space = False;
1783 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1784 BOOL got_exact_match = False;
1786 /* this is a heuristic to avoid seeking the dirptr except when
1787 absolutely necessary. It allows for a filename of about 40 chars */
1788 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1789 out_of_space = True;
1790 finished = False;
1791 } else {
1792 finished = !get_lanman2_dir_entry(conn,
1793 inbuf, outbuf,
1794 mask,dirtype,info_level,
1795 requires_resume_key,dont_descend,
1796 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1797 &last_entry_off, ea_list, ea_ctx);
1800 if (finished && out_of_space)
1801 finished = False;
1803 if (!finished && !out_of_space)
1804 numentries++;
1807 * As an optimisation if we know we aren't looking
1808 * for a wildcard name (ie. the name matches the wildcard exactly)
1809 * then we can finish on any (first) match.
1810 * This speeds up large directory searches. JRA.
1813 if(got_exact_match)
1814 finished = True;
1816 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1819 talloc_destroy(ea_ctx);
1821 /* Check if we can close the dirptr */
1822 if(close_after_first || (finished && close_if_end)) {
1823 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1824 dptr_close(&dptr_num);
1828 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1829 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1830 * the protocol level is less than NT1. Tested with smbclient. JRA.
1831 * This should fix the OS/2 client bug #2335.
1834 if(numentries == 0) {
1835 dptr_close(&dptr_num);
1836 if (Protocol < PROTOCOL_NT1) {
1837 return ERROR_DOS(ERRDOS,ERRnofiles);
1838 } else {
1839 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1843 /* At this point pdata points to numentries directory entries. */
1845 /* Set up the return parameter block */
1846 SSVAL(params,0,dptr_num);
1847 SSVAL(params,2,numentries);
1848 SSVAL(params,4,finished);
1849 SSVAL(params,6,0); /* Never an EA error */
1850 SSVAL(params,8,last_entry_off);
1852 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1854 if ((! *directory) && dptr_path(dptr_num))
1855 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1857 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1858 smb_fn_name(CVAL(inbuf,smb_com)),
1859 mask, directory, dirtype, numentries ) );
1862 * Force a name mangle here to ensure that the
1863 * mask as an 8.3 name is top of the mangled cache.
1864 * The reasons for this are subtle. Don't remove
1865 * this code unless you know what you are doing
1866 * (see PR#13758). JRA.
1869 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1870 mangle_map(mask, True, True, SNUM(conn));
1872 return(-1);
1875 /****************************************************************************
1876 Reply to a TRANS2_FINDNEXT.
1877 ****************************************************************************/
1879 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1880 char **pparams, int total_params, char **ppdata, int total_data,
1881 unsigned int max_data_bytes)
1883 /* We must be careful here that we don't return more than the
1884 allowed number of data bytes. If this means returning fewer than
1885 maxentries then so be it. We assume that the redirector has
1886 enough room for the fixed number of parameter bytes it has
1887 requested. */
1888 char *params = *pparams;
1889 char *pdata = *ppdata;
1890 int dptr_num = SVAL(params,0);
1891 int maxentries = SVAL(params,2);
1892 uint16 info_level = SVAL(params,4);
1893 uint32 resume_key = IVAL(params,6);
1894 uint16 findnext_flags = SVAL(params,10);
1895 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1896 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1897 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1898 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1899 BOOL mask_contains_wcard = False;
1900 pstring resume_name;
1901 pstring mask;
1902 pstring directory;
1903 char *p;
1904 uint16 dirtype;
1905 int numentries = 0;
1906 int i, last_entry_off=0;
1907 BOOL finished = False;
1908 BOOL dont_descend = False;
1909 BOOL out_of_space = False;
1910 int space_remaining;
1911 TALLOC_CTX *ea_ctx = NULL;
1912 struct ea_list *ea_list = NULL;
1913 NTSTATUS ntstatus = NT_STATUS_OK;
1915 if (total_params < 12) {
1916 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1919 *mask = *directory = *resume_name = 0;
1921 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1922 if (!NT_STATUS_IS_OK(ntstatus)) {
1923 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1924 complain (it thinks we're asking for the directory above the shared
1925 path or an invalid name). Catch this as the resume name is only compared, never used in
1926 a file access. JRA. */
1927 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1928 pstrcpy(resume_name, "..");
1929 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1930 pstrcpy(resume_name, ".");
1931 } else {
1932 return ERROR_NT(ntstatus);
1936 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1937 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1938 resume_key = %d resume name = %s continue=%d level = %d\n",
1939 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1940 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1942 if (!maxentries) {
1943 /* W2K3 seems to treat zero as 1. */
1944 maxentries = 1;
1947 switch (info_level) {
1948 case SMB_FIND_INFO_STANDARD:
1949 case SMB_FIND_EA_SIZE:
1950 case SMB_FIND_EA_LIST:
1951 case SMB_FIND_FILE_DIRECTORY_INFO:
1952 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1953 case SMB_FIND_FILE_NAMES_INFO:
1954 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1955 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1956 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1957 break;
1958 case SMB_FIND_FILE_UNIX:
1959 if (!lp_unix_extensions()) {
1960 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1962 break;
1963 default:
1964 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1967 if (info_level == SMB_FIND_EA_LIST) {
1968 uint32 ea_size;
1970 if (total_data < 4) {
1971 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1974 ea_size = IVAL(pdata,0);
1975 if (ea_size != total_data) {
1976 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1977 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1978 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1981 if (!lp_ea_support(SNUM(conn))) {
1982 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1985 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1986 return ERROR_NT(NT_STATUS_NO_MEMORY);
1989 /* Pull out the list of names. */
1990 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1991 if (!ea_list) {
1992 talloc_destroy(ea_ctx);
1993 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1997 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1998 if(*ppdata == NULL) {
1999 talloc_destroy(ea_ctx);
2000 return ERROR_NT(NT_STATUS_NO_MEMORY);
2003 pdata = *ppdata;
2005 /* Realloc the params space */
2006 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2007 if(*pparams == NULL ) {
2008 talloc_destroy(ea_ctx);
2009 return ERROR_NT(NT_STATUS_NO_MEMORY);
2012 params = *pparams;
2014 /* Check that the dptr is valid */
2015 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2016 talloc_destroy(ea_ctx);
2017 return ERROR_DOS(ERRDOS,ERRnofiles);
2020 string_set(&conn->dirpath,dptr_path(dptr_num));
2022 /* Get the wildcard mask from the dptr */
2023 if((p = dptr_wcard(dptr_num))== NULL) {
2024 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2025 talloc_destroy(ea_ctx);
2026 return ERROR_DOS(ERRDOS,ERRnofiles);
2029 pstrcpy(mask, p);
2030 pstrcpy(directory,conn->dirpath);
2032 /* Get the attr mask from the dptr */
2033 dirtype = dptr_attr(dptr_num);
2035 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2036 dptr_num, mask, dirtype,
2037 (long)conn->dirptr,
2038 dptr_TellDir(conn->dirptr)));
2040 /* We don't need to check for VOL here as this is returned by
2041 a different TRANS2 call. */
2043 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2044 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2045 dont_descend = True;
2047 p = pdata;
2048 space_remaining = max_data_bytes;
2049 out_of_space = False;
2052 * Seek to the correct position. We no longer use the resume key but
2053 * depend on the last file name instead.
2056 if(*resume_name && !continue_bit) {
2057 SMB_STRUCT_STAT st;
2059 long current_pos = 0;
2061 * Remember, mangle_map is called by
2062 * get_lanman2_dir_entry(), so the resume name
2063 * could be mangled. Ensure we check the unmangled name.
2066 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2067 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2071 * Fix for NT redirector problem triggered by resume key indexes
2072 * changing between directory scans. We now return a resume key of 0
2073 * and instead look for the filename to continue from (also given
2074 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2075 * findfirst/findnext (as is usual) then the directory pointer
2076 * should already be at the correct place.
2079 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2080 } /* end if resume_name && !continue_bit */
2082 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2083 BOOL got_exact_match = False;
2085 /* this is a heuristic to avoid seeking the dirptr except when
2086 absolutely necessary. It allows for a filename of about 40 chars */
2087 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2088 out_of_space = True;
2089 finished = False;
2090 } else {
2091 finished = !get_lanman2_dir_entry(conn,
2092 inbuf, outbuf,
2093 mask,dirtype,info_level,
2094 requires_resume_key,dont_descend,
2095 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2096 &last_entry_off, ea_list, ea_ctx);
2099 if (finished && out_of_space)
2100 finished = False;
2102 if (!finished && !out_of_space)
2103 numentries++;
2106 * As an optimisation if we know we aren't looking
2107 * for a wildcard name (ie. the name matches the wildcard exactly)
2108 * then we can finish on any (first) match.
2109 * This speeds up large directory searches. JRA.
2112 if(got_exact_match)
2113 finished = True;
2115 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2118 talloc_destroy(ea_ctx);
2120 /* Check if we can close the dirptr */
2121 if(close_after_request || (finished && close_if_end)) {
2122 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2123 dptr_close(&dptr_num); /* This frees up the saved mask */
2126 /* Set up the return parameter block */
2127 SSVAL(params,0,numentries);
2128 SSVAL(params,2,finished);
2129 SSVAL(params,4,0); /* Never an EA error */
2130 SSVAL(params,6,last_entry_off);
2132 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2134 if ((! *directory) && dptr_path(dptr_num))
2135 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2137 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2138 smb_fn_name(CVAL(inbuf,smb_com)),
2139 mask, directory, dirtype, numentries ) );
2141 return(-1);
2144 /****************************************************************************
2145 Reply to a TRANS2_QFSINFO (query filesystem info).
2146 ****************************************************************************/
2148 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2149 char **pparams, int total_params, char **ppdata, int total_data,
2150 unsigned int max_data_bytes)
2152 char *pdata = *ppdata;
2153 char *params = *pparams;
2154 uint16 info_level = SVAL(params,0);
2155 int data_len, len;
2156 SMB_STRUCT_STAT st;
2157 char *vname = volume_label(SNUM(conn));
2158 int snum = SNUM(conn);
2159 char *fstype = lp_fstype(SNUM(conn));
2160 int quota_flag = 0;
2162 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2164 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2165 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2166 return ERROR_DOS(ERRSRV,ERRinvdevice);
2169 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2170 if (*ppdata == NULL ) {
2171 return ERROR_NT(NT_STATUS_NO_MEMORY);
2174 pdata = *ppdata;
2175 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2177 switch (info_level) {
2178 case SMB_INFO_ALLOCATION:
2180 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2181 data_len = 18;
2182 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2183 return(UNIXERROR(ERRHRD,ERRgeneral));
2186 block_size = lp_block_size(snum);
2187 if (bsize < block_size) {
2188 SMB_BIG_UINT factor = block_size/bsize;
2189 bsize = block_size;
2190 dsize /= factor;
2191 dfree /= factor;
2193 if (bsize > block_size) {
2194 SMB_BIG_UINT factor = bsize/block_size;
2195 bsize = block_size;
2196 dsize *= factor;
2197 dfree *= factor;
2199 bytes_per_sector = 512;
2200 sectors_per_unit = bsize/bytes_per_sector;
2202 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2203 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2204 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2206 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2207 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2208 SIVAL(pdata,l1_cUnit,dsize);
2209 SIVAL(pdata,l1_cUnitAvail,dfree);
2210 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2211 break;
2214 case SMB_INFO_VOLUME:
2215 /* Return volume name */
2217 * Add volume serial number - hash of a combination of
2218 * the called hostname and the service name.
2220 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2222 * Win2k3 and previous mess this up by sending a name length
2223 * one byte short. I believe only older clients (OS/2 Win9x) use
2224 * this call so try fixing this by adding a terminating null to
2225 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2227 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2228 SCVAL(pdata,l2_vol_cch,len);
2229 data_len = l2_vol_szVolLabel + len;
2230 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2231 (unsigned)st.st_ctime, len, vname));
2232 break;
2234 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2235 case SMB_FS_ATTRIBUTE_INFORMATION:
2238 #if defined(HAVE_SYS_QUOTAS)
2239 quota_flag = FILE_VOLUME_QUOTAS;
2240 #endif
2242 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2243 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2244 quota_flag); /* FS ATTRIBUTES */
2246 SIVAL(pdata,4,255); /* Max filename component length */
2247 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2248 and will think we can't do long filenames */
2249 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2250 SIVAL(pdata,8,len);
2251 data_len = 12 + len;
2252 break;
2254 case SMB_QUERY_FS_LABEL_INFO:
2255 case SMB_FS_LABEL_INFORMATION:
2256 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2257 data_len = 4 + len;
2258 SIVAL(pdata,0,len);
2259 break;
2261 case SMB_QUERY_FS_VOLUME_INFO:
2262 case SMB_FS_VOLUME_INFORMATION:
2265 * Add volume serial number - hash of a combination of
2266 * the called hostname and the service name.
2268 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2269 (str_checksum(get_local_machine_name())<<16));
2271 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2272 SIVAL(pdata,12,len);
2273 data_len = 18+len;
2274 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2275 (int)strlen(vname),vname, lp_servicename(snum)));
2276 break;
2278 case SMB_QUERY_FS_SIZE_INFO:
2279 case SMB_FS_SIZE_INFORMATION:
2281 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2282 data_len = 24;
2283 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2284 return(UNIXERROR(ERRHRD,ERRgeneral));
2286 block_size = lp_block_size(snum);
2287 if (bsize < block_size) {
2288 SMB_BIG_UINT factor = block_size/bsize;
2289 bsize = block_size;
2290 dsize /= factor;
2291 dfree /= factor;
2293 if (bsize > block_size) {
2294 SMB_BIG_UINT factor = bsize/block_size;
2295 bsize = block_size;
2296 dsize *= factor;
2297 dfree *= factor;
2299 bytes_per_sector = 512;
2300 sectors_per_unit = bsize/bytes_per_sector;
2301 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2302 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2303 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2304 SBIG_UINT(pdata,0,dsize);
2305 SBIG_UINT(pdata,8,dfree);
2306 SIVAL(pdata,16,sectors_per_unit);
2307 SIVAL(pdata,20,bytes_per_sector);
2308 break;
2311 case SMB_FS_FULL_SIZE_INFORMATION:
2313 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2314 data_len = 32;
2315 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2316 return(UNIXERROR(ERRHRD,ERRgeneral));
2318 block_size = lp_block_size(snum);
2319 if (bsize < block_size) {
2320 SMB_BIG_UINT factor = block_size/bsize;
2321 bsize = block_size;
2322 dsize /= factor;
2323 dfree /= factor;
2325 if (bsize > block_size) {
2326 SMB_BIG_UINT factor = bsize/block_size;
2327 bsize = block_size;
2328 dsize *= factor;
2329 dfree *= factor;
2331 bytes_per_sector = 512;
2332 sectors_per_unit = bsize/bytes_per_sector;
2333 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2334 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2335 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2336 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2337 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2338 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2339 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2340 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2341 break;
2344 case SMB_QUERY_FS_DEVICE_INFO:
2345 case SMB_FS_DEVICE_INFORMATION:
2346 data_len = 8;
2347 SIVAL(pdata,0,0); /* dev type */
2348 SIVAL(pdata,4,0); /* characteristics */
2349 break;
2351 #ifdef HAVE_SYS_QUOTAS
2352 case SMB_FS_QUOTA_INFORMATION:
2354 * what we have to send --metze:
2356 * Unknown1: 24 NULL bytes
2357 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2358 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2359 * Quota Flags: 2 byte :
2360 * Unknown3: 6 NULL bytes
2362 * 48 bytes total
2364 * details for Quota Flags:
2366 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2367 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2368 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2369 * 0x0001 Enable Quotas: enable quota for this fs
2373 /* we need to fake up a fsp here,
2374 * because its not send in this call
2376 files_struct fsp;
2377 SMB_NTQUOTA_STRUCT quotas;
2379 ZERO_STRUCT(fsp);
2380 ZERO_STRUCT(quotas);
2382 fsp.conn = conn;
2383 fsp.fnum = -1;
2385 /* access check */
2386 if (current_user.ut.uid != 0) {
2387 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2388 lp_servicename(SNUM(conn)),conn->user));
2389 return ERROR_DOS(ERRDOS,ERRnoaccess);
2392 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2393 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2394 return ERROR_DOS(ERRSRV,ERRerror);
2397 data_len = 48;
2399 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2401 /* Unknown1 24 NULL bytes*/
2402 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2403 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2404 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2406 /* Default Soft Quota 8 bytes */
2407 SBIG_UINT(pdata,24,quotas.softlim);
2409 /* Default Hard Quota 8 bytes */
2410 SBIG_UINT(pdata,32,quotas.hardlim);
2412 /* Quota flag 2 bytes */
2413 SSVAL(pdata,40,quotas.qflags);
2415 /* Unknown3 6 NULL bytes */
2416 SSVAL(pdata,42,0);
2417 SIVAL(pdata,44,0);
2419 break;
2421 #endif /* HAVE_SYS_QUOTAS */
2422 case SMB_FS_OBJECTID_INFORMATION:
2423 data_len = 64;
2424 break;
2427 * Query the version and capabilities of the CIFS UNIX extensions
2428 * in use.
2431 case SMB_QUERY_CIFS_UNIX_INFO:
2432 if (!lp_unix_extensions()) {
2433 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2435 data_len = 12;
2436 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2437 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2438 /* We have POSIX ACLs, pathname and locking capability. */
2439 #if defined(DEVELOPER) /* Not quite finished yet... */
2440 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2441 CIFS_UNIX_POSIX_ACLS_CAP|
2442 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2443 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2444 #else
2445 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2446 CIFS_UNIX_POSIX_ACLS_CAP|
2447 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2448 0)));
2449 #endif
2450 break;
2452 case SMB_QUERY_POSIX_FS_INFO:
2454 int rc;
2455 vfs_statvfs_struct svfs;
2457 if (!lp_unix_extensions()) {
2458 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2461 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2463 if (!rc) {
2464 data_len = 56;
2465 SIVAL(pdata,0,svfs.OptimalTransferSize);
2466 SIVAL(pdata,4,svfs.BlockSize);
2467 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2468 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2469 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2470 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2471 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2472 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2473 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2474 #ifdef EOPNOTSUPP
2475 } else if (rc == EOPNOTSUPP) {
2476 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2477 #endif /* EOPNOTSUPP */
2478 } else {
2479 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2480 return ERROR_DOS(ERRSRV,ERRerror);
2482 break;
2485 case SMB_MAC_QUERY_FS_INFO:
2487 * Thursby MAC extension... ONLY on NTFS filesystems
2488 * once we do streams then we don't need this
2490 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2491 data_len = 88;
2492 SIVAL(pdata,84,0x100); /* Don't support mac... */
2493 break;
2495 /* drop through */
2496 default:
2497 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2501 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2503 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2505 return -1;
2508 /****************************************************************************
2509 Reply to a TRANS2_SETFSINFO (set filesystem info).
2510 ****************************************************************************/
2512 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2513 char **pparams, int total_params, char **ppdata, int total_data,
2514 unsigned int max_data_bytes)
2516 char *pdata = *ppdata;
2517 char *params = *pparams;
2518 uint16 info_level;
2519 int outsize;
2521 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2523 /* */
2524 if (total_params < 4) {
2525 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2526 total_params));
2527 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2530 info_level = SVAL(params,2);
2532 switch(info_level) {
2533 case SMB_SET_CIFS_UNIX_INFO:
2535 uint16 client_unix_major;
2536 uint16 client_unix_minor;
2537 uint32 client_unix_cap_low;
2538 uint32 client_unix_cap_high;
2540 if (!lp_unix_extensions()) {
2541 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2544 /* There should be 12 bytes of capabilities set. */
2545 if (total_data < 8) {
2546 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2548 client_unix_major = SVAL(pdata,0);
2549 client_unix_minor = SVAL(pdata,2);
2550 client_unix_cap_low = IVAL(pdata,4);
2551 client_unix_cap_high = IVAL(pdata,8);
2552 /* Just print these values for now. */
2553 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2554 cap_low = 0x%x, cap_high = 0x%x\n",
2555 (unsigned int)client_unix_major,
2556 (unsigned int)client_unix_minor,
2557 (unsigned int)client_unix_cap_low,
2558 (unsigned int)client_unix_cap_high ));
2560 /* Here is where we must switch to posix pathname processing... */
2561 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2562 lp_set_posix_pathnames();
2563 mangle_change_to_posix();
2565 #if defined(DEVELOPER)
2566 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2567 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2569 #endif
2570 break;
2572 case SMB_FS_QUOTA_INFORMATION:
2574 files_struct *fsp = NULL;
2575 SMB_NTQUOTA_STRUCT quotas;
2577 ZERO_STRUCT(quotas);
2579 /* access check */
2580 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2581 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2582 lp_servicename(SNUM(conn)),conn->user));
2583 return ERROR_DOS(ERRSRV,ERRaccess);
2586 /* note: normaly there're 48 bytes,
2587 * but we didn't use the last 6 bytes for now
2588 * --metze
2590 fsp = file_fsp(params,0);
2591 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2592 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2593 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2596 if (total_data < 42) {
2597 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2598 total_data));
2599 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2602 /* unknown_1 24 NULL bytes in pdata*/
2604 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2605 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2606 #ifdef LARGE_SMB_OFF_T
2607 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2608 #else /* LARGE_SMB_OFF_T */
2609 if ((IVAL(pdata,28) != 0)&&
2610 ((quotas.softlim != 0xFFFFFFFF)||
2611 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2612 /* more than 32 bits? */
2613 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2615 #endif /* LARGE_SMB_OFF_T */
2617 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2618 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2619 #ifdef LARGE_SMB_OFF_T
2620 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2621 #else /* LARGE_SMB_OFF_T */
2622 if ((IVAL(pdata,36) != 0)&&
2623 ((quotas.hardlim != 0xFFFFFFFF)||
2624 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2625 /* more than 32 bits? */
2626 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2628 #endif /* LARGE_SMB_OFF_T */
2630 /* quota_flags 2 bytes **/
2631 quotas.qflags = SVAL(pdata,40);
2633 /* unknown_2 6 NULL bytes follow*/
2635 /* now set the quotas */
2636 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2637 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2638 return ERROR_DOS(ERRSRV,ERRerror);
2641 break;
2643 default:
2644 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2645 info_level));
2646 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2647 break;
2651 * sending this reply works fine,
2652 * but I'm not sure it's the same
2653 * like windows do...
2654 * --metze
2656 outsize = set_message(outbuf,10,0,True);
2658 return outsize;
2661 /****************************************************************************
2662 Utility function to set bad path error.
2663 ****************************************************************************/
2665 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2667 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2668 err, (int)bad_path ));
2670 if(err == ENOENT) {
2671 if (bad_path) {
2672 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2673 } else {
2674 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2677 return UNIXERROR(def_class,def_code);
2680 #if defined(HAVE_POSIX_ACLS)
2681 /****************************************************************************
2682 Utility function to count the number of entries in a POSIX acl.
2683 ****************************************************************************/
2685 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2687 unsigned int ace_count = 0;
2688 int entry_id = SMB_ACL_FIRST_ENTRY;
2689 SMB_ACL_ENTRY_T entry;
2691 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2692 /* get_next... */
2693 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2694 entry_id = SMB_ACL_NEXT_ENTRY;
2696 ace_count++;
2698 return ace_count;
2701 /****************************************************************************
2702 Utility function to marshall a POSIX acl into wire format.
2703 ****************************************************************************/
2705 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2707 int entry_id = SMB_ACL_FIRST_ENTRY;
2708 SMB_ACL_ENTRY_T entry;
2710 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2711 SMB_ACL_TAG_T tagtype;
2712 SMB_ACL_PERMSET_T permset;
2713 unsigned char perms = 0;
2714 unsigned int own_grp;
2716 /* get_next... */
2717 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2718 entry_id = SMB_ACL_NEXT_ENTRY;
2721 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2722 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2723 return False;
2726 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2727 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2728 return False;
2731 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2732 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2733 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2735 SCVAL(pdata,1,perms);
2737 switch (tagtype) {
2738 case SMB_ACL_USER_OBJ:
2739 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2740 own_grp = (unsigned int)pst->st_uid;
2741 SIVAL(pdata,2,own_grp);
2742 SIVAL(pdata,6,0);
2743 break;
2744 case SMB_ACL_USER:
2746 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2747 if (!puid) {
2748 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2750 own_grp = (unsigned int)*puid;
2751 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2752 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2753 SIVAL(pdata,2,own_grp);
2754 SIVAL(pdata,6,0);
2755 break;
2757 case SMB_ACL_GROUP_OBJ:
2758 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2759 own_grp = (unsigned int)pst->st_gid;
2760 SIVAL(pdata,2,own_grp);
2761 SIVAL(pdata,6,0);
2762 break;
2763 case SMB_ACL_GROUP:
2765 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2766 if (!pgid) {
2767 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2769 own_grp = (unsigned int)*pgid;
2770 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2771 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2772 SIVAL(pdata,2,own_grp);
2773 SIVAL(pdata,6,0);
2774 break;
2776 case SMB_ACL_MASK:
2777 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2778 SIVAL(pdata,2,0xFFFFFFFF);
2779 SIVAL(pdata,6,0xFFFFFFFF);
2780 break;
2781 case SMB_ACL_OTHER:
2782 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2783 SIVAL(pdata,2,0xFFFFFFFF);
2784 SIVAL(pdata,6,0xFFFFFFFF);
2785 break;
2786 default:
2787 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2788 return False;
2790 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2793 return True;
2795 #endif
2797 /****************************************************************************
2798 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2799 file name or file id).
2800 ****************************************************************************/
2802 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2803 unsigned int tran_call,
2804 char **pparams, int total_params, char **ppdata, int total_data,
2805 unsigned int max_data_bytes)
2807 char *params = *pparams;
2808 char *pdata = *ppdata;
2809 uint16 info_level;
2810 int mode=0;
2811 int nlink;
2812 SMB_OFF_T file_size=0;
2813 SMB_BIG_UINT allocation_size=0;
2814 unsigned int data_size = 0;
2815 unsigned int param_size = 2;
2816 SMB_STRUCT_STAT sbuf;
2817 pstring fname, dos_fname;
2818 char *fullpathname;
2819 char *base_name;
2820 char *p;
2821 SMB_OFF_T pos = 0;
2822 BOOL bad_path = False;
2823 BOOL delete_pending = False;
2824 int len;
2825 time_t c_time;
2826 files_struct *fsp = NULL;
2827 TALLOC_CTX *data_ctx = NULL;
2828 struct ea_list *ea_list = NULL;
2829 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2830 #if defined(DEVELOPER)
2831 char *lock_data = NULL;
2832 #endif
2834 if (!params)
2835 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2837 ZERO_STRUCT(sbuf);
2839 if (tran_call == TRANSACT2_QFILEINFO) {
2840 if (total_params < 4) {
2841 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2844 fsp = file_fsp(params,0);
2845 info_level = SVAL(params,2);
2847 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2849 if(fsp && (fsp->fake_file_handle)) {
2851 * This is actually for the QUOTA_FAKE_FILE --metze
2854 pstrcpy(fname, fsp->fsp_name);
2855 /* We know this name is ok, it's already passed the checks. */
2857 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2859 * This is actually a QFILEINFO on a directory
2860 * handle (returned from an NT SMB). NT5.0 seems
2861 * to do this call. JRA.
2863 /* We know this name is ok, it's already passed the checks. */
2864 pstrcpy(fname, fsp->fsp_name);
2866 if (INFO_LEVEL_IS_UNIX(info_level)) {
2867 /* Always do lstat for UNIX calls. */
2868 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2869 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2870 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2872 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2873 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2874 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2878 } else {
2880 * Original code - this is an open file.
2882 CHECK_FSP(fsp,conn);
2884 pstrcpy(fname, fsp->fsp_name);
2885 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2886 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2887 return(UNIXERROR(ERRDOS,ERRbadfid));
2889 pos = fsp->fh->position_information;
2890 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2891 access_mask = fsp->access_mask;
2893 } else {
2894 NTSTATUS status = NT_STATUS_OK;
2896 /* qpathinfo */
2897 if (total_params < 6) {
2898 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2901 info_level = SVAL(params,0);
2903 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2905 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 return ERROR_NT(status);
2910 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2912 unix_convert(fname,conn,0,&bad_path,&sbuf);
2913 if (bad_path) {
2914 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2916 if (!check_name(fname,conn)) {
2917 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2918 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2921 if (INFO_LEVEL_IS_UNIX(info_level)) {
2922 /* Always do lstat for UNIX calls. */
2923 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2924 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2925 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2927 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2928 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2929 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2932 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2933 if (delete_pending) {
2934 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2938 nlink = sbuf.st_nlink;
2940 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2941 /* NTFS does not seem to count ".." */
2942 nlink -= 1;
2945 if ((nlink > 0) && delete_pending) {
2946 nlink -= 1;
2949 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2950 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2953 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2954 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2956 p = strrchr_m(fname,'/');
2957 if (!p)
2958 base_name = fname;
2959 else
2960 base_name = p+1;
2962 mode = dos_mode(conn,fname,&sbuf);
2963 if (!mode)
2964 mode = FILE_ATTRIBUTE_NORMAL;
2966 fullpathname = fname;
2967 if (!(mode & aDIR))
2968 file_size = get_file_size(sbuf);
2970 /* Pull out any data sent here before we realloc. */
2971 switch (info_level) {
2972 case SMB_INFO_QUERY_EAS_FROM_LIST:
2974 /* Pull any EA list from the data portion. */
2975 uint32 ea_size;
2977 if (total_data < 4) {
2978 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2980 ea_size = IVAL(pdata,0);
2982 if (total_data > 0 && ea_size != total_data) {
2983 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2984 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2985 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2988 if (!lp_ea_support(SNUM(conn))) {
2989 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2992 if ((data_ctx = talloc_init("ea_list")) == NULL) {
2993 return ERROR_NT(NT_STATUS_NO_MEMORY);
2996 /* Pull out the list of names. */
2997 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
2998 if (!ea_list) {
2999 talloc_destroy(data_ctx);
3000 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3002 break;
3004 #if defined(DEVELOPER)
3005 case SMB_QUERY_POSIX_LOCK:
3007 if (fsp == NULL || fsp->fh->fd == -1) {
3008 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3011 if (total_data != POSIX_LOCK_DATA_SIZE) {
3012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3015 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3016 return ERROR_NT(NT_STATUS_NO_MEMORY);
3019 /* Copy the lock range data. */
3020 lock_data = talloc_memdup(data_ctx, pdata, total_data);
3021 if (!lock_data) {
3022 talloc_destroy(data_ctx);
3023 return ERROR_NT(NT_STATUS_NO_MEMORY);
3026 #endif
3027 default:
3028 break;
3031 *pparams = SMB_REALLOC(*pparams,2);
3032 if (*pparams == NULL) {
3033 talloc_destroy(data_ctx);
3034 return ERROR_NT(NT_STATUS_NO_MEMORY);
3036 params = *pparams;
3037 SSVAL(params,0,0);
3038 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3039 *ppdata = SMB_REALLOC(*ppdata, data_size);
3040 if (*ppdata == NULL ) {
3041 talloc_destroy(data_ctx);
3042 return ERROR_NT(NT_STATUS_NO_MEMORY);
3044 pdata = *ppdata;
3046 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3048 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3050 if (fsp) {
3051 if (fsp->pending_modtime) {
3052 /* the pending modtime overrides the current modtime */
3053 sbuf.st_mtime = fsp->pending_modtime;
3055 } else {
3056 /* Do we have this path open ? */
3057 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3058 if (fsp1 && fsp1->pending_modtime) {
3059 /* the pending modtime overrides the current modtime */
3060 sbuf.st_mtime = fsp1->pending_modtime;
3062 if (fsp1 && fsp1->initial_allocation_size) {
3063 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3067 if (lp_dos_filetime_resolution(SNUM(conn))) {
3068 c_time &= ~1;
3069 sbuf.st_atime &= ~1;
3070 sbuf.st_ctime &= ~1;
3071 sbuf.st_mtime &= ~1;
3074 /* NT expects the name to be in an exact form of the *full*
3075 filename. See the trans2 torture test */
3076 if (strequal(base_name,".")) {
3077 pstrcpy(dos_fname, "\\");
3078 } else {
3079 pstr_sprintf(dos_fname, "\\%s", fname);
3080 string_replace(dos_fname, '/', '\\');
3083 switch (info_level) {
3084 case SMB_INFO_STANDARD:
3085 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3086 data_size = 22;
3087 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3088 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3089 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3090 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3091 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3092 SSVAL(pdata,l1_attrFile,mode);
3093 break;
3095 case SMB_INFO_QUERY_EA_SIZE:
3097 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3098 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3099 data_size = 26;
3100 srv_put_dos_date2(pdata,0,c_time);
3101 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3102 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3103 SIVAL(pdata,12,(uint32)file_size);
3104 SIVAL(pdata,16,(uint32)allocation_size);
3105 SSVAL(pdata,20,mode);
3106 SIVAL(pdata,22,ea_size);
3107 break;
3110 case SMB_INFO_IS_NAME_VALID:
3111 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3112 if (tran_call == TRANSACT2_QFILEINFO) {
3113 /* os/2 needs this ? really ?*/
3114 return ERROR_DOS(ERRDOS,ERRbadfunc);
3116 data_size = 0;
3117 param_size = 0;
3118 break;
3120 case SMB_INFO_QUERY_EAS_FROM_LIST:
3122 size_t total_ea_len = 0;
3123 struct ea_list *ea_file_list = NULL;
3125 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3127 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3128 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3130 if (!ea_list || (total_ea_len > data_size)) {
3131 talloc_destroy(data_ctx);
3132 data_size = 4;
3133 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3134 break;
3137 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3138 talloc_destroy(data_ctx);
3139 break;
3142 case SMB_INFO_QUERY_ALL_EAS:
3144 /* We have data_size bytes to put EA's into. */
3145 size_t total_ea_len = 0;
3147 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3149 data_ctx = talloc_init("ea_ctx");
3150 if (!data_ctx) {
3151 return ERROR_NT(NT_STATUS_NO_MEMORY);
3154 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3155 if (!ea_list || (total_ea_len > data_size)) {
3156 talloc_destroy(data_ctx);
3157 data_size = 4;
3158 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3159 break;
3162 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3163 talloc_destroy(data_ctx);
3164 break;
3167 case SMB_FILE_BASIC_INFORMATION:
3168 case SMB_QUERY_FILE_BASIC_INFO:
3170 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3171 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3172 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3173 } else {
3174 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3175 data_size = 40;
3176 SIVAL(pdata,36,0);
3178 put_long_date(pdata,c_time);
3179 put_long_date(pdata+8,sbuf.st_atime);
3180 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3181 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3182 SIVAL(pdata,32,mode);
3184 DEBUG(5,("SMB_QFBI - "));
3186 time_t create_time = c_time;
3187 DEBUG(5,("create: %s ", ctime(&create_time)));
3189 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3190 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3191 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3192 DEBUG(5,("mode: %x\n", mode));
3193 break;
3195 case SMB_FILE_STANDARD_INFORMATION:
3196 case SMB_QUERY_FILE_STANDARD_INFO:
3198 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3199 data_size = 24;
3200 SOFF_T(pdata,0,allocation_size);
3201 SOFF_T(pdata,8,file_size);
3202 SIVAL(pdata,16,nlink);
3203 SCVAL(pdata,20,delete_pending?1:0);
3204 SCVAL(pdata,21,(mode&aDIR)?1:0);
3205 SSVAL(pdata,22,0); /* Padding. */
3206 break;
3208 case SMB_FILE_EA_INFORMATION:
3209 case SMB_QUERY_FILE_EA_INFO:
3211 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3212 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3213 data_size = 4;
3214 SIVAL(pdata,0,ea_size);
3215 break;
3218 /* Get the 8.3 name - used if NT SMB was negotiated. */
3219 case SMB_QUERY_FILE_ALT_NAME_INFO:
3220 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3222 pstring short_name;
3224 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3225 pstrcpy(short_name,base_name);
3226 /* Mangle if not already 8.3 */
3227 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3228 mangle_map(short_name,True,True,SNUM(conn));
3230 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3231 data_size = 4 + len;
3232 SIVAL(pdata,0,len);
3233 break;
3236 case SMB_QUERY_FILE_NAME_INFO:
3238 this must be *exactly* right for ACLs on mapped drives to work
3240 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3241 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3242 data_size = 4 + len;
3243 SIVAL(pdata,0,len);
3244 break;
3246 case SMB_FILE_ALLOCATION_INFORMATION:
3247 case SMB_QUERY_FILE_ALLOCATION_INFO:
3248 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3249 data_size = 8;
3250 SOFF_T(pdata,0,allocation_size);
3251 break;
3253 case SMB_FILE_END_OF_FILE_INFORMATION:
3254 case SMB_QUERY_FILE_END_OF_FILEINFO:
3255 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3256 data_size = 8;
3257 SOFF_T(pdata,0,file_size);
3258 break;
3260 case SMB_QUERY_FILE_ALL_INFO:
3261 case SMB_FILE_ALL_INFORMATION:
3263 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3264 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3265 put_long_date(pdata,c_time);
3266 put_long_date(pdata+8,sbuf.st_atime);
3267 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3268 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3269 SIVAL(pdata,32,mode);
3270 SIVAL(pdata,36,0); /* padding. */
3271 pdata += 40;
3272 SOFF_T(pdata,0,allocation_size);
3273 SOFF_T(pdata,8,file_size);
3274 SIVAL(pdata,16,nlink);
3275 SCVAL(pdata,20,delete_pending);
3276 SCVAL(pdata,21,(mode&aDIR)?1:0);
3277 SSVAL(pdata,22,0);
3278 pdata += 24;
3279 SIVAL(pdata,0,ea_size);
3280 pdata += 4; /* EA info */
3281 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3282 SIVAL(pdata,0,len);
3283 pdata += 4 + len;
3284 data_size = PTR_DIFF(pdata,(*ppdata));
3285 break;
3287 case SMB_FILE_INTERNAL_INFORMATION:
3288 /* This should be an index number - looks like
3289 dev/ino to me :-)
3291 I think this causes us to fail the IFSKIT
3292 BasicFileInformationTest. -tpot */
3294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3295 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3296 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3297 data_size = 8;
3298 break;
3300 case SMB_FILE_ACCESS_INFORMATION:
3301 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3302 SIVAL(pdata,0,access_mask);
3303 data_size = 4;
3304 break;
3306 case SMB_FILE_NAME_INFORMATION:
3307 /* Pathname with leading '\'. */
3309 size_t byte_len;
3310 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3311 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3312 SIVAL(pdata,0,byte_len);
3313 data_size = 4 + byte_len;
3314 break;
3317 case SMB_FILE_DISPOSITION_INFORMATION:
3318 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3319 data_size = 1;
3320 SCVAL(pdata,0,delete_pending);
3321 break;
3323 case SMB_FILE_POSITION_INFORMATION:
3324 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3325 data_size = 8;
3326 SOFF_T(pdata,0,pos);
3327 break;
3329 case SMB_FILE_MODE_INFORMATION:
3330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3331 SIVAL(pdata,0,mode);
3332 data_size = 4;
3333 break;
3335 case SMB_FILE_ALIGNMENT_INFORMATION:
3336 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3337 SIVAL(pdata,0,0); /* No alignment needed. */
3338 data_size = 4;
3339 break;
3341 #if 0
3343 * NT4 server just returns "invalid query" to this - if we try to answer
3344 * it then NTws gets a BSOD! (tridge).
3345 * W2K seems to want this. JRA.
3347 case SMB_QUERY_FILE_STREAM_INFO:
3348 #endif
3349 case SMB_FILE_STREAM_INFORMATION:
3350 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3351 if (mode & aDIR) {
3352 data_size = 0;
3353 } else {
3354 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3355 SIVAL(pdata,0,0); /* ??? */
3356 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3357 SOFF_T(pdata,8,file_size);
3358 SIVAL(pdata,16,allocation_size);
3359 SIVAL(pdata,20,0); /* ??? */
3360 data_size = 24 + byte_len;
3362 break;
3364 case SMB_QUERY_COMPRESSION_INFO:
3365 case SMB_FILE_COMPRESSION_INFORMATION:
3366 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3367 SOFF_T(pdata,0,file_size);
3368 SIVAL(pdata,8,0); /* ??? */
3369 SIVAL(pdata,12,0); /* ??? */
3370 data_size = 16;
3371 break;
3373 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3374 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3375 put_long_date(pdata,c_time);
3376 put_long_date(pdata+8,sbuf.st_atime);
3377 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3378 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3379 SIVAL(pdata,32,allocation_size);
3380 SOFF_T(pdata,40,file_size);
3381 SIVAL(pdata,48,mode);
3382 SIVAL(pdata,52,0); /* ??? */
3383 data_size = 56;
3384 break;
3386 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3388 SIVAL(pdata,0,mode);
3389 SIVAL(pdata,4,0);
3390 data_size = 8;
3391 break;
3394 * CIFS UNIX Extensions.
3397 case SMB_QUERY_FILE_UNIX_BASIC:
3399 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3400 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3402 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3403 pdata += 8;
3405 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3406 pdata += 8;
3408 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3409 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3410 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3411 pdata += 24;
3413 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3414 SIVAL(pdata,4,0);
3415 pdata += 8;
3417 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3418 SIVAL(pdata,4,0);
3419 pdata += 8;
3421 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3422 pdata += 4;
3424 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3425 SIVAL(pdata,4,0);
3426 pdata += 8;
3428 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3429 SIVAL(pdata,4,0);
3430 pdata += 8;
3432 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3433 pdata += 8;
3435 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3436 SIVAL(pdata,4,0);
3437 pdata += 8;
3439 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3440 SIVAL(pdata,4,0);
3441 pdata += 8;
3442 data_size = PTR_DIFF(pdata,(*ppdata));
3445 int i;
3446 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3448 for (i=0; i<100; i++)
3449 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3450 DEBUG(4,("\n"));
3453 break;
3455 case SMB_QUERY_FILE_UNIX_LINK:
3457 pstring buffer;
3459 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3460 #ifdef S_ISLNK
3461 if(!S_ISLNK(sbuf.st_mode))
3462 return(UNIXERROR(ERRSRV,ERRbadlink));
3463 #else
3464 return(UNIXERROR(ERRDOS,ERRbadlink));
3465 #endif
3466 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3467 if (len == -1)
3468 return(UNIXERROR(ERRDOS,ERRnoaccess));
3469 buffer[len] = 0;
3470 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3471 pdata += len;
3472 data_size = PTR_DIFF(pdata,(*ppdata));
3474 break;
3477 #if defined(HAVE_POSIX_ACLS)
3478 case SMB_QUERY_POSIX_ACL:
3480 SMB_ACL_T file_acl = NULL;
3481 SMB_ACL_T def_acl = NULL;
3482 uint16 num_file_acls = 0;
3483 uint16 num_def_acls = 0;
3485 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3486 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3487 } else {
3488 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3491 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3492 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3493 fname ));
3494 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3497 if (S_ISDIR(sbuf.st_mode)) {
3498 if (fsp && fsp->is_directory) {
3499 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3500 } else {
3501 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3503 def_acl = free_empty_sys_acl(conn, def_acl);
3506 num_file_acls = count_acl_entries(conn, file_acl);
3507 num_def_acls = count_acl_entries(conn, def_acl);
3509 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3510 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3511 data_size,
3512 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3513 SMB_POSIX_ACL_HEADER_SIZE) ));
3514 if (file_acl) {
3515 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3517 if (def_acl) {
3518 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3520 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3523 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3524 SSVAL(pdata,2,num_file_acls);
3525 SSVAL(pdata,4,num_def_acls);
3526 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3527 if (file_acl) {
3528 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3530 if (def_acl) {
3531 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3533 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3535 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3536 if (file_acl) {
3537 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3539 if (def_acl) {
3540 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3542 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3545 if (file_acl) {
3546 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3548 if (def_acl) {
3549 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3551 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3552 break;
3554 #endif
3557 #if defined(DEVELOPER)
3558 case SMB_QUERY_POSIX_LOCK:
3560 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3561 SMB_BIG_UINT count;
3562 SMB_BIG_UINT offset;
3563 uint16 lock_pid;
3564 enum brl_type lock_type;
3566 if (total_data != POSIX_LOCK_DATA_SIZE) {
3567 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3570 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3571 case POSIX_LOCK_TYPE_READ:
3572 lock_type = READ_LOCK;
3573 break;
3574 case POSIX_LOCK_TYPE_WRITE:
3575 lock_type = WRITE_LOCK;
3576 break;
3577 case POSIX_LOCK_TYPE_UNLOCK:
3578 default:
3579 /* There's no point in asking for an unlock... */
3580 talloc_destroy(data_ctx);
3581 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3584 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3585 #if defined(HAVE_LONGLONG)
3586 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3587 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3588 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3589 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3590 #else /* HAVE_LONGLONG */
3591 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3592 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3593 #endif /* HAVE_LONGLONG */
3595 status = query_lock(fsp,
3596 &lock_pid,
3597 &count,
3598 &offset,
3599 &lock_type,
3600 POSIX_LOCK);
3602 if (ERROR_WAS_LOCK_DENIED(status)) {
3603 /* Here we need to report who has it locked... */
3604 data_size = POSIX_LOCK_DATA_SIZE;
3606 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3607 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3608 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3609 #if defined(HAVE_LONGLONG)
3610 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3611 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3612 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3613 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3614 #else /* HAVE_LONGLONG */
3615 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3616 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3617 #endif /* HAVE_LONGLONG */
3619 } else if (NT_STATUS_IS_OK(status)) {
3620 /* For success we just return a copy of what we sent
3621 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3622 data_size = POSIX_LOCK_DATA_SIZE;
3623 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3624 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3625 } else {
3626 return ERROR_NT(status);
3628 break;
3630 #endif
3632 default:
3633 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3636 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3638 return(-1);
3641 /****************************************************************************
3642 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3643 code.
3644 ****************************************************************************/
3646 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3648 BOOL bad_path_oldname = False;
3649 BOOL bad_path_newname = False;
3650 SMB_STRUCT_STAT sbuf1, sbuf2;
3651 pstring last_component_oldname;
3652 pstring last_component_newname;
3653 NTSTATUS status = NT_STATUS_OK;
3655 ZERO_STRUCT(sbuf1);
3656 ZERO_STRUCT(sbuf2);
3658 /* No wildcards. */
3659 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3660 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3663 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3664 if (bad_path_oldname) {
3665 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3668 /* Quick check for "." and ".." */
3669 if (last_component_oldname[0] == '.') {
3670 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3671 return NT_STATUS_OBJECT_NAME_INVALID;
3675 /* source must already exist. */
3676 if (!VALID_STAT(sbuf1)) {
3677 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3680 if (!check_name(oldname,conn)) {
3681 return NT_STATUS_ACCESS_DENIED;
3684 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3685 if (bad_path_newname) {
3686 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3689 /* Quick check for "." and ".." */
3690 if (last_component_newname[0] == '.') {
3691 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3692 return NT_STATUS_OBJECT_NAME_INVALID;
3696 /* Disallow if newname already exists. */
3697 if (VALID_STAT(sbuf2)) {
3698 return NT_STATUS_OBJECT_NAME_COLLISION;
3701 if (!check_name(newname,conn)) {
3702 return NT_STATUS_ACCESS_DENIED;
3705 /* No links from a directory. */
3706 if (S_ISDIR(sbuf1.st_mode)) {
3707 return NT_STATUS_FILE_IS_A_DIRECTORY;
3710 /* Ensure this is within the share. */
3711 if (!reduce_name(conn, oldname) != 0)
3712 return NT_STATUS_ACCESS_DENIED;
3714 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3716 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3717 status = map_nt_error_from_unix(errno);
3718 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3719 nt_errstr(status), newname, oldname));
3722 return status;
3725 /****************************************************************************
3726 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3727 ****************************************************************************/
3729 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3730 unsigned int tran_call,
3731 char **pparams, int total_params, char **ppdata, int total_data,
3732 unsigned int max_data_bytes)
3734 char *params = *pparams;
3735 char *pdata = *ppdata;
3736 uint16 info_level;
3737 int dosmode=0;
3738 SMB_OFF_T size=0;
3739 struct utimbuf tvs;
3740 SMB_STRUCT_STAT sbuf;
3741 pstring fname;
3742 int fd = -1;
3743 BOOL bad_path = False;
3744 files_struct *fsp = NULL;
3745 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3746 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3747 mode_t unixmode = 0;
3748 NTSTATUS status = NT_STATUS_OK;
3750 if (!params)
3751 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3753 ZERO_STRUCT(sbuf);
3754 ZERO_STRUCT(tvs);
3756 if (tran_call == TRANSACT2_SETFILEINFO) {
3757 if (total_params < 4) {
3758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3761 fsp = file_fsp(params,0);
3762 info_level = SVAL(params,2);
3764 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3766 * This is actually a SETFILEINFO on a directory
3767 * handle (returned from an NT SMB). NT5.0 seems
3768 * to do this call. JRA.
3770 pstrcpy(fname, fsp->fsp_name);
3771 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3772 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3773 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3775 } else if (fsp && fsp->print_file) {
3777 * Doing a DELETE_ON_CLOSE should cancel a print job.
3779 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3780 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3782 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3784 SSVAL(params,0,0);
3785 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3786 return(-1);
3787 } else
3788 return (UNIXERROR(ERRDOS,ERRbadpath));
3789 } else {
3791 * Original code - this is an open file.
3793 CHECK_FSP(fsp,conn);
3795 pstrcpy(fname, fsp->fsp_name);
3796 fd = fsp->fh->fd;
3798 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3799 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3800 return(UNIXERROR(ERRDOS,ERRbadfid));
3803 } else {
3804 /* set path info */
3805 if (total_params < 6) {
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3809 info_level = SVAL(params,0);
3810 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 return ERROR_NT(status);
3814 unix_convert(fname,conn,0,&bad_path,&sbuf);
3815 if (bad_path) {
3816 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3820 * For CIFS UNIX extensions the target name may not exist.
3823 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3824 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3825 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3828 if(!check_name(fname, conn)) {
3829 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3834 if (!CAN_WRITE(conn))
3835 return ERROR_DOS(ERRSRV,ERRaccess);
3837 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3838 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3841 if (VALID_STAT(sbuf))
3842 unixmode = sbuf.st_mode;
3844 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3845 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3847 /* Realloc the parameter size */
3848 *pparams = SMB_REALLOC(*pparams,2);
3849 if (*pparams == NULL) {
3850 return ERROR_NT(NT_STATUS_NO_MEMORY);
3852 params = *pparams;
3854 SSVAL(params,0,0);
3856 if (fsp && fsp->pending_modtime) {
3857 /* the pending modtime overrides the current modtime */
3858 sbuf.st_mtime = fsp->pending_modtime;
3861 size = get_file_size(sbuf);
3862 tvs.modtime = sbuf.st_mtime;
3863 tvs.actime = sbuf.st_atime;
3864 dosmode = dos_mode(conn,fname,&sbuf);
3865 unixmode = sbuf.st_mode;
3867 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3868 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3870 switch (info_level) {
3871 case SMB_INFO_STANDARD:
3873 if (total_data < 12) {
3874 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3877 /* access time */
3878 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3879 /* write time */
3880 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3881 break;
3884 case SMB_INFO_SET_EA:
3886 struct ea_list *ea_list = NULL;
3887 TALLOC_CTX *ctx = NULL;
3889 if (total_data < 10) {
3891 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3892 length. They seem to have no effect. Bug #3212. JRA */
3894 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3895 /* We're done. We only get EA info in this call. */
3896 SSVAL(params,0,0);
3897 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3898 return(-1);
3901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3904 if (IVAL(pdata,0) > total_data) {
3905 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3906 IVAL(pdata,0), (unsigned int)total_data));
3907 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3910 ctx = talloc_init("SMB_INFO_SET_EA");
3911 if (!ctx) {
3912 return ERROR_NT(NT_STATUS_NO_MEMORY);
3914 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3915 if (!ea_list) {
3916 talloc_destroy(ctx);
3917 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3919 status = set_ea(conn, fsp, fname, ea_list);
3920 talloc_destroy(ctx);
3922 if (!NT_STATUS_IS_OK(status)) {
3923 return ERROR_NT(status);
3926 /* We're done. We only get EA info in this call. */
3927 SSVAL(params,0,0);
3928 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3929 return(-1);
3932 #if 0
3933 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3934 /* XXXX um, i don't think this is right.
3935 it's also not in the cifs6.txt spec.
3937 case SMB_INFO_QUERY_EAS_FROM_LIST:
3938 if (total_data < 28)
3939 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3941 tvs.actime = make_unix_date2(pdata+8);
3942 tvs.modtime = make_unix_date2(pdata+12);
3943 size = IVAL(pdata,16);
3944 dosmode = IVAL(pdata,24);
3945 break;
3947 /* XXXX nor this. not in cifs6.txt, either. */
3948 case SMB_INFO_QUERY_ALL_EAS:
3949 if (total_data < 28)
3950 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3952 tvs.actime = make_unix_date2(pdata+8);
3953 tvs.modtime = make_unix_date2(pdata+12);
3954 size = IVAL(pdata,16);
3955 dosmode = IVAL(pdata,24);
3956 break;
3957 #endif
3959 case SMB_SET_FILE_BASIC_INFO:
3960 case SMB_FILE_BASIC_INFORMATION:
3962 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3963 time_t write_time;
3964 time_t changed_time;
3966 if (total_data < 36) {
3967 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3970 /* Ignore create time at offset pdata. */
3972 /* access time */
3973 tvs.actime = interpret_long_date(pdata+8);
3975 write_time = interpret_long_date(pdata+16);
3976 changed_time = interpret_long_date(pdata+24);
3978 tvs.modtime = MIN(write_time, changed_time);
3980 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3981 tvs.modtime = write_time;
3983 /* Prefer a defined time to an undefined one. */
3984 if (null_mtime(tvs.modtime)) {
3985 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3988 /* attributes */
3989 dosmode = IVAL(pdata,32);
3990 break;
3993 case SMB_FILE_ALLOCATION_INFORMATION:
3994 case SMB_SET_FILE_ALLOCATION_INFO:
3996 int ret = -1;
3997 SMB_BIG_UINT allocation_size;
3999 if (total_data < 8) {
4000 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4003 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4004 #ifdef LARGE_SMB_OFF_T
4005 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4006 #else /* LARGE_SMB_OFF_T */
4007 if (IVAL(pdata,4) != 0) {
4008 /* more than 32 bits? */
4009 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4011 #endif /* LARGE_SMB_OFF_T */
4012 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4013 fname, (double)allocation_size ));
4015 if (allocation_size) {
4016 allocation_size = smb_roundup(conn, allocation_size);
4019 if(allocation_size != get_file_size(sbuf)) {
4020 SMB_STRUCT_STAT new_sbuf;
4022 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4023 fname, (double)allocation_size ));
4025 if (fd == -1) {
4026 files_struct *new_fsp = NULL;
4028 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4029 FILE_WRITE_DATA,
4030 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4031 FILE_OPEN,
4033 FILE_ATTRIBUTE_NORMAL,
4034 FORCE_OPLOCK_BREAK_TO_NONE,
4035 NULL);
4037 if (new_fsp == NULL) {
4038 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4039 /* We have re-scheduled this call. */
4040 return -1;
4042 return(UNIXERROR(ERRDOS,ERRnoaccess));
4044 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4045 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4046 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4047 new_fsp->fnum, strerror(errno)));
4048 ret = -1;
4050 close_file(new_fsp,NORMAL_CLOSE);
4051 } else {
4052 ret = vfs_allocate_file_space(fsp, allocation_size);
4053 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4054 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4055 fsp->fnum, strerror(errno)));
4056 ret = -1;
4059 if (ret == -1)
4060 return ERROR_NT(NT_STATUS_DISK_FULL);
4062 /* Allocate can truncate size... */
4063 size = get_file_size(new_sbuf);
4066 break;
4069 case SMB_FILE_END_OF_FILE_INFORMATION:
4070 case SMB_SET_FILE_END_OF_FILE_INFO:
4072 if (total_data < 8) {
4073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4076 size = IVAL(pdata,0);
4077 #ifdef LARGE_SMB_OFF_T
4078 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4079 #else /* LARGE_SMB_OFF_T */
4080 if (IVAL(pdata,4) != 0) {
4081 /* more than 32 bits? */
4082 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4084 #endif /* LARGE_SMB_OFF_T */
4085 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4086 break;
4089 case SMB_FILE_DISPOSITION_INFORMATION:
4090 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4092 BOOL delete_on_close;
4094 if (total_data < 1) {
4095 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4098 delete_on_close = (CVAL(pdata,0) ? True : False);
4100 /* Just ignore this set on a path. */
4101 if (tran_call != TRANSACT2_SETFILEINFO)
4102 break;
4104 if (fsp == NULL)
4105 return(UNIXERROR(ERRDOS,ERRbadfid));
4107 status = can_set_delete_on_close(fsp, delete_on_close,
4108 dosmode);
4110 if (!NT_STATUS_IS_OK(status)) {
4111 return ERROR_NT(status);
4114 /* The set is across all open files on this dev/inode pair. */
4115 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4116 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4119 SSVAL(params,0,0);
4120 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4121 return(-1);
4124 case SMB_FILE_POSITION_INFORMATION:
4126 SMB_BIG_UINT position_information;
4128 if (total_data < 8) {
4129 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4132 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4133 #ifdef LARGE_SMB_OFF_T
4134 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4135 #else /* LARGE_SMB_OFF_T */
4136 if (IVAL(pdata,4) != 0) {
4137 /* more than 32 bits? */
4138 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4140 #endif /* LARGE_SMB_OFF_T */
4141 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4142 fname, (double)position_information ));
4143 if (fsp) {
4144 fsp->fh->position_information = position_information;
4147 /* We're done. We only get position info in this call. */
4148 SSVAL(params,0,0);
4149 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4150 return(-1);
4153 /* From tridge Samba4 :
4154 * MODE_INFORMATION in setfileinfo (I have no
4155 * idea what "mode information" on a file is - it takes a value of 0,
4156 * 2, 4 or 6. What could it be?).
4159 case SMB_FILE_MODE_INFORMATION:
4161 uint32 mode;
4163 if (total_data < 4) {
4164 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4166 mode = IVAL(pdata,0);
4167 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4168 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4171 /* We're done. We only get mode info in this call. */
4172 SSVAL(params,0,0);
4173 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4174 return(-1);
4178 * CIFS UNIX extensions.
4181 case SMB_SET_FILE_UNIX_BASIC:
4183 uint32 raw_unixmode;
4185 if (total_data < 100) {
4186 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4189 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4190 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4191 size=IVAL(pdata,0); /* first 8 Bytes are size */
4192 #ifdef LARGE_SMB_OFF_T
4193 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4194 #else /* LARGE_SMB_OFF_T */
4195 if (IVAL(pdata,4) != 0) {
4196 /* more than 32 bits? */
4197 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4199 #endif /* LARGE_SMB_OFF_T */
4201 pdata+=24; /* ctime & st_blocks are not changed */
4202 tvs.actime = interpret_long_date(pdata); /* access_time */
4203 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4204 pdata+=16;
4205 set_owner = (uid_t)IVAL(pdata,0);
4206 pdata += 8;
4207 set_grp = (gid_t)IVAL(pdata,0);
4208 pdata += 8;
4209 raw_unixmode = IVAL(pdata,28);
4210 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4211 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4213 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4214 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4215 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4217 if (!VALID_STAT(sbuf)) {
4220 * The only valid use of this is to create character and block
4221 * devices, and named pipes. This is deprecated (IMHO) and
4222 * a new info level should be used for mknod. JRA.
4225 uint32 file_type = IVAL(pdata,0);
4226 #if defined(HAVE_MAKEDEV)
4227 uint32 dev_major = IVAL(pdata,4);
4228 uint32 dev_minor = IVAL(pdata,12);
4229 #endif
4231 uid_t myuid = geteuid();
4232 gid_t mygid = getegid();
4233 SMB_DEV_T dev = (SMB_DEV_T)0;
4235 if (tran_call == TRANSACT2_SETFILEINFO)
4236 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4238 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4239 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4242 #if defined(HAVE_MAKEDEV)
4243 dev = makedev(dev_major, dev_minor);
4244 #endif
4246 /* We can only create as the owner/group we are. */
4248 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4249 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4250 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4251 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4253 switch (file_type) {
4254 #if defined(S_IFIFO)
4255 case UNIX_TYPE_FIFO:
4256 unixmode |= S_IFIFO;
4257 break;
4258 #endif
4259 #if defined(S_IFSOCK)
4260 case UNIX_TYPE_SOCKET:
4261 unixmode |= S_IFSOCK;
4262 break;
4263 #endif
4264 #if defined(S_IFCHR)
4265 case UNIX_TYPE_CHARDEV:
4266 unixmode |= S_IFCHR;
4267 break;
4268 #endif
4269 #if defined(S_IFBLK)
4270 case UNIX_TYPE_BLKDEV:
4271 unixmode |= S_IFBLK;
4272 break;
4273 #endif
4274 default:
4275 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4278 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4279 0%o for file %s\n", (double)dev, unixmode, fname ));
4281 /* Ok - do the mknod. */
4282 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4283 return(UNIXERROR(ERRDOS,ERRnoaccess));
4285 inherit_access_acl(conn, fname, unixmode);
4287 SSVAL(params,0,0);
4288 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4289 return(-1);
4293 * Deal with the UNIX specific mode set.
4296 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4297 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4298 (unsigned int)unixmode, fname ));
4299 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4300 return(UNIXERROR(ERRDOS,ERRnoaccess));
4304 * Deal with the UNIX specific uid set.
4307 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4308 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4309 (unsigned int)set_owner, fname ));
4310 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4311 return(UNIXERROR(ERRDOS,ERRnoaccess));
4315 * Deal with the UNIX specific gid set.
4318 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4319 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4320 (unsigned int)set_owner, fname ));
4321 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4322 return(UNIXERROR(ERRDOS,ERRnoaccess));
4324 break;
4327 case SMB_SET_FILE_UNIX_LINK:
4329 pstring link_target;
4330 char *newname = fname;
4332 /* Set a symbolic link. */
4333 /* Don't allow this if follow links is false. */
4335 if (!lp_symlinks(SNUM(conn)))
4336 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4338 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4340 /* !widelinks forces the target path to be within the share. */
4341 /* This means we can interpret the target as a pathname. */
4342 if (!lp_widelinks(SNUM(conn))) {
4343 pstring rel_name;
4344 char *last_dirp = NULL;
4346 unix_format(link_target);
4347 if (*link_target == '/') {
4348 /* No absolute paths allowed. */
4349 return(UNIXERROR(ERRDOS,ERRnoaccess));
4351 pstrcpy(rel_name, newname);
4352 last_dirp = strrchr_m(rel_name, '/');
4353 if (last_dirp) {
4354 last_dirp[1] = '\0';
4355 } else {
4356 pstrcpy(rel_name, "./");
4358 pstrcat(rel_name, link_target);
4360 if (!check_name(rel_name, conn)) {
4361 return(UNIXERROR(ERRDOS,ERRnoaccess));
4365 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4366 fname, link_target ));
4368 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4369 return(UNIXERROR(ERRDOS,ERRnoaccess));
4370 SSVAL(params,0,0);
4371 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4372 return(-1);
4375 case SMB_SET_FILE_UNIX_HLINK:
4377 pstring oldname;
4378 char *newname = fname;
4380 /* Set a hard link. */
4381 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 return ERROR_NT(status);
4386 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4387 fname, oldname));
4389 status = hardlink_internals(conn, oldname, newname);
4390 if (!NT_STATUS_IS_OK(status)) {
4391 return ERROR_NT(status);
4394 SSVAL(params,0,0);
4395 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4396 return(-1);
4399 case SMB_FILE_RENAME_INFORMATION:
4401 BOOL overwrite;
4402 uint32 root_fid;
4403 uint32 len;
4404 pstring newname;
4405 pstring base_name;
4406 char *p;
4408 if (total_data < 12) {
4409 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4412 overwrite = (CVAL(pdata,0) ? True : False);
4413 root_fid = IVAL(pdata,4);
4414 len = IVAL(pdata,8);
4415 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4416 if (!NT_STATUS_IS_OK(status)) {
4417 return ERROR_NT(status);
4420 /* Check the new name has no '/' characters. */
4421 if (strchr_m(newname, '/'))
4422 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4424 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4426 /* Create the base directory. */
4427 pstrcpy(base_name, fname);
4428 p = strrchr_m(base_name, '/');
4429 if (p)
4430 *p = '\0';
4431 /* Append the new name. */
4432 pstrcat(base_name, "/");
4433 pstrcat(base_name, newname);
4435 if (fsp) {
4436 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4437 fsp->fnum, fsp->fsp_name, base_name ));
4438 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4439 } else {
4440 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4441 fname, newname ));
4442 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4444 if (!NT_STATUS_IS_OK(status)) {
4445 return ERROR_NT(status);
4447 process_pending_change_notify_queue((time_t)0);
4448 SSVAL(params,0,0);
4449 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4450 return(-1);
4453 #if defined(HAVE_POSIX_ACLS)
4454 case SMB_SET_POSIX_ACL:
4456 uint16 posix_acl_version;
4457 uint16 num_file_acls;
4458 uint16 num_def_acls;
4459 BOOL valid_file_acls = True;
4460 BOOL valid_def_acls = True;
4462 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4463 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4465 posix_acl_version = SVAL(pdata,0);
4466 num_file_acls = SVAL(pdata,2);
4467 num_def_acls = SVAL(pdata,4);
4469 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4470 valid_file_acls = False;
4471 num_file_acls = 0;
4474 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4475 valid_def_acls = False;
4476 num_def_acls = 0;
4479 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4480 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4483 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4484 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4485 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4488 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4489 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4490 return(UNIXERROR(ERRDOS,ERRnoaccess));
4493 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4494 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4495 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4496 return(UNIXERROR(ERRDOS,ERRnoaccess));
4499 SSVAL(params,0,0);
4500 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4501 return(-1);
4503 #endif
4505 #if defined(DEVELOPER)
4506 case SMB_SET_POSIX_LOCK:
4508 SMB_BIG_UINT count;
4509 SMB_BIG_UINT offset;
4510 uint16 lock_pid;
4511 BOOL lock_blocking;
4512 enum brl_type lock_type;
4513 BOOL my_lock_ctx;
4515 if (fsp == NULL || fsp->fh->fd == -1) {
4516 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4519 if (total_data != POSIX_LOCK_DATA_SIZE) {
4520 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4523 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4524 case POSIX_LOCK_TYPE_READ:
4525 lock_type = READ_LOCK;
4526 break;
4527 case POSIX_LOCK_TYPE_WRITE:
4528 /* Return the right POSIX-mappable error code for files opened read-only. */
4529 if (!fsp->can_write) {
4530 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4532 lock_type = WRITE_LOCK;
4533 break;
4534 case POSIX_LOCK_TYPE_UNLOCK:
4535 lock_type = UNLOCK_LOCK;
4536 break;
4537 default:
4538 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4541 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4542 lock_blocking = False;
4543 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4544 lock_blocking = True;
4545 } else {
4546 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4549 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4550 #if defined(HAVE_LONGLONG)
4551 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4552 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4553 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4554 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4555 #else /* HAVE_LONGLONG */
4556 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4557 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4558 #endif /* HAVE_LONGLONG */
4560 if (lock_type == UNLOCK_LOCK) {
4561 status = do_unlock(fsp,
4562 lock_pid,
4563 count,
4564 offset,
4565 POSIX_LOCK);
4566 } else {
4567 status = do_lock(fsp,
4568 lock_pid,
4569 count,
4570 offset,
4571 lock_type,
4572 POSIX_LOCK,
4573 &my_lock_ctx);
4575 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4577 * A blocking lock was requested. Package up
4578 * this smb into a queued request and push it
4579 * onto the blocking lock queue.
4581 if(push_blocking_lock_request(inbuf, length,
4582 fsp,
4583 -1, /* infinite timeout. */
4585 lock_pid,
4586 lock_type,
4587 POSIX_LOCK,
4588 offset,
4589 count)) {
4590 return -1;
4595 if (!NT_STATUS_IS_OK(status)) {
4596 return ERROR_NT(status);
4599 SSVAL(params,0,0);
4600 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4601 return(-1);
4603 #endif
4605 default:
4606 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4609 /* get some defaults (no modifications) if any info is zero or -1. */
4610 if (null_mtime(tvs.actime)) {
4611 tvs.actime = sbuf.st_atime;
4614 if (null_mtime(tvs.modtime)) {
4615 tvs.modtime = sbuf.st_mtime;
4618 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4619 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4620 DEBUG(6,("size: %.0f ", (double)size));
4622 if (dosmode) {
4623 if (S_ISDIR(sbuf.st_mode))
4624 dosmode |= aDIR;
4625 else
4626 dosmode &= ~aDIR;
4629 DEBUG(6,("dosmode: %x\n" , dosmode));
4631 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4632 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4633 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4634 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4637 * Only do this test if we are not explicitly
4638 * changing the size of a file.
4640 if (!size)
4641 size = get_file_size(sbuf);
4645 * Try and set the times, size and mode of this file -
4646 * if they are different from the current values
4649 /* check the mode isn't different, before changing it */
4650 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4652 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4654 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4655 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4656 return(UNIXERROR(ERRDOS,ERRnoaccess));
4660 /* Now the size. */
4661 if (size != get_file_size(sbuf)) {
4663 int ret;
4665 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4666 fname, (double)size ));
4668 if (fd == -1) {
4669 files_struct *new_fsp = NULL;
4671 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4672 FILE_WRITE_DATA,
4673 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4674 FILE_OPEN,
4676 FILE_ATTRIBUTE_NORMAL,
4677 FORCE_OPLOCK_BREAK_TO_NONE,
4678 NULL);
4680 if (new_fsp == NULL) {
4681 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4682 /* We have re-scheduled this call. */
4683 return -1;
4685 return(UNIXERROR(ERRDOS,ERRnoaccess));
4687 ret = vfs_set_filelen(new_fsp, size);
4688 close_file(new_fsp,NORMAL_CLOSE);
4689 } else {
4690 ret = vfs_set_filelen(fsp, size);
4693 if (ret == -1) {
4694 return (UNIXERROR(ERRHRD,ERRdiskfull));
4699 * Finally the times.
4701 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4702 if(fsp != NULL) {
4704 * This was a setfileinfo on an open file.
4705 * NT does this a lot. We also need to
4706 * set the time here, as it can be read by
4707 * FindFirst/FindNext and with the patch for bug #2045
4708 * in smbd/fileio.c it ensures that this timestamp is
4709 * kept sticky even after a write. We save the request
4710 * away and will set it on file close and after a write. JRA.
4713 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4714 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4715 fsp_set_pending_modtime(fsp, tvs.modtime);
4719 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4721 if(file_utime(conn, fname, &tvs)!=0) {
4722 return(UNIXERROR(ERRDOS,ERRnoaccess));
4726 SSVAL(params,0,0);
4727 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4729 return(-1);
4732 /****************************************************************************
4733 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4734 ****************************************************************************/
4736 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4737 char **pparams, int total_params, char **ppdata, int total_data,
4738 unsigned int max_data_bytes)
4740 char *params = *pparams;
4741 char *pdata = *ppdata;
4742 pstring directory;
4743 int ret = -1;
4744 SMB_STRUCT_STAT sbuf;
4745 BOOL bad_path = False;
4746 NTSTATUS status = NT_STATUS_OK;
4747 TALLOC_CTX *ctx = NULL;
4748 struct ea_list *ea_list = NULL;
4750 if (!CAN_WRITE(conn))
4751 return ERROR_DOS(ERRSRV,ERRaccess);
4753 if (total_params < 4) {
4754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4757 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
4758 if (!NT_STATUS_IS_OK(status)) {
4759 return ERROR_NT(status);
4762 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4764 unix_convert(directory,conn,0,&bad_path,&sbuf);
4765 if (bad_path) {
4766 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4769 /* Any data in this call is an EA list. */
4770 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4771 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4775 * OS/2 workplace shell seems to send SET_EA requests of "null"
4776 * length (4 bytes containing IVAL 4).
4777 * They seem to have no effect. Bug #3212. JRA.
4780 if (total_data != 4) {
4781 if (total_data < 10) {
4782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4785 if (IVAL(pdata,0) > total_data) {
4786 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4787 IVAL(pdata,0), (unsigned int)total_data));
4788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4791 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4792 if (!ctx) {
4793 return ERROR_NT(NT_STATUS_NO_MEMORY);
4795 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4796 if (!ea_list) {
4797 talloc_destroy(ctx);
4798 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4800 } else if (IVAL(pdata,0) != 4) {
4801 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4804 if (check_name(directory,conn)) {
4805 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4808 if(ret < 0) {
4809 talloc_destroy(ctx);
4810 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4811 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4814 /* Try and set any given EA. */
4815 if (total_data) {
4816 status = set_ea(conn, NULL, directory, ea_list);
4817 talloc_destroy(ctx);
4818 if (!NT_STATUS_IS_OK(status)) {
4819 return ERROR_NT(status);
4823 /* Realloc the parameter and data sizes */
4824 *pparams = SMB_REALLOC(*pparams,2);
4825 if(*pparams == NULL) {
4826 return ERROR_NT(NT_STATUS_NO_MEMORY);
4828 params = *pparams;
4830 SSVAL(params,0,0);
4832 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4834 return(-1);
4837 /****************************************************************************
4838 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4839 We don't actually do this - we just send a null response.
4840 ****************************************************************************/
4842 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4843 char **pparams, int total_params, char **ppdata, int total_data,
4844 unsigned int max_data_bytes)
4846 static uint16 fnf_handle = 257;
4847 char *params = *pparams;
4848 uint16 info_level;
4850 if (total_params < 6) {
4851 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4854 info_level = SVAL(params,4);
4855 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4857 switch (info_level) {
4858 case 1:
4859 case 2:
4860 break;
4861 default:
4862 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4865 /* Realloc the parameter and data sizes */
4866 *pparams = SMB_REALLOC(*pparams,6);
4867 if (*pparams == NULL) {
4868 return ERROR_NT(NT_STATUS_NO_MEMORY);
4870 params = *pparams;
4872 SSVAL(params,0,fnf_handle);
4873 SSVAL(params,2,0); /* No changes */
4874 SSVAL(params,4,0); /* No EA errors */
4876 fnf_handle++;
4878 if(fnf_handle == 0)
4879 fnf_handle = 257;
4881 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4883 return(-1);
4886 /****************************************************************************
4887 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4888 changes). Currently this does nothing.
4889 ****************************************************************************/
4891 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4892 char **pparams, int total_params, char **ppdata, int total_data,
4893 unsigned int max_data_bytes)
4895 char *params = *pparams;
4897 DEBUG(3,("call_trans2findnotifynext\n"));
4899 /* Realloc the parameter and data sizes */
4900 *pparams = SMB_REALLOC(*pparams,4);
4901 if (*pparams == NULL) {
4902 return ERROR_NT(NT_STATUS_NO_MEMORY);
4904 params = *pparams;
4906 SSVAL(params,0,0); /* No changes */
4907 SSVAL(params,2,0); /* No EA errors */
4909 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4911 return(-1);
4914 /****************************************************************************
4915 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4916 ****************************************************************************/
4918 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4919 char **pparams, int total_params, char **ppdata, int total_data,
4920 unsigned int max_data_bytes)
4922 char *params = *pparams;
4923 pstring pathname;
4924 int reply_size = 0;
4925 int max_referral_level;
4927 DEBUG(10,("call_trans2getdfsreferral\n"));
4929 if (total_params < 2) {
4930 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4933 max_referral_level = SVAL(params,0);
4935 if(!lp_host_msdfs())
4936 return ERROR_DOS(ERRDOS,ERRbadfunc);
4938 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4939 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4940 return UNIXERROR(ERRDOS,ERRbadfile);
4942 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4943 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4945 return(-1);
4948 #define LMCAT_SPL 0x53
4949 #define LMFUNC_GETJOBID 0x60
4951 /****************************************************************************
4952 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4953 ****************************************************************************/
4955 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4956 char **pparams, int total_params, char **ppdata, int total_data,
4957 unsigned int max_data_bytes)
4959 char *pdata = *ppdata;
4960 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4962 /* check for an invalid fid before proceeding */
4964 if (!fsp)
4965 return(ERROR_DOS(ERRDOS,ERRbadfid));
4967 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4968 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4969 *ppdata = SMB_REALLOC(*ppdata, 32);
4970 if (*ppdata == NULL) {
4971 return ERROR_NT(NT_STATUS_NO_MEMORY);
4973 pdata = *ppdata;
4975 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4976 CAN ACCEPT THIS IN UNICODE. JRA. */
4978 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4979 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4980 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4981 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4982 return(-1);
4983 } else {
4984 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4985 return ERROR_DOS(ERRSRV,ERRerror);
4989 /****************************************************************************
4990 Reply to a SMBfindclose (stop trans2 directory search).
4991 ****************************************************************************/
4993 int reply_findclose(connection_struct *conn,
4994 char *inbuf,char *outbuf,int length,int bufsize)
4996 int outsize = 0;
4997 int dptr_num=SVALS(inbuf,smb_vwv0);
4998 START_PROFILE(SMBfindclose);
5000 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5002 dptr_close(&dptr_num);
5004 outsize = set_message(outbuf,0,0,False);
5006 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5008 END_PROFILE(SMBfindclose);
5009 return(outsize);
5012 /****************************************************************************
5013 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5014 ****************************************************************************/
5016 int reply_findnclose(connection_struct *conn,
5017 char *inbuf,char *outbuf,int length,int bufsize)
5019 int outsize = 0;
5020 int dptr_num= -1;
5021 START_PROFILE(SMBfindnclose);
5023 dptr_num = SVAL(inbuf,smb_vwv0);
5025 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5027 /* We never give out valid handles for a
5028 findnotifyfirst - so any dptr_num is ok here.
5029 Just ignore it. */
5031 outsize = set_message(outbuf,0,0,False);
5033 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5035 END_PROFILE(SMBfindnclose);
5036 return(outsize);
5039 int handle_trans2(connection_struct *conn,
5040 struct trans_state *state,
5041 char *inbuf, char *outbuf, int size, int bufsize)
5043 int outsize;
5045 if (Protocol >= PROTOCOL_NT1) {
5046 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5049 /* Now we must call the relevant TRANS2 function */
5050 switch(state->call) {
5051 case TRANSACT2_OPEN:
5053 START_PROFILE_NESTED(Trans2_open);
5054 outsize = call_trans2open(
5055 conn, inbuf, outbuf, bufsize,
5056 &state->param, state->total_param,
5057 &state->data, state->total_data,
5058 state->max_data_return);
5059 END_PROFILE_NESTED(Trans2_open);
5060 break;
5063 case TRANSACT2_FINDFIRST:
5065 START_PROFILE_NESTED(Trans2_findfirst);
5066 outsize = call_trans2findfirst(
5067 conn, inbuf, outbuf, bufsize,
5068 &state->param, state->total_param,
5069 &state->data, state->total_data,
5070 state->max_data_return);
5071 END_PROFILE_NESTED(Trans2_findfirst);
5072 break;
5075 case TRANSACT2_FINDNEXT:
5077 START_PROFILE_NESTED(Trans2_findnext);
5078 outsize = call_trans2findnext(
5079 conn, inbuf, outbuf, size, bufsize,
5080 &state->param, state->total_param,
5081 &state->data, state->total_data,
5082 state->max_data_return);
5083 END_PROFILE_NESTED(Trans2_findnext);
5084 break;
5087 case TRANSACT2_QFSINFO:
5089 START_PROFILE_NESTED(Trans2_qfsinfo);
5090 outsize = call_trans2qfsinfo(
5091 conn, inbuf, outbuf, size, bufsize,
5092 &state->param, state->total_param,
5093 &state->data, state->total_data,
5094 state->max_data_return);
5095 END_PROFILE_NESTED(Trans2_qfsinfo);
5096 break;
5099 case TRANSACT2_SETFSINFO:
5101 START_PROFILE_NESTED(Trans2_setfsinfo);
5102 outsize = call_trans2setfsinfo(
5103 conn, inbuf, outbuf, size, bufsize,
5104 &state->param, state->total_param,
5105 &state->data, state->total_data,
5106 state->max_data_return);
5107 END_PROFILE_NESTED(Trans2_setfsinfo);
5108 break;
5111 case TRANSACT2_QPATHINFO:
5112 case TRANSACT2_QFILEINFO:
5114 START_PROFILE_NESTED(Trans2_qpathinfo);
5115 outsize = call_trans2qfilepathinfo(
5116 conn, inbuf, outbuf, size, bufsize, state->call,
5117 &state->param, state->total_param,
5118 &state->data, state->total_data,
5119 state->max_data_return);
5120 END_PROFILE_NESTED(Trans2_qpathinfo);
5121 break;
5124 case TRANSACT2_SETPATHINFO:
5125 case TRANSACT2_SETFILEINFO:
5127 START_PROFILE_NESTED(Trans2_setpathinfo);
5128 outsize = call_trans2setfilepathinfo(
5129 conn, inbuf, outbuf, size, bufsize, state->call,
5130 &state->param, state->total_param,
5131 &state->data, state->total_data,
5132 state->max_data_return);
5133 END_PROFILE_NESTED(Trans2_setpathinfo);
5134 break;
5137 case TRANSACT2_FINDNOTIFYFIRST:
5139 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5140 outsize = call_trans2findnotifyfirst(
5141 conn, inbuf, outbuf, size, bufsize,
5142 &state->param, state->total_param,
5143 &state->data, state->total_data,
5144 state->max_data_return);
5145 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5146 break;
5149 case TRANSACT2_FINDNOTIFYNEXT:
5151 START_PROFILE_NESTED(Trans2_findnotifynext);
5152 outsize = call_trans2findnotifynext(
5153 conn, inbuf, outbuf, size, bufsize,
5154 &state->param, state->total_param,
5155 &state->data, state->total_data,
5156 state->max_data_return);
5157 END_PROFILE_NESTED(Trans2_findnotifynext);
5158 break;
5161 case TRANSACT2_MKDIR:
5163 START_PROFILE_NESTED(Trans2_mkdir);
5164 outsize = call_trans2mkdir(
5165 conn, inbuf, outbuf, size, bufsize,
5166 &state->param, state->total_param,
5167 &state->data, state->total_data,
5168 state->max_data_return);
5169 END_PROFILE_NESTED(Trans2_mkdir);
5170 break;
5173 case TRANSACT2_GET_DFS_REFERRAL:
5175 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5176 outsize = call_trans2getdfsreferral(
5177 conn, inbuf, outbuf, size, bufsize,
5178 &state->param, state->total_param,
5179 &state->data, state->total_data,
5180 state->max_data_return);
5181 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5182 break;
5185 case TRANSACT2_IOCTL:
5187 START_PROFILE_NESTED(Trans2_ioctl);
5188 outsize = call_trans2ioctl(
5189 conn, inbuf, outbuf, size, bufsize,
5190 &state->param, state->total_param,
5191 &state->data, state->total_data,
5192 state->max_data_return);
5193 END_PROFILE_NESTED(Trans2_ioctl);
5194 break;
5197 default:
5198 /* Error in request */
5199 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5200 outsize = ERROR_DOS(ERRSRV,ERRerror);
5203 return outsize;
5206 /****************************************************************************
5207 Reply to a SMBtrans2.
5208 ****************************************************************************/
5210 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5211 int size, int bufsize)
5213 int outsize = 0;
5214 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5215 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5216 unsigned int psoff = SVAL(inbuf, smb_psoff);
5217 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5218 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5219 struct trans_state *state;
5220 NTSTATUS result;
5222 START_PROFILE(SMBtrans2);
5224 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5225 if (!NT_STATUS_IS_OK(result)) {
5226 DEBUG(2, ("Got invalid trans2 request: %s\n",
5227 nt_errstr(result)));
5228 END_PROFILE(SMBtrans2);
5229 return ERROR_NT(result);
5232 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5233 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5234 END_PROFILE(SMBtrans2);
5235 return ERROR_DOS(ERRSRV,ERRaccess);
5238 if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5239 DEBUG(0, ("talloc failed\n"));
5240 END_PROFILE(SMBtrans2);
5241 return ERROR_NT(NT_STATUS_NO_MEMORY);
5244 state->cmd = SMBtrans2;
5246 state->mid = SVAL(inbuf, smb_mid);
5247 state->vuid = SVAL(inbuf, smb_uid);
5248 state->setup_count = SVAL(inbuf, smb_suwcnt);
5249 state->total_param = SVAL(inbuf, smb_tpscnt);
5250 state->param = NULL;
5251 state->total_data = SVAL(inbuf, smb_tdscnt);
5252 state->data = NULL;
5253 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5254 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5255 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5256 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5257 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5259 state->call = tran_call;
5261 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5262 is so as a sanity check */
5263 if (state->setup_count != 1) {
5265 * Need to have rc=0 for ioctl to get job id for OS/2.
5266 * Network printing will fail if function is not successful.
5267 * Similar function in reply.c will be used if protocol
5268 * is LANMAN1.0 instead of LM1.2X002.
5269 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5270 * outbuf doesn't have to be set(only job id is used).
5272 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5273 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5274 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5275 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5276 } else {
5277 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5278 DEBUG(2,("Transaction is %d\n",tran_call));
5279 TALLOC_FREE(state);
5280 END_PROFILE(SMBtrans2);
5281 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5285 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5286 goto bad_param;
5288 if (state->total_data) {
5289 /* Can't use talloc here, the core routines do realloc on the
5290 * params and data. */
5291 state->data = SMB_MALLOC(state->total_data);
5292 if (state->data == NULL) {
5293 DEBUG(0,("reply_trans2: data malloc fail for %u "
5294 "bytes !\n", (unsigned int)state->total_data));
5295 TALLOC_FREE(state);
5296 END_PROFILE(SMBtrans2);
5297 return(ERROR_DOS(ERRDOS,ERRnomem));
5299 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5300 goto bad_param;
5301 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5302 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5303 goto bad_param;
5305 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5308 if (state->total_param) {
5309 /* Can't use talloc here, the core routines do realloc on the
5310 * params and data. */
5311 state->param = SMB_MALLOC(state->total_param);
5312 if (state->param == NULL) {
5313 DEBUG(0,("reply_trans: param malloc fail for %u "
5314 "bytes !\n", (unsigned int)state->total_param));
5315 SAFE_FREE(state->data);
5316 TALLOC_FREE(state);
5317 END_PROFILE(SMBtrans2);
5318 return(ERROR_DOS(ERRDOS,ERRnomem));
5320 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5321 goto bad_param;
5322 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5323 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5324 goto bad_param;
5326 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5329 state->received_data = dscnt;
5330 state->received_param = pscnt;
5332 if ((state->received_param == state->total_param) &&
5333 (state->received_data == state->total_data)) {
5335 outsize = handle_trans2(conn, state, inbuf, outbuf,
5336 size, bufsize);
5337 SAFE_FREE(state->data);
5338 SAFE_FREE(state->param);
5339 TALLOC_FREE(state);
5340 END_PROFILE(SMBtrans2);
5341 return outsize;
5344 DLIST_ADD(conn->pending_trans, state);
5346 /* We need to send an interim response then receive the rest
5347 of the parameter/data bytes */
5348 outsize = set_message(outbuf,0,0,False);
5349 show_msg(outbuf);
5350 END_PROFILE(SMBtrans2);
5351 return outsize;
5353 bad_param:
5355 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5356 SAFE_FREE(state->data);
5357 SAFE_FREE(state->param);
5358 TALLOC_FREE(state);
5359 END_PROFILE(SMBtrans2);
5360 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5364 /****************************************************************************
5365 Reply to a SMBtranss2
5366 ****************************************************************************/
5368 int reply_transs2(connection_struct *conn,
5369 char *inbuf,char *outbuf,int size,int bufsize)
5371 int outsize = 0;
5372 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5373 struct trans_state *state;
5375 START_PROFILE(SMBtranss2);
5377 show_msg(inbuf);
5379 for (state = conn->pending_trans; state != NULL;
5380 state = state->next) {
5381 if (state->mid == SVAL(inbuf,smb_mid)) {
5382 break;
5386 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5387 END_PROFILE(SMBtranss2);
5388 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5391 /* Revise state->total_param and state->total_data in case they have
5392 changed downwards */
5394 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5395 state->total_param = SVAL(inbuf, smb_tpscnt);
5396 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5397 state->total_data = SVAL(inbuf, smb_tdscnt);
5399 pcnt = SVAL(inbuf, smb_spscnt);
5400 poff = SVAL(inbuf, smb_spsoff);
5401 pdisp = SVAL(inbuf, smb_spsdisp);
5403 dcnt = SVAL(inbuf, smb_sdscnt);
5404 doff = SVAL(inbuf, smb_sdsoff);
5405 ddisp = SVAL(inbuf, smb_sdsdisp);
5407 state->received_param += pcnt;
5408 state->received_data += dcnt;
5410 if ((state->received_data > state->total_data) ||
5411 (state->received_param > state->total_param))
5412 goto bad_param;
5414 if (pcnt) {
5415 if (pdisp+pcnt > state->total_param)
5416 goto bad_param;
5417 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5418 goto bad_param;
5419 if (pdisp > state->total_param)
5420 goto bad_param;
5421 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5422 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5423 goto bad_param;
5424 if (state->param + pdisp < state->param)
5425 goto bad_param;
5427 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5428 pcnt);
5431 if (dcnt) {
5432 if (ddisp+dcnt > state->total_data)
5433 goto bad_param;
5434 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5435 goto bad_param;
5436 if (ddisp > state->total_data)
5437 goto bad_param;
5438 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5439 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5440 goto bad_param;
5441 if (state->data + ddisp < state->data)
5442 goto bad_param;
5444 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5445 dcnt);
5448 if ((state->received_param < state->total_param) ||
5449 (state->received_data < state->total_data)) {
5450 END_PROFILE(SMBtranss2);
5451 return -1;
5454 /* construct_reply_common has done us the favor to pre-fill the
5455 * command field with SMBtranss2 which is wrong :-)
5457 SCVAL(outbuf,smb_com,SMBtrans2);
5459 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5461 DLIST_REMOVE(conn->pending_trans, state);
5462 SAFE_FREE(state->data);
5463 SAFE_FREE(state->param);
5464 TALLOC_FREE(state);
5466 if (outsize == 0) {
5467 END_PROFILE(SMBtranss2);
5468 return(ERROR_DOS(ERRSRV,ERRnosupport));
5471 END_PROFILE(SMBtranss2);
5472 return(outsize);
5474 bad_param:
5476 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5477 DLIST_REMOVE(conn->pending_trans, state);
5478 SAFE_FREE(state->data);
5479 SAFE_FREE(state->param);
5480 TALLOC_FREE(state);
5481 END_PROFILE(SMBtranss2);
5482 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);