r5831: Along with jra's recent checkins, fix dir/xcopy of empty dirs on OS/2. Bugs
[Samba/bb.git] / source / smbd / trans2.c
blobac2a29bd6049cfaa50b4cd641d930df5993a698b
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest allocation roundup size boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44 /* Only roundup for Windows clients. */
45 enum remote_arch_types ra_type = get_remote_arch();
46 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47 val = SMB_ROUNDUP(val,rval);
49 return val;
52 /********************************************************************
53 Given a stat buffer return the allocated size on disk, taking into
54 account sparse files.
55 ********************************************************************/
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
59 SMB_BIG_UINT ret;
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
63 #else
64 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
65 #endif
67 if (!ret && fsp && fsp->initial_allocation_size)
68 ret = fsp->initial_allocation_size;
70 return smb_roundup(conn, ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
80 NULL
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
89 int i;
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
93 return True;
95 return False;
98 struct ea_list {
99 struct ea_list *next, *prev;
100 struct ea_struct ea;
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
112 char *val = NULL;
113 ssize_t sizeret;
115 again:
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
118 if (!val) {
119 return False;
122 if (fsp && fsp->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
124 } else {
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
129 attr_size = 65536;
130 goto again;
133 if (sizeret == -1) {
134 return False;
137 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138 dump_data(10, val, sizeret);
140 pea->flags = 0;
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
143 } else {
144 pea->name = ea_name;
146 pea->value.data = val;
147 pea->value.length = (size_t)sizeret;
148 return True;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
157 /* Get a list of all xattrs. Max namesize is 64k. */
158 size_t ea_namelist_size = 1024;
159 char *ea_namelist;
160 char *p;
161 ssize_t sizeret;
162 int i;
163 struct ea_list *ea_list_head = NULL;
165 *pea_total_len = 0;
167 if (!lp_ea_support(SNUM(conn))) {
168 return NULL;
171 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
172 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
173 if (fsp && fsp->fd != -1) {
174 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
175 } else {
176 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
179 if (sizeret == -1 && errno == ERANGE) {
180 ea_namelist_size *= 2;
181 } else {
182 break;
186 if (sizeret == -1)
187 return NULL;
189 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
191 if (sizeret) {
192 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
193 struct ea_list *listp, *tmp;
195 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
196 continue;
198 listp = TALLOC_P(mem_ctx, struct ea_list);
199 if (!listp)
200 return NULL;
202 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
203 return NULL;
207 fstring dos_ea_name;
208 push_ascii_fstring(dos_ea_name, listp->ea.name);
209 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
210 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
211 *pea_total_len, dos_ea_name,
212 (unsigned int)listp->ea.value.length ));
214 DLIST_ADD_END(ea_list_head, listp, tmp);
216 /* Add on 4 for total length. */
217 if (*pea_total_len) {
218 *pea_total_len += 4;
222 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
223 return ea_list_head;
226 /****************************************************************************
227 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
228 that was filled.
229 ****************************************************************************/
231 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
232 connection_struct *conn, files_struct *fsp, const char *fname)
234 unsigned int ret_data_size = 4;
235 char *p = pdata;
236 size_t total_ea_len;
237 TALLOC_CTX *mem_ctx;
238 struct ea_list *ea_list;
240 SMB_ASSERT(total_data_size >= 4);
242 SIVAL(pdata,0,0);
243 if (!lp_ea_support(SNUM(conn))) {
244 return 4;
246 mem_ctx = talloc_init("fill_ea_buffer");
247 if (!mem_ctx) {
248 return 4;
251 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
252 if (!ea_list) {
253 talloc_destroy(mem_ctx);
254 return 4;
257 if (total_ea_len > total_data_size) {
258 talloc_destroy(mem_ctx);
259 return 4;
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 size_t dos_namelen;
264 fstring dos_ea_name;
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
268 break;
270 if (ea_list->ea.value.length > 65535) {
271 break;
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274 break;
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
290 ret_data_size, total_ea_len ));
291 talloc_destroy(mem_ctx);
292 SIVAL(pdata,0,ret_data_size);
293 return ret_data_size;
296 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
298 size_t total_ea_len = 0;
299 TALLOC_CTX *mem_ctx = NULL;
301 if (!lp_ea_support(SNUM(conn))) {
302 return 0;
304 mem_ctx = talloc_init("estimate_ea_size");
305 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
306 talloc_destroy(mem_ctx);
307 return total_ea_len;
310 /****************************************************************************
311 Ensure the EA name is case insensitive by matching any existing EA name.
312 ****************************************************************************/
314 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
316 size_t total_ea_len;
317 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
318 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
320 for (; ea_list; ea_list = ea_list->next) {
321 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
322 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
323 &unix_ea_name[5], ea_list->ea.name));
324 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 break;
328 talloc_destroy(mem_ctx);
331 /****************************************************************************
332 Set or delete an extended attribute.
333 ****************************************************************************/
335 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
336 char *pdata, int total_data)
338 unsigned int namelen;
339 unsigned int ealen;
340 int ret;
341 fstring unix_ea_name;
343 if (!lp_ea_support(SNUM(conn))) {
344 return NT_STATUS_EAS_NOT_SUPPORTED;
347 if (total_data < 8) {
348 return NT_STATUS_INVALID_PARAMETER;
351 if (IVAL(pdata,0) > total_data) {
352 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
353 return NT_STATUS_INVALID_PARAMETER;
356 pdata += 4;
357 namelen = CVAL(pdata,1);
358 ealen = SVAL(pdata,2);
359 pdata += 4;
360 if (total_data < 8 + namelen + 1 + ealen) {
361 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
362 (unsigned int)total_data, namelen, ealen));
363 return NT_STATUS_INVALID_PARAMETER;
366 if (pdata[namelen] != '\0') {
367 DEBUG(10,("set_ea: ea name not null terminated\n"));
368 return NT_STATUS_INVALID_PARAMETER;
371 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
372 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
373 pdata += (namelen + 1);
375 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
377 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
378 if (ealen) {
379 DEBUG(10,("set_ea: data :\n"));
380 dump_data(10, pdata, ealen);
383 if (samba_private_attr_name(unix_ea_name)) {
384 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
385 return NT_STATUS_ACCESS_DENIED;
388 if (ealen == 0) {
389 /* Remove the attribute. */
390 if (fsp && (fsp->fd != -1)) {
391 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
392 unix_ea_name, fsp->fsp_name));
393 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
394 } else {
395 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
396 unix_ea_name, fname));
397 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
399 #ifdef ENOATTR
400 /* Removing a non existent attribute always succeeds. */
401 if (ret == -1 && errno == ENOATTR) {
402 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
403 ret = 0;
405 #endif
406 } else {
407 if (fsp && (fsp->fd != -1)) {
408 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
409 unix_ea_name, fsp->fsp_name));
410 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
411 } else {
412 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
413 unix_ea_name, fname));
414 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
418 if (ret == -1) {
419 #ifdef ENOTSUP
420 if (errno == ENOTSUP) {
421 return NT_STATUS_EAS_NOT_SUPPORTED;
423 #endif
424 return map_nt_error_from_unix(errno);
427 return NT_STATUS_OK;
430 /****************************************************************************
431 Send the required number of replies back.
432 We assume all fields other than the data fields are
433 set correctly for the type of call.
434 HACK ! Always assumes smb_setup field is zero.
435 ****************************************************************************/
437 static int send_trans2_replies(char *outbuf,
438 int bufsize,
439 char *params,
440 int paramsize,
441 char *pdata,
442 int datasize)
444 /* As we are using a protocol > LANMAN1 then the max_send
445 variable must have been set in the sessetupX call.
446 This takes precedence over the max_xmit field in the
447 global struct. These different max_xmit variables should
448 be merged as this is now too confusing */
450 extern int max_send;
451 int data_to_send = datasize;
452 int params_to_send = paramsize;
453 int useable_space;
454 char *pp = params;
455 char *pd = pdata;
456 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
457 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
458 int data_alignment_offset = 0;
460 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
462 set_message(outbuf,10,0,True);
464 /* If there genuinely are no parameters or data to send just send the empty packet */
466 if(params_to_send == 0 && data_to_send == 0) {
467 if (!send_smb(smbd_server_fd(),outbuf))
468 exit_server("send_trans2_replies: send_smb failed.");
469 return 0;
472 /* When sending params and data ensure that both are nicely aligned */
473 /* Only do this alignment when there is also data to send - else
474 can cause NT redirector problems. */
476 if (((params_to_send % 4) != 0) && (data_to_send != 0))
477 data_alignment_offset = 4 - (params_to_send % 4);
479 /* Space is bufsize minus Netbios over TCP header minus SMB header */
480 /* The alignment_offset is to align the param bytes on an even byte
481 boundary. NT 4.0 Beta needs this to work correctly. */
483 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
485 /* useable_space can never be more than max_send minus the alignment offset. */
487 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
489 while (params_to_send || data_to_send) {
490 /* Calculate whether we will totally or partially fill this packet */
492 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
494 /* We can never send more than useable_space */
496 * Note that 'useable_space' does not include the alignment offsets,
497 * but we must include the alignment offsets in the calculation of
498 * the length of the data we send over the wire, as the alignment offsets
499 * are sent here. Fix from Marc_Jacobsen@hp.com.
502 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
504 set_message(outbuf, 10, total_sent_thistime, True);
506 /* Set total params and data to be sent */
507 SSVAL(outbuf,smb_tprcnt,paramsize);
508 SSVAL(outbuf,smb_tdrcnt,datasize);
510 /* Calculate how many parameters and data we can fit into
511 * this packet. Parameters get precedence
514 params_sent_thistime = MIN(params_to_send,useable_space);
515 data_sent_thistime = useable_space - params_sent_thistime;
516 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
518 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
520 /* smb_proff is the offset from the start of the SMB header to the
521 parameter bytes, however the first 4 bytes of outbuf are
522 the Netbios over TCP header. Thus use smb_base() to subtract
523 them from the calculation */
525 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
527 if(params_sent_thistime == 0)
528 SSVAL(outbuf,smb_prdisp,0);
529 else
530 /* Absolute displacement of param bytes sent in this packet */
531 SSVAL(outbuf,smb_prdisp,pp - params);
533 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
534 if(data_sent_thistime == 0) {
535 SSVAL(outbuf,smb_droff,0);
536 SSVAL(outbuf,smb_drdisp, 0);
537 } else {
538 /* The offset of the data bytes is the offset of the
539 parameter bytes plus the number of parameters being sent this time */
540 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
541 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
542 SSVAL(outbuf,smb_drdisp, pd - pdata);
545 /* Copy the param bytes into the packet */
547 if(params_sent_thistime)
548 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
550 /* Copy in the data bytes */
551 if(data_sent_thistime)
552 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
553 data_alignment_offset,pd,data_sent_thistime);
555 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
556 params_sent_thistime, data_sent_thistime, useable_space));
557 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
558 params_to_send, data_to_send, paramsize, datasize));
560 /* Send the packet */
561 if (!send_smb(smbd_server_fd(),outbuf))
562 exit_server("send_trans2_replies: send_smb failed.");
564 pp += params_sent_thistime;
565 pd += data_sent_thistime;
567 params_to_send -= params_sent_thistime;
568 data_to_send -= data_sent_thistime;
570 /* Sanity check */
571 if(params_to_send < 0 || data_to_send < 0) {
572 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
573 params_to_send, data_to_send));
574 return -1;
578 return 0;
581 /****************************************************************************
582 Reply to a TRANSACT2_OPEN.
583 ****************************************************************************/
585 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
586 char **pparams, int total_params, char **ppdata, int total_data,
587 unsigned int max_data_bytes)
589 char *params = *pparams;
590 int16 open_mode;
591 int16 open_attr;
592 BOOL oplock_request;
593 #if 0
594 BOOL return_additional_info;
595 int16 open_sattr;
596 time_t open_time;
597 #endif
598 int16 open_ofun;
599 int32 open_size;
600 char *pname;
601 pstring fname;
602 SMB_OFF_T size=0;
603 int fmode=0,mtime=0,rmode;
604 SMB_INO_T inode = 0;
605 SMB_STRUCT_STAT sbuf;
606 int smb_action = 0;
607 BOOL bad_path = False;
608 files_struct *fsp;
609 NTSTATUS status;
612 * Ensure we have enough parameters to perform the operation.
615 if (total_params < 29)
616 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
618 open_mode = SVAL(params, 2);
619 open_attr = SVAL(params,6);
620 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
621 #if 0
622 return_additional_info = BITSETW(params,0);
623 open_sattr = SVAL(params, 4);
624 open_time = make_unix_date3(params+8);
625 #endif
626 open_ofun = SVAL(params,12);
627 open_size = IVAL(params,14);
628 pname = &params[28];
630 if (IS_IPC(conn))
631 return(ERROR_DOS(ERRSRV,ERRaccess));
633 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
634 if (!NT_STATUS_IS_OK(status)) {
635 return ERROR_NT(status);
638 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
639 fname,open_mode, open_attr, open_ofun, open_size));
641 /* XXXX we need to handle passed times, sattr and flags */
643 unix_convert(fname,conn,0,&bad_path,&sbuf);
644 if (bad_path) {
645 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
648 if (!check_name(fname,conn)) {
649 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
652 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
653 oplock_request, &rmode,&smb_action);
655 if (!fsp) {
656 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
657 /* We have re-scheduled this call. */
658 clear_cached_errors();
659 return -1;
661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
664 size = get_file_size(sbuf);
665 fmode = dos_mode(conn,fname,&sbuf);
666 mtime = sbuf.st_mtime;
667 inode = sbuf.st_ino;
668 if (fmode & aDIR) {
669 close_file(fsp,False);
670 return(ERROR_DOS(ERRDOS,ERRnoaccess));
673 /* Realloc the size of parameters and data we will return */
674 params = SMB_REALLOC(*pparams, 28);
675 if( params == NULL )
676 return(ERROR_DOS(ERRDOS,ERRnomem));
677 *pparams = params;
679 memset((char *)params,'\0',28);
680 SSVAL(params,0,fsp->fnum);
681 SSVAL(params,2,fmode);
682 put_dos_date2(params,4, mtime);
683 SIVAL(params,8, (uint32)size);
684 SSVAL(params,12,rmode);
686 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
687 smb_action |= EXTENDED_OPLOCK_GRANTED;
689 SSVAL(params,18,smb_action);
692 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
694 SIVAL(params,20,inode);
696 /* Send the required number of replies */
697 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
699 return -1;
702 /*********************************************************
703 Routine to check if a given string matches exactly.
704 as a special case a mask of "." does NOT match. That
705 is required for correct wildcard semantics
706 Case can be significant or not.
707 **********************************************************/
709 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
711 if (mask[0] == '.' && mask[1] == 0)
712 return False;
713 if (case_sig)
714 return strcmp(str,mask)==0;
715 if (StrCaseCmp(str,mask) != 0) {
716 return False;
718 if (ms_has_wild(str)) {
719 return False;
721 return True;
724 /****************************************************************************
725 Return the filetype for UNIX extensions.
726 ****************************************************************************/
728 static uint32 unix_filetype(mode_t mode)
730 if(S_ISREG(mode))
731 return UNIX_TYPE_FILE;
732 else if(S_ISDIR(mode))
733 return UNIX_TYPE_DIR;
734 #ifdef S_ISLNK
735 else if(S_ISLNK(mode))
736 return UNIX_TYPE_SYMLINK;
737 #endif
738 #ifdef S_ISCHR
739 else if(S_ISCHR(mode))
740 return UNIX_TYPE_CHARDEV;
741 #endif
742 #ifdef S_ISBLK
743 else if(S_ISBLK(mode))
744 return UNIX_TYPE_BLKDEV;
745 #endif
746 #ifdef S_ISFIFO
747 else if(S_ISFIFO(mode))
748 return UNIX_TYPE_FIFO;
749 #endif
750 #ifdef S_ISSOCK
751 else if(S_ISSOCK(mode))
752 return UNIX_TYPE_SOCKET;
753 #endif
755 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
756 return UNIX_TYPE_UNKNOWN;
759 /****************************************************************************
760 Map wire perms onto standard UNIX permissions. Obey share restrictions.
761 ****************************************************************************/
763 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
765 mode_t ret = 0;
767 if (perms == SMB_MODE_NO_CHANGE)
768 return pst->st_mode;
770 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
771 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
772 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
773 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
774 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
775 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
776 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
777 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
778 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
779 #ifdef S_ISVTX
780 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
781 #endif
782 #ifdef S_ISGID
783 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
784 #endif
785 #ifdef S_ISUID
786 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
787 #endif
789 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
790 ret &= lp_dir_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_dir_mode(SNUM(conn));
793 } else {
794 /* Apply mode mask */
795 ret &= lp_create_mask(SNUM(conn));
796 /* Add in force bits */
797 ret |= lp_force_create_mode(SNUM(conn));
800 return ret;
803 /****************************************************************************
804 Get a level dependent lanman2 dir entry.
805 ****************************************************************************/
807 static BOOL get_lanman2_dir_entry(connection_struct *conn,
808 void *inbuf, void *outbuf,
809 char *path_mask,int dirtype,int info_level,
810 int requires_resume_key,
811 BOOL dont_descend,char **ppdata,
812 char *base_data, int space_remaining,
813 BOOL *out_of_space, BOOL *got_exact_match,
814 int *last_entry_off)
816 const char *dname;
817 BOOL found = False;
818 SMB_STRUCT_STAT sbuf;
819 pstring mask;
820 pstring pathreal;
821 pstring fname;
822 char *p, *q, *pdata = *ppdata;
823 uint32 reskey=0;
824 long prev_dirpos=0;
825 int mode=0;
826 SMB_OFF_T file_size = 0;
827 SMB_BIG_UINT allocation_size = 0;
828 uint32 len;
829 time_t mdate=0, adate=0, cdate=0;
830 char *nameptr;
831 char *last_entry_ptr;
832 BOOL was_8_3;
833 int nt_extmode; /* Used for NT connections instead of mode */
834 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
836 *fname = 0;
837 *out_of_space = False;
838 *got_exact_match = False;
840 if (!conn->dirptr)
841 return(False);
843 p = strrchr_m(path_mask,'/');
844 if(p != NULL) {
845 if(p[1] == '\0')
846 pstrcpy(mask,"*.*");
847 else
848 pstrcpy(mask, p+1);
849 } else
850 pstrcpy(mask, path_mask);
853 while (!found) {
854 BOOL got_match;
855 /* Needed if we run out of space */
856 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
857 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
860 * Due to bugs in NT client redirectors we are not using
861 * resume keys any more - set them to zero.
862 * Check out the related comments in findfirst/findnext.
863 * JRA.
866 reskey = 0;
868 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
869 (long)conn->dirptr,curr_dirpos));
871 if (!dname)
872 return(False);
874 pstrcpy(fname,dname);
876 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
877 got_match = mask_match(fname, mask, conn->case_sensitive);
879 if(!got_match && !mangle_is_8_3(fname, False)) {
882 * It turns out that NT matches wildcards against
883 * both long *and* short names. This may explain some
884 * of the wildcard wierdness from old DOS clients
885 * that some people have been seeing.... JRA.
888 pstring newname;
889 pstrcpy( newname, fname);
890 mangle_map( newname, True, False, SNUM(conn));
891 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
892 got_match = mask_match(newname, mask, conn->case_sensitive);
895 if(got_match) {
896 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
897 if (dont_descend && !isdots)
898 continue;
900 pstrcpy(pathreal,conn->dirpath);
901 if(needslash)
902 pstrcat(pathreal,"/");
903 pstrcat(pathreal,dname);
905 if (INFO_LEVEL_IS_UNIX(info_level)) {
906 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
907 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
908 pathreal,strerror(errno)));
909 continue;
911 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
913 /* Needed to show the msdfs symlinks as
914 * directories */
916 if(lp_host_msdfs() &&
917 lp_msdfs_root(SNUM(conn)) &&
918 is_msdfs_link(conn, pathreal, NULL, NULL,
919 &sbuf)) {
921 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
922 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
924 } else {
926 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
927 pathreal,strerror(errno)));
928 continue;
932 mode = dos_mode(conn,pathreal,&sbuf);
934 if (!dir_check_ftype(conn,mode,dirtype)) {
935 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
936 continue;
939 file_size = get_file_size(sbuf);
940 allocation_size = get_allocation_size(conn,NULL,&sbuf);
941 mdate = sbuf.st_mtime;
942 adate = sbuf.st_atime;
943 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
945 if (lp_dos_filetime_resolution(SNUM(conn))) {
946 cdate &= ~1;
947 mdate &= ~1;
948 adate &= ~1;
951 if(mode & aDIR) {
952 /* This is necessary, as otherwise the
953 * desktop.ini file in this folder is
954 * ignored */
955 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
956 file_size = 0;
959 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
961 found = True;
965 mangle_map(fname,False,True,SNUM(conn));
967 p = pdata;
968 last_entry_ptr = p;
970 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
972 switch (info_level) {
973 case SMB_INFO_STANDARD:
974 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
975 if(requires_resume_key) {
976 SIVAL(p,0,reskey);
977 p += 4;
979 put_dos_date2(p,l1_fdateCreation,cdate);
980 put_dos_date2(p,l1_fdateLastAccess,adate);
981 put_dos_date2(p,l1_fdateLastWrite,mdate);
982 SIVAL(p,l1_cbFile,(uint32)file_size);
983 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
984 SSVAL(p,l1_attrFile,mode);
985 p += l1_achName;
986 nameptr = p;
987 p += align_string(outbuf, p, 0);
988 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
989 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
990 if (len > 2) {
991 SCVAL(nameptr, -1, len - 2);
992 } else {
993 SCVAL(nameptr, -1, 0);
995 } else {
996 if (len > 1) {
997 SCVAL(nameptr, -1, len - 1);
998 } else {
999 SCVAL(nameptr, -1, 0);
1002 p += len;
1003 break;
1005 case SMB_INFO_QUERY_EA_SIZE:
1006 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1007 if(requires_resume_key) {
1008 SIVAL(p,0,reskey);
1009 p += 4;
1011 put_dos_date2(p,l2_fdateCreation,cdate);
1012 put_dos_date2(p,l2_fdateLastAccess,adate);
1013 put_dos_date2(p,l2_fdateLastWrite,mdate);
1014 SIVAL(p,l2_cbFile,(uint32)file_size);
1015 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1016 SSVAL(p,l2_attrFile,mode);
1018 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1019 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1021 p += l2_achName;
1022 nameptr = p - 1;
1023 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1024 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1025 if (len > 2) {
1026 len -= 2;
1027 } else {
1028 len = 0;
1030 } else {
1031 if (len > 1) {
1032 len -= 1;
1033 } else {
1034 len = 0;
1037 SCVAL(nameptr,0,len);
1038 p += len;
1039 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1040 break;
1042 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1043 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1044 was_8_3 = mangle_is_8_3(fname, True);
1045 p += 4;
1046 SIVAL(p,0,reskey); p += 4;
1047 put_long_date(p,cdate); p += 8;
1048 put_long_date(p,adate); p += 8;
1049 put_long_date(p,mdate); p += 8;
1050 put_long_date(p,mdate); p += 8;
1051 SOFF_T(p,0,file_size); p += 8;
1052 SOFF_T(p,0,allocation_size); p += 8;
1053 SIVAL(p,0,nt_extmode); p += 4;
1054 q = p; p += 4; /* q is placeholder for name length. */
1056 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1057 SIVAL(p,0,ea_size); /* Extended attributes */
1058 p += 4;
1060 /* Clear the short name buffer. This is
1061 * IMPORTANT as not doing so will trigger
1062 * a Win2k client bug. JRA.
1064 memset(p,'\0',26);
1065 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1066 pstring mangled_name;
1067 pstrcpy(mangled_name, fname);
1068 mangle_map(mangled_name,True,True,SNUM(conn));
1069 mangled_name[12] = 0;
1070 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1071 SSVAL(p, 0, len);
1072 } else {
1073 SSVAL(p,0,0);
1074 *(p+2) = 0;
1076 p += 2 + 24;
1077 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1078 SIVAL(q,0,len);
1079 p += len;
1080 len = PTR_DIFF(p, pdata);
1081 len = (len + 3) & ~3;
1082 SIVAL(pdata,0,len);
1083 p = pdata + len;
1084 break;
1086 case SMB_FIND_FILE_DIRECTORY_INFO:
1087 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1088 p += 4;
1089 SIVAL(p,0,reskey); p += 4;
1090 put_long_date(p,cdate); p += 8;
1091 put_long_date(p,adate); p += 8;
1092 put_long_date(p,mdate); p += 8;
1093 put_long_date(p,mdate); p += 8;
1094 SOFF_T(p,0,file_size); p += 8;
1095 SOFF_T(p,0,allocation_size); p += 8;
1096 SIVAL(p,0,nt_extmode); p += 4;
1097 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1098 SIVAL(p,0,len);
1099 p += 4 + len;
1100 len = PTR_DIFF(p, pdata);
1101 len = (len + 3) & ~3;
1102 SIVAL(pdata,0,len);
1103 p = pdata + len;
1104 break;
1106 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1107 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1108 p += 4;
1109 SIVAL(p,0,reskey); p += 4;
1110 put_long_date(p,cdate); p += 8;
1111 put_long_date(p,adate); p += 8;
1112 put_long_date(p,mdate); p += 8;
1113 put_long_date(p,mdate); p += 8;
1114 SOFF_T(p,0,file_size); p += 8;
1115 SOFF_T(p,0,allocation_size); p += 8;
1116 SIVAL(p,0,nt_extmode); p += 4;
1117 q = p; p += 4; /* q is placeholder for name length. */
1119 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1120 SIVAL(p,0,ea_size); /* Extended attributes */
1121 p +=4;
1123 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1124 SIVAL(q, 0, len);
1125 p += len;
1127 len = PTR_DIFF(p, pdata);
1128 len = (len + 3) & ~3;
1129 SIVAL(pdata,0,len);
1130 p = pdata + len;
1131 break;
1133 case SMB_FIND_FILE_NAMES_INFO:
1134 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1135 p += 4;
1136 SIVAL(p,0,reskey); p += 4;
1137 p += 4;
1138 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1139 acl on a dir (tridge) */
1140 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1141 SIVAL(p, -4, len);
1142 p += len;
1143 len = PTR_DIFF(p, pdata);
1144 len = (len + 3) & ~3;
1145 SIVAL(pdata,0,len);
1146 p = pdata + len;
1147 break;
1149 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1150 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1151 p += 4;
1152 SIVAL(p,0,reskey); p += 4;
1153 put_long_date(p,cdate); p += 8;
1154 put_long_date(p,adate); p += 8;
1155 put_long_date(p,mdate); p += 8;
1156 put_long_date(p,mdate); p += 8;
1157 SOFF_T(p,0,file_size); p += 8;
1158 SOFF_T(p,0,allocation_size); p += 8;
1159 SIVAL(p,0,nt_extmode); p += 4;
1160 q = p; p += 4; /* q is placeholder for name length. */
1162 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1163 SIVAL(p,0,ea_size); /* Extended attributes */
1164 p +=4;
1166 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1167 SIVAL(p,0,sbuf.st_dev); p += 4;
1168 SIVAL(p,0,sbuf.st_ino); p += 4;
1169 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1170 SIVAL(q, 0, len);
1171 p += len;
1172 len = PTR_DIFF(p, pdata);
1173 len = (len + 3) & ~3;
1174 SIVAL(pdata,0,len);
1175 p = pdata + len;
1176 break;
1178 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1179 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1180 was_8_3 = mangle_is_8_3(fname, True);
1181 p += 4;
1182 SIVAL(p,0,reskey); p += 4;
1183 put_long_date(p,cdate); p += 8;
1184 put_long_date(p,adate); p += 8;
1185 put_long_date(p,mdate); p += 8;
1186 put_long_date(p,mdate); p += 8;
1187 SOFF_T(p,0,file_size); p += 8;
1188 SOFF_T(p,0,allocation_size); p += 8;
1189 SIVAL(p,0,nt_extmode); p += 4;
1190 q = p; p += 4; /* q is placeholder for name length */
1192 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1193 SIVAL(p,0,ea_size); /* Extended attributes */
1194 p +=4;
1196 /* Clear the short name buffer. This is
1197 * IMPORTANT as not doing so will trigger
1198 * a Win2k client bug. JRA.
1200 memset(p,'\0',26);
1201 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1202 pstring mangled_name;
1203 pstrcpy(mangled_name, fname);
1204 mangle_map(mangled_name,True,True,SNUM(conn));
1205 mangled_name[12] = 0;
1206 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1207 SSVAL(p, 0, len);
1208 } else {
1209 SSVAL(p,0,0);
1210 *(p+2) = 0;
1212 p += 26;
1213 SSVAL(p,0,0); p += 2; /* Reserved ? */
1214 SIVAL(p,0,sbuf.st_dev); p += 4;
1215 SIVAL(p,0,sbuf.st_ino); p += 4;
1216 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1217 SIVAL(q,0,len);
1218 p += len;
1219 len = PTR_DIFF(p, pdata);
1220 len = (len + 3) & ~3;
1221 SIVAL(pdata,0,len);
1222 p = pdata + len;
1223 break;
1225 /* CIFS UNIX Extension. */
1227 case SMB_FIND_FILE_UNIX:
1228 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1229 p+= 4;
1230 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1232 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1233 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1234 p+= 8;
1236 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1237 p+= 8;
1239 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1240 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1241 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1242 p+= 24;
1244 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1245 SIVAL(p,4,0);
1246 p+= 8;
1248 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1249 SIVAL(p,4,0);
1250 p+= 8;
1252 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1253 p+= 4;
1255 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1256 SIVAL(p,4,0);
1257 p+= 8;
1259 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1260 SIVAL(p,4,0);
1261 p+= 8;
1263 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1264 p+= 8;
1266 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1267 SIVAL(p,4,0);
1268 p+= 8;
1270 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1271 SIVAL(p,4,0);
1272 p+= 8;
1274 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1275 p += len;
1277 len = PTR_DIFF(p, pdata);
1278 len = (len + 3) & ~3;
1279 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1280 p = pdata + len;
1281 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1283 break;
1285 default:
1286 return(False);
1290 if (PTR_DIFF(p,pdata) > space_remaining) {
1291 /* Move the dirptr back to prev_dirpos */
1292 dptr_SeekDir(conn->dirptr, prev_dirpos);
1293 *out_of_space = True;
1294 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1295 return False; /* Not finished - just out of space */
1298 /* Setup the last entry pointer, as an offset from base_data */
1299 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1300 /* Advance the data pointer to the next slot */
1301 *ppdata = p;
1303 return(found);
1306 /****************************************************************************
1307 Reply to a TRANS2_FINDFIRST.
1308 ****************************************************************************/
1310 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1311 char **pparams, int total_params, char **ppdata, int total_data,
1312 unsigned int max_data_bytes)
1314 /* We must be careful here that we don't return more than the
1315 allowed number of data bytes. If this means returning fewer than
1316 maxentries then so be it. We assume that the redirector has
1317 enough room for the fixed number of parameter bytes it has
1318 requested. */
1319 char *params = *pparams;
1320 char *pdata = *ppdata;
1321 int dirtype = SVAL(params,0);
1322 int maxentries = SVAL(params,2);
1323 uint16 findfirst_flags = SVAL(params,4);
1324 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1325 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1326 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1327 int info_level = SVAL(params,6);
1328 pstring directory;
1329 pstring mask;
1330 char *p;
1331 int last_entry_off=0;
1332 int dptr_num = -1;
1333 int numentries = 0;
1334 int i;
1335 BOOL finished = False;
1336 BOOL dont_descend = False;
1337 BOOL out_of_space = False;
1338 int space_remaining;
1339 BOOL bad_path = False;
1340 SMB_STRUCT_STAT sbuf;
1341 NTSTATUS ntstatus = NT_STATUS_OK;
1343 if (total_params < 12)
1344 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1346 *directory = *mask = 0;
1348 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1349 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1350 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1351 info_level, max_data_bytes));
1353 if (!maxentries) {
1354 /* W2K3 seems to treat zero as 1. */
1355 maxentries = 1;
1358 switch (info_level) {
1359 case SMB_INFO_STANDARD:
1360 case SMB_INFO_QUERY_EA_SIZE:
1361 case SMB_FIND_FILE_DIRECTORY_INFO:
1362 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1363 case SMB_FIND_FILE_NAMES_INFO:
1364 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1365 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1366 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1367 break;
1368 case SMB_FIND_FILE_UNIX:
1369 if (!lp_unix_extensions())
1370 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1371 break;
1372 default:
1373 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1376 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1377 if (!NT_STATUS_IS_OK(ntstatus)) {
1378 return ERROR_NT(ntstatus);
1381 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1383 unix_convert(directory,conn,0,&bad_path,&sbuf);
1384 if (bad_path) {
1385 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1387 if(!check_name(directory,conn)) {
1388 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1391 p = strrchr_m(directory,'/');
1392 if(p == NULL) {
1393 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1394 if((directory[0] == '.') && (directory[1] == '\0'))
1395 pstrcpy(mask,"*");
1396 else
1397 pstrcpy(mask,directory);
1398 pstrcpy(directory,"./");
1399 } else {
1400 pstrcpy(mask,p+1);
1401 *p = 0;
1404 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1406 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1407 if( pdata == NULL )
1408 return(ERROR_DOS(ERRDOS,ERRnomem));
1410 *ppdata = pdata;
1411 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1413 /* Realloc the params space */
1414 params = SMB_REALLOC(*pparams, 10);
1415 if (params == NULL)
1416 return ERROR_DOS(ERRDOS,ERRnomem);
1417 *pparams = params;
1419 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1420 if (dptr_num < 0)
1421 return(UNIXERROR(ERRDOS,ERRbadfile));
1423 /* Save the wildcard match and attribs we are using on this directory -
1424 needed as lanman2 assumes these are being saved between calls */
1426 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1427 dptr_close(&dptr_num);
1428 return ERROR_DOS(ERRDOS,ERRnomem);
1431 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1433 /* We don't need to check for VOL here as this is returned by
1434 a different TRANS2 call. */
1436 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1437 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1438 dont_descend = True;
1440 p = pdata;
1441 space_remaining = max_data_bytes;
1442 out_of_space = False;
1444 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1445 BOOL got_exact_match = False;
1447 /* this is a heuristic to avoid seeking the dirptr except when
1448 absolutely necessary. It allows for a filename of about 40 chars */
1449 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1450 out_of_space = True;
1451 finished = False;
1452 } else {
1453 finished = !get_lanman2_dir_entry(conn,
1454 inbuf, outbuf,
1455 mask,dirtype,info_level,
1456 requires_resume_key,dont_descend,
1457 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1458 &last_entry_off);
1461 if (finished && out_of_space)
1462 finished = False;
1464 if (!finished && !out_of_space)
1465 numentries++;
1468 * As an optimisation if we know we aren't looking
1469 * for a wildcard name (ie. the name matches the wildcard exactly)
1470 * then we can finish on any (first) match.
1471 * This speeds up large directory searches. JRA.
1474 if(got_exact_match)
1475 finished = True;
1477 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1480 /* Check if we can close the dirptr */
1481 if(close_after_first || (finished && close_if_end)) {
1482 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1483 dptr_close(&dptr_num);
1487 * If there are no matching entries we must return ERRDOS/ERRnofiles -
1488 * from observation of NT.
1491 if(numentries == 0) {
1492 dptr_close(&dptr_num);
1493 return ERROR_DOS(ERRDOS,ERRnofiles);
1496 /* At this point pdata points to numentries directory entries. */
1498 /* Set up the return parameter block */
1499 SSVAL(params,0,dptr_num);
1500 SSVAL(params,2,numentries);
1501 SSVAL(params,4,finished);
1502 SSVAL(params,6,0); /* Never an EA error */
1503 SSVAL(params,8,last_entry_off);
1505 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1507 if ((! *directory) && dptr_path(dptr_num))
1508 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1510 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1511 smb_fn_name(CVAL(inbuf,smb_com)),
1512 mask, directory, dirtype, numentries ) );
1515 * Force a name mangle here to ensure that the
1516 * mask as an 8.3 name is top of the mangled cache.
1517 * The reasons for this are subtle. Don't remove
1518 * this code unless you know what you are doing
1519 * (see PR#13758). JRA.
1522 if(!mangle_is_8_3_wildcards( mask, False))
1523 mangle_map(mask, True, True, SNUM(conn));
1525 return(-1);
1528 /****************************************************************************
1529 Reply to a TRANS2_FINDNEXT.
1530 ****************************************************************************/
1532 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1533 char **pparams, int total_params, char **ppdata, int total_data,
1534 unsigned int max_data_bytes)
1536 /* We must be careful here that we don't return more than the
1537 allowed number of data bytes. If this means returning fewer than
1538 maxentries then so be it. We assume that the redirector has
1539 enough room for the fixed number of parameter bytes it has
1540 requested. */
1541 char *params = *pparams;
1542 char *pdata = *ppdata;
1543 int dptr_num = SVAL(params,0);
1544 int maxentries = SVAL(params,2);
1545 uint16 info_level = SVAL(params,4);
1546 uint32 resume_key = IVAL(params,6);
1547 uint16 findnext_flags = SVAL(params,10);
1548 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1549 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1550 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1551 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1552 pstring resume_name;
1553 pstring mask;
1554 pstring directory;
1555 char *p;
1556 uint16 dirtype;
1557 int numentries = 0;
1558 int i, last_entry_off=0;
1559 BOOL finished = False;
1560 BOOL dont_descend = False;
1561 BOOL out_of_space = False;
1562 int space_remaining;
1563 NTSTATUS ntstatus = NT_STATUS_OK;
1565 if (total_params < 12)
1566 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1568 *mask = *directory = *resume_name = 0;
1570 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1571 if (!NT_STATUS_IS_OK(ntstatus)) {
1572 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1573 complain (it thinks we're asking for the directory above the shared
1574 path or an invalid name). Catch this as the resume name is only compared, never used in
1575 a file access. JRA. */
1576 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1577 pstrcpy(resume_name, "..");
1578 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1579 pstrcpy(resume_name, ".");
1580 } else {
1581 return ERROR_NT(ntstatus);
1585 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1586 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1587 resume_key = %d resume name = %s continue=%d level = %d\n",
1588 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1589 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1591 if (!maxentries) {
1592 /* W2K3 seems to treat zero as 1. */
1593 maxentries = 1;
1596 switch (info_level) {
1597 case SMB_INFO_STANDARD:
1598 case SMB_INFO_QUERY_EA_SIZE:
1599 case SMB_FIND_FILE_DIRECTORY_INFO:
1600 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1601 case SMB_FIND_FILE_NAMES_INFO:
1602 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1603 break;
1604 case SMB_FIND_FILE_UNIX:
1605 if (!lp_unix_extensions())
1606 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1607 break;
1608 default:
1609 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1612 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1613 if(pdata == NULL)
1614 return ERROR_DOS(ERRDOS,ERRnomem);
1616 *ppdata = pdata;
1617 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1619 /* Realloc the params space */
1620 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1621 if( params == NULL )
1622 return ERROR_DOS(ERRDOS,ERRnomem);
1624 *pparams = params;
1626 /* Check that the dptr is valid */
1627 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1628 return ERROR_DOS(ERRDOS,ERRnofiles);
1630 string_set(&conn->dirpath,dptr_path(dptr_num));
1632 /* Get the wildcard mask from the dptr */
1633 if((p = dptr_wcard(dptr_num))== NULL) {
1634 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1635 return ERROR_DOS(ERRDOS,ERRnofiles);
1638 pstrcpy(mask, p);
1639 pstrcpy(directory,conn->dirpath);
1641 /* Get the attr mask from the dptr */
1642 dirtype = dptr_attr(dptr_num);
1644 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1645 dptr_num, mask, dirtype,
1646 (long)conn->dirptr,
1647 dptr_TellDir(conn->dirptr)));
1649 /* We don't need to check for VOL here as this is returned by
1650 a different TRANS2 call. */
1652 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1653 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1654 dont_descend = True;
1656 p = pdata;
1657 space_remaining = max_data_bytes;
1658 out_of_space = False;
1661 * Seek to the correct position. We no longer use the resume key but
1662 * depend on the last file name instead.
1665 if(*resume_name && !continue_bit) {
1666 SMB_STRUCT_STAT st;
1668 long current_pos = 0;
1670 * Remember, mangle_map is called by
1671 * get_lanman2_dir_entry(), so the resume name
1672 * could be mangled. Ensure we check the unmangled name.
1675 if (mangle_is_mangled(resume_name)) {
1676 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1680 * Fix for NT redirector problem triggered by resume key indexes
1681 * changing between directory scans. We now return a resume key of 0
1682 * and instead look for the filename to continue from (also given
1683 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1684 * findfirst/findnext (as is usual) then the directory pointer
1685 * should already be at the correct place.
1688 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
1689 } /* end if resume_name && !continue_bit */
1691 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1692 BOOL got_exact_match = False;
1694 /* this is a heuristic to avoid seeking the dirptr except when
1695 absolutely necessary. It allows for a filename of about 40 chars */
1696 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1697 out_of_space = True;
1698 finished = False;
1699 } else {
1700 finished = !get_lanman2_dir_entry(conn,
1701 inbuf, outbuf,
1702 mask,dirtype,info_level,
1703 requires_resume_key,dont_descend,
1704 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1705 &last_entry_off);
1708 if (finished && out_of_space)
1709 finished = False;
1711 if (!finished && !out_of_space)
1712 numentries++;
1715 * As an optimisation if we know we aren't looking
1716 * for a wildcard name (ie. the name matches the wildcard exactly)
1717 * then we can finish on any (first) match.
1718 * This speeds up large directory searches. JRA.
1721 if(got_exact_match)
1722 finished = True;
1724 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1727 /* Check if we can close the dirptr */
1728 if(close_after_request || (finished && close_if_end)) {
1729 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1730 dptr_close(&dptr_num); /* This frees up the saved mask */
1733 /* Set up the return parameter block */
1734 SSVAL(params,0,numentries);
1735 SSVAL(params,2,finished);
1736 SSVAL(params,4,0); /* Never an EA error */
1737 SSVAL(params,6,last_entry_off);
1739 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1741 if ((! *directory) && dptr_path(dptr_num))
1742 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1744 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1745 smb_fn_name(CVAL(inbuf,smb_com)),
1746 mask, directory, dirtype, numentries ) );
1748 return(-1);
1751 /****************************************************************************
1752 Reply to a TRANS2_QFSINFO (query filesystem info).
1753 ****************************************************************************/
1755 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1756 char **pparams, int total_params, char **ppdata, int total_data,
1757 unsigned int max_data_bytes)
1759 char *pdata = *ppdata;
1760 char *params = *pparams;
1761 uint16 info_level = SVAL(params,0);
1762 int data_len, len;
1763 SMB_STRUCT_STAT st;
1764 char *vname = volume_label(SNUM(conn));
1765 int snum = SNUM(conn);
1766 char *fstype = lp_fstype(SNUM(conn));
1767 int quota_flag = 0;
1769 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1771 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1772 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1773 return ERROR_DOS(ERRSRV,ERRinvdevice);
1776 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1777 if ( pdata == NULL )
1778 return ERROR_DOS(ERRDOS,ERRnomem);
1780 *ppdata = pdata;
1781 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1783 switch (info_level) {
1784 case SMB_INFO_ALLOCATION:
1786 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1787 data_len = 18;
1788 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1789 return(UNIXERROR(ERRHRD,ERRgeneral));
1792 block_size = lp_block_size(snum);
1793 if (bsize < block_size) {
1794 SMB_BIG_UINT factor = block_size/bsize;
1795 bsize = block_size;
1796 dsize /= factor;
1797 dfree /= factor;
1799 if (bsize > block_size) {
1800 SMB_BIG_UINT factor = bsize/block_size;
1801 bsize = block_size;
1802 dsize *= factor;
1803 dfree *= factor;
1805 bytes_per_sector = 512;
1806 sectors_per_unit = bsize/bytes_per_sector;
1808 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1809 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1810 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1812 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1813 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1814 SIVAL(pdata,l1_cUnit,dsize);
1815 SIVAL(pdata,l1_cUnitAvail,dfree);
1816 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1817 break;
1820 case SMB_INFO_VOLUME:
1821 /* Return volume name */
1823 * Add volume serial number - hash of a combination of
1824 * the called hostname and the service name.
1826 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1827 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1828 SCVAL(pdata,l2_vol_cch,len);
1829 data_len = l2_vol_szVolLabel + len;
1830 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1831 (unsigned)st.st_ctime, len, vname));
1832 break;
1834 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1835 case SMB_FS_ATTRIBUTE_INFORMATION:
1838 #if defined(HAVE_SYS_QUOTAS)
1839 quota_flag = FILE_VOLUME_QUOTAS;
1840 #endif
1842 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1843 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1844 quota_flag); /* FS ATTRIBUTES */
1846 SIVAL(pdata,4,255); /* Max filename component length */
1847 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1848 and will think we can't do long filenames */
1849 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1850 SIVAL(pdata,8,len);
1851 data_len = 12 + len;
1852 break;
1854 case SMB_QUERY_FS_LABEL_INFO:
1855 case SMB_FS_LABEL_INFORMATION:
1856 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1857 data_len = 4 + len;
1858 SIVAL(pdata,0,len);
1859 break;
1861 case SMB_QUERY_FS_VOLUME_INFO:
1862 case SMB_FS_VOLUME_INFORMATION:
1865 * Add volume serial number - hash of a combination of
1866 * the called hostname and the service name.
1868 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1869 (str_checksum(get_local_machine_name())<<16));
1871 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1872 SIVAL(pdata,12,len);
1873 data_len = 18+len;
1874 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1875 (int)strlen(vname),vname, lp_servicename(snum)));
1876 break;
1878 case SMB_QUERY_FS_SIZE_INFO:
1879 case SMB_FS_SIZE_INFORMATION:
1881 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1882 data_len = 24;
1883 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1884 return(UNIXERROR(ERRHRD,ERRgeneral));
1886 block_size = lp_block_size(snum);
1887 if (bsize < block_size) {
1888 SMB_BIG_UINT factor = block_size/bsize;
1889 bsize = block_size;
1890 dsize /= factor;
1891 dfree /= factor;
1893 if (bsize > block_size) {
1894 SMB_BIG_UINT factor = bsize/block_size;
1895 bsize = block_size;
1896 dsize *= factor;
1897 dfree *= factor;
1899 bytes_per_sector = 512;
1900 sectors_per_unit = bsize/bytes_per_sector;
1901 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1902 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1903 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1904 SBIG_UINT(pdata,0,dsize);
1905 SBIG_UINT(pdata,8,dfree);
1906 SIVAL(pdata,16,sectors_per_unit);
1907 SIVAL(pdata,20,bytes_per_sector);
1908 break;
1911 case SMB_FS_FULL_SIZE_INFORMATION:
1913 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1914 data_len = 32;
1915 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1916 return(UNIXERROR(ERRHRD,ERRgeneral));
1918 block_size = lp_block_size(snum);
1919 if (bsize < block_size) {
1920 SMB_BIG_UINT factor = block_size/bsize;
1921 bsize = block_size;
1922 dsize /= factor;
1923 dfree /= factor;
1925 if (bsize > block_size) {
1926 SMB_BIG_UINT factor = bsize/block_size;
1927 bsize = block_size;
1928 dsize *= factor;
1929 dfree *= factor;
1931 bytes_per_sector = 512;
1932 sectors_per_unit = bsize/bytes_per_sector;
1933 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1934 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1935 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1936 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1937 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1938 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1939 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1940 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1941 break;
1944 case SMB_QUERY_FS_DEVICE_INFO:
1945 case SMB_FS_DEVICE_INFORMATION:
1946 data_len = 8;
1947 SIVAL(pdata,0,0); /* dev type */
1948 SIVAL(pdata,4,0); /* characteristics */
1949 break;
1951 #ifdef HAVE_SYS_QUOTAS
1952 case SMB_FS_QUOTA_INFORMATION:
1954 * what we have to send --metze:
1956 * Unknown1: 24 NULL bytes
1957 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1958 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1959 * Quota Flags: 2 byte :
1960 * Unknown3: 6 NULL bytes
1962 * 48 bytes total
1964 * details for Quota Flags:
1966 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1967 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1968 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1969 * 0x0001 Enable Quotas: enable quota for this fs
1973 /* we need to fake up a fsp here,
1974 * because its not send in this call
1976 files_struct fsp;
1977 SMB_NTQUOTA_STRUCT quotas;
1979 ZERO_STRUCT(fsp);
1980 ZERO_STRUCT(quotas);
1982 fsp.conn = conn;
1983 fsp.fnum = -1;
1984 fsp.fd = -1;
1986 /* access check */
1987 if (current_user.uid != 0) {
1988 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1989 lp_servicename(SNUM(conn)),conn->user));
1990 return ERROR_DOS(ERRDOS,ERRnoaccess);
1993 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1994 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1995 return ERROR_DOS(ERRSRV,ERRerror);
1998 data_len = 48;
2000 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2002 /* Unknown1 24 NULL bytes*/
2003 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2004 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2005 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2007 /* Default Soft Quota 8 bytes */
2008 SBIG_UINT(pdata,24,quotas.softlim);
2010 /* Default Hard Quota 8 bytes */
2011 SBIG_UINT(pdata,32,quotas.hardlim);
2013 /* Quota flag 2 bytes */
2014 SSVAL(pdata,40,quotas.qflags);
2016 /* Unknown3 6 NULL bytes */
2017 SSVAL(pdata,42,0);
2018 SIVAL(pdata,44,0);
2020 break;
2022 #endif /* HAVE_SYS_QUOTAS */
2023 case SMB_FS_OBJECTID_INFORMATION:
2024 data_len = 64;
2025 break;
2028 * Query the version and capabilities of the CIFS UNIX extensions
2029 * in use.
2032 case SMB_QUERY_CIFS_UNIX_INFO:
2033 if (!lp_unix_extensions())
2034 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2035 data_len = 12;
2036 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2037 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2038 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2039 break;
2041 case SMB_MAC_QUERY_FS_INFO:
2043 * Thursby MAC extension... ONLY on NTFS filesystems
2044 * once we do streams then we don't need this
2046 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2047 data_len = 88;
2048 SIVAL(pdata,84,0x100); /* Don't support mac... */
2049 break;
2051 /* drop through */
2052 default:
2053 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2057 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2059 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2061 return -1;
2064 #ifdef HAVE_SYS_QUOTAS
2065 /****************************************************************************
2066 Reply to a TRANS2_SETFSINFO (set filesystem info).
2067 ****************************************************************************/
2069 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2070 char **pparams, int total_params, char **ppdata, int total_data,
2071 unsigned int max_data_bytes)
2073 char *pdata = *ppdata;
2074 char *params = *pparams;
2075 files_struct *fsp = NULL;
2076 uint16 info_level;
2077 int outsize;
2078 SMB_NTQUOTA_STRUCT quotas;
2080 ZERO_STRUCT(quotas);
2082 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2084 /* access check */
2085 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2086 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2087 lp_servicename(SNUM(conn)),conn->user));
2088 return ERROR_DOS(ERRSRV,ERRaccess);
2091 /* */
2092 if (total_params < 4) {
2093 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2094 total_params));
2095 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2098 fsp = file_fsp(params,0);
2100 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2101 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2102 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2105 info_level = SVAL(params,2);
2107 switch(info_level) {
2108 case SMB_FS_QUOTA_INFORMATION:
2109 /* note: normaly there're 48 bytes,
2110 * but we didn't use the last 6 bytes for now
2111 * --metze
2113 if (total_data < 42) {
2114 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2115 total_data));
2116 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2119 /* unknown_1 24 NULL bytes in pdata*/
2121 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2122 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2123 #ifdef LARGE_SMB_OFF_T
2124 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2125 #else /* LARGE_SMB_OFF_T */
2126 if ((IVAL(pdata,28) != 0)&&
2127 ((quotas.softlim != 0xFFFFFFFF)||
2128 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2129 /* more than 32 bits? */
2130 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2132 #endif /* LARGE_SMB_OFF_T */
2134 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2135 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2136 #ifdef LARGE_SMB_OFF_T
2137 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2138 #else /* LARGE_SMB_OFF_T */
2139 if ((IVAL(pdata,36) != 0)&&
2140 ((quotas.hardlim != 0xFFFFFFFF)||
2141 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2142 /* more than 32 bits? */
2143 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2145 #endif /* LARGE_SMB_OFF_T */
2147 /* quota_flags 2 bytes **/
2148 quotas.qflags = SVAL(pdata,40);
2150 /* unknown_2 6 NULL bytes follow*/
2152 /* now set the quotas */
2153 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2154 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2155 return ERROR_DOS(ERRSRV,ERRerror);
2158 break;
2159 default:
2160 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2161 info_level));
2162 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2163 break;
2167 * sending this reply works fine,
2168 * but I'm not sure it's the same
2169 * like windows do...
2170 * --metze
2172 outsize = set_message(outbuf,10,0,True);
2174 return outsize;
2176 #endif /* HAVE_SYS_QUOTAS */
2178 /****************************************************************************
2179 Utility function to set bad path error.
2180 ****************************************************************************/
2182 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2184 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2185 err, (int)bad_path ));
2187 if(err == ENOENT) {
2188 if (bad_path) {
2189 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2190 } else {
2191 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2194 return UNIXERROR(def_class,def_code);
2197 #if defined(HAVE_POSIX_ACLS)
2198 /****************************************************************************
2199 Utility function to count the number of entries in a POSIX acl.
2200 ****************************************************************************/
2202 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2204 unsigned int ace_count = 0;
2205 int entry_id = SMB_ACL_FIRST_ENTRY;
2206 SMB_ACL_ENTRY_T entry;
2208 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2209 /* get_next... */
2210 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2211 entry_id = SMB_ACL_NEXT_ENTRY;
2213 ace_count++;
2215 return ace_count;
2218 /****************************************************************************
2219 Utility function to marshall a POSIX acl into wire format.
2220 ****************************************************************************/
2222 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2224 int entry_id = SMB_ACL_FIRST_ENTRY;
2225 SMB_ACL_ENTRY_T entry;
2227 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2228 SMB_ACL_TAG_T tagtype;
2229 SMB_ACL_PERMSET_T permset;
2230 unsigned char perms = 0;
2231 unsigned int own_grp;
2233 /* get_next... */
2234 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2235 entry_id = SMB_ACL_NEXT_ENTRY;
2238 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2239 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2240 return False;
2243 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2244 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2245 return False;
2248 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2249 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2250 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2252 SCVAL(pdata,1,perms);
2254 switch (tagtype) {
2255 case SMB_ACL_USER_OBJ:
2256 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2257 own_grp = (unsigned int)pst->st_uid;
2258 SIVAL(pdata,2,own_grp);
2259 SIVAL(pdata,6,0);
2260 break;
2261 case SMB_ACL_USER:
2263 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2264 if (!puid) {
2265 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2267 own_grp = (unsigned int)*puid;
2268 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2269 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2270 SIVAL(pdata,2,own_grp);
2271 SIVAL(pdata,6,0);
2272 break;
2274 case SMB_ACL_GROUP_OBJ:
2275 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2276 own_grp = (unsigned int)pst->st_gid;
2277 SIVAL(pdata,2,own_grp);
2278 SIVAL(pdata,6,0);
2279 break;
2280 case SMB_ACL_GROUP:
2282 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2283 if (!pgid) {
2284 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2286 own_grp = (unsigned int)*pgid;
2287 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2288 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2289 SIVAL(pdata,2,own_grp);
2290 SIVAL(pdata,6,0);
2291 break;
2293 case SMB_ACL_MASK:
2294 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2295 SIVAL(pdata,2,0xFFFFFFFF);
2296 SIVAL(pdata,6,0xFFFFFFFF);
2297 break;
2298 case SMB_ACL_OTHER:
2299 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2300 SIVAL(pdata,2,0xFFFFFFFF);
2301 SIVAL(pdata,6,0xFFFFFFFF);
2302 break;
2303 default:
2304 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2305 return False;
2307 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2310 return True;
2312 #endif
2314 /****************************************************************************
2315 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2316 file name or file id).
2317 ****************************************************************************/
2319 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2320 char **pparams, int total_params, char **ppdata, int total_data,
2321 unsigned int max_data_bytes)
2323 char *params = *pparams;
2324 char *pdata = *ppdata;
2325 uint16 tran_call = SVAL(inbuf, smb_setup0);
2326 uint16 info_level;
2327 int mode=0;
2328 SMB_OFF_T file_size=0;
2329 SMB_BIG_UINT allocation_size=0;
2330 unsigned int data_size;
2331 unsigned int param_size = 2;
2332 SMB_STRUCT_STAT sbuf;
2333 pstring fname, dos_fname;
2334 char *fullpathname;
2335 char *base_name;
2336 char *p;
2337 SMB_OFF_T pos = 0;
2338 BOOL bad_path = False;
2339 BOOL delete_pending = False;
2340 int len;
2341 time_t c_time;
2342 files_struct *fsp = NULL;
2343 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2345 if (!params)
2346 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2348 ZERO_STRUCT(sbuf);
2350 if (tran_call == TRANSACT2_QFILEINFO) {
2351 if (total_params < 4)
2352 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2354 fsp = file_fsp(params,0);
2355 info_level = SVAL(params,2);
2357 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2359 if(fsp && (fsp->fake_file_handle)) {
2361 * This is actually for the QUOTA_FAKE_FILE --metze
2364 pstrcpy(fname, fsp->fsp_name);
2365 /* We know this name is ok, it's already passed the checks. */
2367 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2369 * This is actually a QFILEINFO on a directory
2370 * handle (returned from an NT SMB). NT5.0 seems
2371 * to do this call. JRA.
2373 /* We know this name is ok, it's already passed the checks. */
2374 pstrcpy(fname, fsp->fsp_name);
2376 if (INFO_LEVEL_IS_UNIX(info_level)) {
2377 /* Always do lstat for UNIX calls. */
2378 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2379 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2380 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2382 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2383 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2384 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2387 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2388 } else {
2390 * Original code - this is an open file.
2392 CHECK_FSP(fsp,conn);
2394 pstrcpy(fname, fsp->fsp_name);
2395 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2396 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2397 return(UNIXERROR(ERRDOS,ERRbadfid));
2399 pos = fsp->position_information;
2400 delete_pending = fsp->delete_on_close;
2401 desired_access = fsp->desired_access;
2403 } else {
2404 NTSTATUS status = NT_STATUS_OK;
2406 /* qpathinfo */
2407 if (total_params < 6)
2408 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2410 info_level = SVAL(params,0);
2412 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2414 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2415 if (!NT_STATUS_IS_OK(status)) {
2416 return ERROR_NT(status);
2419 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2421 unix_convert(fname,conn,0,&bad_path,&sbuf);
2422 if (bad_path) {
2423 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2425 if (!check_name(fname,conn)) {
2426 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2427 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2430 if (INFO_LEVEL_IS_UNIX(info_level)) {
2431 /* Always do lstat for UNIX calls. */
2432 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2433 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2434 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2436 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2437 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2438 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2442 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2443 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2445 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2446 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2448 p = strrchr_m(fname,'/');
2449 if (!p)
2450 base_name = fname;
2451 else
2452 base_name = p+1;
2454 mode = dos_mode(conn,fname,&sbuf);
2455 if (!mode)
2456 mode = FILE_ATTRIBUTE_NORMAL;
2458 fullpathname = fname;
2459 file_size = get_file_size(sbuf);
2460 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2461 if (mode & aDIR) {
2462 /* This is necessary, as otherwise the desktop.ini file in
2463 * this folder is ignored */
2464 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2465 file_size = 0;
2468 params = SMB_REALLOC(*pparams,2);
2469 if (params == NULL)
2470 return ERROR_DOS(ERRDOS,ERRnomem);
2471 *pparams = params;
2472 memset((char *)params,'\0',2);
2473 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2474 pdata = SMB_REALLOC(*ppdata, data_size);
2475 if ( pdata == NULL )
2476 return ERROR_DOS(ERRDOS,ERRnomem);
2477 *ppdata = pdata;
2479 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2480 /* uggh, EAs for OS2 */
2481 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2482 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2485 memset((char *)pdata,'\0',data_size);
2487 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2489 if (fsp) {
2490 if (fsp->pending_modtime) {
2491 /* the pending modtime overrides the current modtime */
2492 sbuf.st_mtime = fsp->pending_modtime;
2494 } else {
2495 /* Do we have this path open ? */
2496 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2497 if (fsp1 && fsp1->pending_modtime) {
2498 /* the pending modtime overrides the current modtime */
2499 sbuf.st_mtime = fsp1->pending_modtime;
2503 if (lp_dos_filetime_resolution(SNUM(conn))) {
2504 c_time &= ~1;
2505 sbuf.st_atime &= ~1;
2506 sbuf.st_ctime &= ~1;
2507 sbuf.st_mtime &= ~1;
2510 /* NT expects the name to be in an exact form of the *full*
2511 filename. See the trans2 torture test */
2512 if (strequal(base_name,".")) {
2513 pstrcpy(dos_fname, "\\");
2514 } else {
2515 pstr_sprintf(dos_fname, "\\%s", fname);
2516 string_replace(dos_fname, '/', '\\');
2519 switch (info_level) {
2520 case SMB_INFO_STANDARD:
2521 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2522 data_size = 22;
2523 put_dos_date2(pdata,l1_fdateCreation,c_time);
2524 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2525 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2526 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2527 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2528 SSVAL(pdata,l1_attrFile,mode);
2529 break;
2531 case SMB_INFO_QUERY_EA_SIZE:
2533 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2534 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2535 data_size = 26;
2536 put_dos_date2(pdata,l1_fdateCreation,c_time);
2537 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2538 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2539 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2540 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2541 SSVAL(pdata,l1_attrFile,mode);
2542 SIVAL(pdata,l1_attrFile+2,ea_size);
2543 break;
2546 case SMB_INFO_IS_NAME_VALID:
2547 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2548 if (tran_call == TRANSACT2_QFILEINFO) {
2549 /* os/2 needs this ? really ?*/
2550 return ERROR_DOS(ERRDOS,ERRbadfunc);
2552 data_size = 0;
2553 param_size = 0;
2554 break;
2556 case SMB_INFO_QUERY_EAS_FROM_LIST:
2557 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2558 data_size = 24;
2559 put_dos_date2(pdata,0,c_time);
2560 put_dos_date2(pdata,4,sbuf.st_atime);
2561 put_dos_date2(pdata,8,sbuf.st_mtime);
2562 SIVAL(pdata,12,(uint32)file_size);
2563 SIVAL(pdata,16,(uint32)allocation_size);
2564 SIVAL(pdata,20,mode);
2565 break;
2567 case SMB_INFO_QUERY_ALL_EAS:
2568 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2569 /* We have data_size bytes to put EA's into. */
2570 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2571 break;
2573 case SMB_FILE_BASIC_INFORMATION:
2574 case SMB_QUERY_FILE_BASIC_INFO:
2576 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2577 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2578 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2579 } else {
2580 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2581 data_size = 40;
2582 SIVAL(pdata,36,0);
2584 put_long_date(pdata,c_time);
2585 put_long_date(pdata+8,sbuf.st_atime);
2586 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2587 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2588 SIVAL(pdata,32,mode);
2590 DEBUG(5,("SMB_QFBI - "));
2592 time_t create_time = c_time;
2593 DEBUG(5,("create: %s ", ctime(&create_time)));
2595 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2596 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2597 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2598 DEBUG(5,("mode: %x\n", mode));
2600 break;
2602 case SMB_FILE_STANDARD_INFORMATION:
2603 case SMB_QUERY_FILE_STANDARD_INFO:
2605 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2606 data_size = 24;
2607 SOFF_T(pdata,0,allocation_size);
2608 SOFF_T(pdata,8,file_size);
2609 if (delete_pending & sbuf.st_nlink)
2610 SIVAL(pdata,16,sbuf.st_nlink - 1);
2611 else
2612 SIVAL(pdata,16,sbuf.st_nlink);
2613 SCVAL(pdata,20,0);
2614 SCVAL(pdata,21,(mode&aDIR)?1:0);
2615 break;
2617 case SMB_FILE_EA_INFORMATION:
2618 case SMB_QUERY_FILE_EA_INFO:
2620 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2621 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2622 data_size = 4;
2623 SIVAL(pdata,0,ea_size);
2624 break;
2627 /* Get the 8.3 name - used if NT SMB was negotiated. */
2628 case SMB_QUERY_FILE_ALT_NAME_INFO:
2629 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2631 pstring short_name;
2633 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2634 pstrcpy(short_name,base_name);
2635 /* Mangle if not already 8.3 */
2636 if(!mangle_is_8_3(short_name, True)) {
2637 mangle_map(short_name,True,True,SNUM(conn));
2639 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2640 data_size = 4 + len;
2641 SIVAL(pdata,0,len);
2642 break;
2645 case SMB_QUERY_FILE_NAME_INFO:
2647 this must be *exactly* right for ACLs on mapped drives to work
2649 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2650 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2651 data_size = 4 + len;
2652 SIVAL(pdata,0,len);
2653 break;
2655 case SMB_FILE_ALLOCATION_INFORMATION:
2656 case SMB_QUERY_FILE_ALLOCATION_INFO:
2657 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2658 data_size = 8;
2659 SOFF_T(pdata,0,allocation_size);
2660 break;
2662 case SMB_FILE_END_OF_FILE_INFORMATION:
2663 case SMB_QUERY_FILE_END_OF_FILEINFO:
2664 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2665 data_size = 8;
2666 SOFF_T(pdata,0,file_size);
2667 break;
2669 case SMB_QUERY_FILE_ALL_INFO:
2670 case SMB_FILE_ALL_INFORMATION:
2672 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2673 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2674 put_long_date(pdata,c_time);
2675 put_long_date(pdata+8,sbuf.st_atime);
2676 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2677 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2678 SIVAL(pdata,32,mode);
2679 pdata += 40;
2680 SOFF_T(pdata,0,allocation_size);
2681 SOFF_T(pdata,8,file_size);
2682 if (delete_pending && sbuf.st_nlink)
2683 SIVAL(pdata,16,sbuf.st_nlink - 1);
2684 else
2685 SIVAL(pdata,16,sbuf.st_nlink);
2686 SCVAL(pdata,20,delete_pending);
2687 SCVAL(pdata,21,(mode&aDIR)?1:0);
2688 pdata += 24;
2689 SIVAL(pdata,0,ea_size);
2690 pdata += 4; /* EA info */
2691 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2692 SIVAL(pdata,0,len);
2693 pdata += 4 + len;
2694 data_size = PTR_DIFF(pdata,(*ppdata));
2695 break;
2697 case SMB_FILE_INTERNAL_INFORMATION:
2698 /* This should be an index number - looks like
2699 dev/ino to me :-)
2701 I think this causes us to fail the IFSKIT
2702 BasicFileInformationTest. -tpot */
2704 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2705 SIVAL(pdata,0,sbuf.st_dev);
2706 SIVAL(pdata,4,sbuf.st_ino);
2707 data_size = 8;
2708 break;
2710 case SMB_FILE_ACCESS_INFORMATION:
2711 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2712 SIVAL(pdata,0,desired_access);
2713 data_size = 4;
2714 break;
2716 case SMB_FILE_NAME_INFORMATION:
2717 /* Pathname with leading '\'. */
2719 size_t byte_len;
2720 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2721 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2722 SIVAL(pdata,0,byte_len);
2723 data_size = 4 + byte_len;
2724 break;
2727 case SMB_FILE_DISPOSITION_INFORMATION:
2728 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2729 data_size = 1;
2730 SCVAL(pdata,0,delete_pending);
2731 break;
2733 case SMB_FILE_POSITION_INFORMATION:
2734 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2735 data_size = 8;
2736 SOFF_T(pdata,0,pos);
2737 break;
2739 case SMB_FILE_MODE_INFORMATION:
2740 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2741 SIVAL(pdata,0,mode);
2742 data_size = 4;
2743 break;
2745 case SMB_FILE_ALIGNMENT_INFORMATION:
2746 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2747 SIVAL(pdata,0,0); /* No alignment needed. */
2748 data_size = 4;
2749 break;
2751 #if 0
2753 * NT4 server just returns "invalid query" to this - if we try to answer
2754 * it then NTws gets a BSOD! (tridge).
2755 * W2K seems to want this. JRA.
2757 case SMB_QUERY_FILE_STREAM_INFO:
2758 #endif
2759 case SMB_FILE_STREAM_INFORMATION:
2760 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2761 if (mode & aDIR) {
2762 data_size = 0;
2763 } else {
2764 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2765 SIVAL(pdata,0,0); /* ??? */
2766 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2767 SOFF_T(pdata,8,file_size);
2768 SIVAL(pdata,16,allocation_size);
2769 SIVAL(pdata,20,0); /* ??? */
2770 data_size = 24 + byte_len;
2772 break;
2774 case SMB_QUERY_COMPRESSION_INFO:
2775 case SMB_FILE_COMPRESSION_INFORMATION:
2776 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2777 SOFF_T(pdata,0,file_size);
2778 SIVAL(pdata,8,0); /* ??? */
2779 SIVAL(pdata,12,0); /* ??? */
2780 data_size = 16;
2781 break;
2783 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2784 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2785 put_long_date(pdata,c_time);
2786 put_long_date(pdata+8,sbuf.st_atime);
2787 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2788 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2789 SIVAL(pdata,32,allocation_size);
2790 SOFF_T(pdata,40,file_size);
2791 SIVAL(pdata,48,mode);
2792 SIVAL(pdata,52,0); /* ??? */
2793 data_size = 56;
2794 break;
2796 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2797 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2798 SIVAL(pdata,0,mode);
2799 SIVAL(pdata,4,0);
2800 data_size = 8;
2801 break;
2804 * CIFS UNIX Extensions.
2807 case SMB_QUERY_FILE_UNIX_BASIC:
2809 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2810 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2812 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2813 pdata += 8;
2815 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2816 pdata += 8;
2818 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2819 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2820 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2821 pdata += 24;
2823 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2824 SIVAL(pdata,4,0);
2825 pdata += 8;
2827 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2828 SIVAL(pdata,4,0);
2829 pdata += 8;
2831 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2832 pdata += 4;
2834 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2835 SIVAL(pdata,4,0);
2836 pdata += 8;
2838 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2839 SIVAL(pdata,4,0);
2840 pdata += 8;
2842 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2843 pdata += 8;
2845 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2846 SIVAL(pdata,4,0);
2847 pdata += 8;
2849 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2850 SIVAL(pdata,4,0);
2851 pdata += 8+1;
2852 data_size = PTR_DIFF(pdata,(*ppdata));
2855 int i;
2856 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2858 for (i=0; i<100; i++)
2859 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2860 DEBUG(4,("\n"));
2863 break;
2865 case SMB_QUERY_FILE_UNIX_LINK:
2867 pstring buffer;
2869 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2870 #ifdef S_ISLNK
2871 if(!S_ISLNK(sbuf.st_mode))
2872 return(UNIXERROR(ERRSRV,ERRbadlink));
2873 #else
2874 return(UNIXERROR(ERRDOS,ERRbadlink));
2875 #endif
2876 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2877 if (len == -1)
2878 return(UNIXERROR(ERRDOS,ERRnoaccess));
2879 buffer[len] = 0;
2880 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2881 pdata += len;
2882 data_size = PTR_DIFF(pdata,(*ppdata));
2884 break;
2887 #if defined(HAVE_POSIX_ACLS)
2888 case SMB_QUERY_POSIX_ACL:
2890 SMB_ACL_T file_acl = NULL;
2891 SMB_ACL_T def_acl = NULL;
2892 uint16 num_file_acls = 0;
2893 uint16 num_def_acls = 0;
2895 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2896 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2897 } else {
2898 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2901 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2902 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2903 fname ));
2904 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2907 if (S_ISDIR(sbuf.st_mode)) {
2908 if (fsp && fsp->is_directory) {
2909 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2910 } else {
2911 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2913 def_acl = free_empty_sys_acl(conn, def_acl);
2916 num_file_acls = count_acl_entries(conn, file_acl);
2917 num_def_acls = count_acl_entries(conn, def_acl);
2919 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2920 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2921 data_size,
2922 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2923 SMB_POSIX_ACL_HEADER_SIZE) ));
2924 if (file_acl) {
2925 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2927 if (def_acl) {
2928 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2930 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2933 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2934 SSVAL(pdata,2,num_file_acls);
2935 SSVAL(pdata,4,num_def_acls);
2936 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2937 if (file_acl) {
2938 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2940 if (def_acl) {
2941 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2943 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2945 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2946 if (file_acl) {
2947 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2949 if (def_acl) {
2950 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2952 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2955 if (file_acl) {
2956 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2958 if (def_acl) {
2959 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2961 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
2962 break;
2964 #endif
2966 default:
2967 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2970 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2972 return(-1);
2975 /****************************************************************************
2976 Deal with the internal needs of setting the delete on close flag. Note that
2977 as the tdb locking is recursive, it is safe to call this from within
2978 open_file_shared. JRA.
2979 ****************************************************************************/
2981 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
2983 if (delete_on_close) {
2985 * Only allow delete on close for writable files.
2988 if (!lp_delete_readonly(SNUM(fsp->conn))) {
2989 if (dosmode & aRONLY) {
2990 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
2991 fsp->fsp_name ));
2992 return NT_STATUS_CANNOT_DELETE;
2997 * Only allow delete on close for writable shares.
3000 if (!CAN_WRITE(fsp->conn)) {
3001 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3002 fsp->fsp_name ));
3003 return NT_STATUS_ACCESS_DENIED;
3007 * Only allow delete on close for files/directories opened with delete intent.
3010 if (!(fsp->desired_access & DELETE_ACCESS)) {
3011 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3012 fsp->fsp_name ));
3013 return NT_STATUS_ACCESS_DENIED;
3017 if(fsp->is_directory) {
3018 fsp->directory_delete_on_close = delete_on_close;
3019 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3020 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3021 } else {
3022 fsp->delete_on_close = delete_on_close;
3023 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3024 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3027 return NT_STATUS_OK;
3030 /****************************************************************************
3031 Sets the delete on close flag over all share modes on this file.
3032 Modify the share mode entry for all files open
3033 on this device and inode to tell other smbds we have
3034 changed the delete on close flag. This will be noticed
3035 in the close code, the last closer will delete the file
3036 if flag is set.
3037 ****************************************************************************/
3039 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3041 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3042 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3044 if (fsp->is_directory || fsp->is_stat)
3045 return NT_STATUS_OK;
3047 if (lock_share_entry_fsp(fsp) == False)
3048 return NT_STATUS_ACCESS_DENIED;
3050 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3051 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3052 fsp->fsp_name ));
3053 unlock_share_entry_fsp(fsp);
3054 return NT_STATUS_ACCESS_DENIED;
3057 unlock_share_entry_fsp(fsp);
3058 return NT_STATUS_OK;
3061 /****************************************************************************
3062 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3063 code.
3064 ****************************************************************************/
3066 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3068 BOOL bad_path_oldname = False;
3069 BOOL bad_path_newname = False;
3070 SMB_STRUCT_STAT sbuf1, sbuf2;
3071 pstring last_component_oldname;
3072 pstring last_component_newname;
3073 NTSTATUS status = NT_STATUS_OK;
3075 ZERO_STRUCT(sbuf1);
3076 ZERO_STRUCT(sbuf2);
3078 /* No wildcards. */
3079 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3080 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3083 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3084 if (bad_path_oldname) {
3085 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3088 /* Quick check for "." and ".." */
3089 if (last_component_oldname[0] == '.') {
3090 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3091 return NT_STATUS_OBJECT_NAME_INVALID;
3095 /* source must already exist. */
3096 if (!VALID_STAT(sbuf1)) {
3097 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3100 if (!check_name(oldname,conn)) {
3101 return NT_STATUS_ACCESS_DENIED;
3104 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3105 if (bad_path_newname) {
3106 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3109 /* Quick check for "." and ".." */
3110 if (last_component_newname[0] == '.') {
3111 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3112 return NT_STATUS_OBJECT_NAME_INVALID;
3116 /* Disallow if newname already exists. */
3117 if (VALID_STAT(sbuf2)) {
3118 return NT_STATUS_OBJECT_NAME_COLLISION;
3121 if (!check_name(newname,conn)) {
3122 return NT_STATUS_ACCESS_DENIED;
3125 /* No links from a directory. */
3126 if (S_ISDIR(sbuf1.st_mode)) {
3127 return NT_STATUS_FILE_IS_A_DIRECTORY;
3130 /* Ensure this is within the share. */
3131 if (!reduce_name(conn, oldname) != 0)
3132 return NT_STATUS_ACCESS_DENIED;
3134 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3136 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3137 status = map_nt_error_from_unix(errno);
3138 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3139 nt_errstr(status), newname, oldname));
3142 return status;
3145 /****************************************************************************
3146 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3147 ****************************************************************************/
3149 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3150 char **pparams, int total_params, char **ppdata, int total_data,
3151 unsigned int max_data_bytes)
3153 char *params = *pparams;
3154 char *pdata = *ppdata;
3155 uint16 tran_call = SVAL(inbuf, smb_setup0);
3156 uint16 info_level;
3157 int dosmode=0;
3158 SMB_OFF_T size=0;
3159 struct utimbuf tvs;
3160 SMB_STRUCT_STAT sbuf;
3161 pstring fname;
3162 int fd = -1;
3163 BOOL bad_path = False;
3164 files_struct *fsp = NULL;
3165 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3166 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3167 mode_t unixmode = 0;
3168 NTSTATUS status = NT_STATUS_OK;
3170 if (!params)
3171 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3173 ZERO_STRUCT(sbuf);
3175 if (tran_call == TRANSACT2_SETFILEINFO) {
3176 if (total_params < 4)
3177 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3179 fsp = file_fsp(params,0);
3180 info_level = SVAL(params,2);
3182 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3184 * This is actually a SETFILEINFO on a directory
3185 * handle (returned from an NT SMB). NT5.0 seems
3186 * to do this call. JRA.
3188 pstrcpy(fname, fsp->fsp_name);
3189 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3190 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3191 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3193 } else if (fsp && fsp->print_file) {
3195 * Doing a DELETE_ON_CLOSE should cancel a print job.
3197 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3198 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3200 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3202 SSVAL(params,0,0);
3203 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3204 return(-1);
3205 } else
3206 return (UNIXERROR(ERRDOS,ERRbadpath));
3207 } else {
3209 * Original code - this is an open file.
3211 CHECK_FSP(fsp,conn);
3213 pstrcpy(fname, fsp->fsp_name);
3214 fd = fsp->fd;
3216 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3217 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3218 return(UNIXERROR(ERRDOS,ERRbadfid));
3221 } else {
3222 /* set path info */
3223 if (total_params < 6)
3224 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3226 info_level = SVAL(params,0);
3227 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3228 if (!NT_STATUS_IS_OK(status)) {
3229 return ERROR_NT(status);
3231 unix_convert(fname,conn,0,&bad_path,&sbuf);
3232 if (bad_path) {
3233 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3237 * For CIFS UNIX extensions the target name may not exist.
3240 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3241 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3242 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3245 if(!check_name(fname, conn)) {
3246 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3251 if (!CAN_WRITE(conn))
3252 return ERROR_DOS(ERRSRV,ERRaccess);
3254 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3255 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3257 if (VALID_STAT(sbuf))
3258 unixmode = sbuf.st_mode;
3260 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3261 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3263 /* Realloc the parameter and data sizes */
3264 params = SMB_REALLOC(*pparams,2);
3265 if(params == NULL)
3266 return ERROR_DOS(ERRDOS,ERRnomem);
3267 *pparams = params;
3269 SSVAL(params,0,0);
3271 if (fsp && fsp->pending_modtime) {
3272 /* the pending modtime overrides the current modtime */
3273 sbuf.st_mtime = fsp->pending_modtime;
3276 size = get_file_size(sbuf);
3277 tvs.modtime = sbuf.st_mtime;
3278 tvs.actime = sbuf.st_atime;
3279 dosmode = dos_mode(conn,fname,&sbuf);
3280 unixmode = sbuf.st_mode;
3282 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3283 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3285 switch (info_level) {
3286 case SMB_INFO_STANDARD:
3288 if (total_data < 12)
3289 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3291 /* access time */
3292 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3293 /* write time */
3294 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3295 break;
3298 case SMB_INFO_SET_EA:
3299 status = set_ea(conn, fsp, fname, pdata, total_data);
3300 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3301 return ERROR_NT(status);
3302 break;
3304 /* XXXX um, i don't think this is right.
3305 it's also not in the cifs6.txt spec.
3307 case SMB_INFO_QUERY_EAS_FROM_LIST:
3308 if (total_data < 28)
3309 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3311 tvs.actime = make_unix_date2(pdata+8);
3312 tvs.modtime = make_unix_date2(pdata+12);
3313 size = IVAL(pdata,16);
3314 dosmode = IVAL(pdata,24);
3315 break;
3317 /* XXXX nor this. not in cifs6.txt, either. */
3318 case SMB_INFO_QUERY_ALL_EAS:
3319 if (total_data < 28)
3320 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3322 tvs.actime = make_unix_date2(pdata+8);
3323 tvs.modtime = make_unix_date2(pdata+12);
3324 size = IVAL(pdata,16);
3325 dosmode = IVAL(pdata,24);
3326 break;
3328 case SMB_SET_FILE_BASIC_INFO:
3329 case SMB_FILE_BASIC_INFORMATION:
3331 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3332 time_t write_time;
3333 time_t changed_time;
3335 if (total_data < 36)
3336 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3338 /* Ignore create time at offset pdata. */
3340 /* access time */
3341 tvs.actime = interpret_long_date(pdata+8);
3343 write_time = interpret_long_date(pdata+16);
3344 changed_time = interpret_long_date(pdata+24);
3346 tvs.modtime = MIN(write_time, changed_time);
3348 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3349 tvs.modtime = write_time;
3351 /* Prefer a defined time to an undefined one. */
3352 if (null_mtime(tvs.modtime)) {
3353 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3356 /* attributes */
3357 dosmode = IVAL(pdata,32);
3358 break;
3361 case SMB_FILE_ALLOCATION_INFORMATION:
3362 case SMB_SET_FILE_ALLOCATION_INFO:
3364 int ret = -1;
3365 SMB_BIG_UINT allocation_size;
3367 if (total_data < 8)
3368 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3370 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3371 #ifdef LARGE_SMB_OFF_T
3372 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3373 #else /* LARGE_SMB_OFF_T */
3374 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3375 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3376 #endif /* LARGE_SMB_OFF_T */
3377 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3378 fname, (double)allocation_size ));
3380 if (allocation_size) {
3381 allocation_size = smb_roundup(conn, allocation_size);
3384 if(allocation_size != get_file_size(sbuf)) {
3385 SMB_STRUCT_STAT new_sbuf;
3387 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3388 fname, (double)allocation_size ));
3390 if (fd == -1) {
3391 files_struct *new_fsp = NULL;
3392 int access_mode = 0;
3393 int action = 0;
3395 if(global_oplock_break) {
3396 /* Queue this file modify as we are the process of an oplock break. */
3398 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3399 DEBUGADD(2,( "in oplock break state.\n"));
3401 push_oplock_pending_smb_message(inbuf, length);
3402 return -1;
3405 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3406 SET_OPEN_MODE(DOS_OPEN_RDWR),
3407 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3408 FILE_ATTRIBUTE_NORMAL,
3409 INTERNAL_OPEN_ONLY, &access_mode, &action);
3411 if (new_fsp == NULL)
3412 return(UNIXERROR(ERRDOS,ERRbadpath));
3413 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3414 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3415 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3416 new_fsp->fnum, strerror(errno)));
3417 ret = -1;
3419 close_file(new_fsp,True);
3420 } else {
3421 ret = vfs_allocate_file_space(fsp, allocation_size);
3422 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3423 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3424 fsp->fnum, strerror(errno)));
3425 ret = -1;
3428 if (ret == -1)
3429 return ERROR_NT(NT_STATUS_DISK_FULL);
3431 /* Allocate can truncate size... */
3432 size = get_file_size(new_sbuf);
3435 break;
3438 case SMB_FILE_END_OF_FILE_INFORMATION:
3439 case SMB_SET_FILE_END_OF_FILE_INFO:
3441 if (total_data < 8)
3442 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3444 size = IVAL(pdata,0);
3445 #ifdef LARGE_SMB_OFF_T
3446 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3447 #else /* LARGE_SMB_OFF_T */
3448 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3449 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3450 #endif /* LARGE_SMB_OFF_T */
3451 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3452 break;
3455 case SMB_FILE_DISPOSITION_INFORMATION:
3456 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3458 BOOL delete_on_close;
3460 if (total_data < 1)
3461 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3463 delete_on_close = (CVAL(pdata,0) ? True : False);
3465 /* Just ignore this set on a path. */
3466 if (tran_call != TRANSACT2_SETFILEINFO)
3467 break;
3469 if (fsp == NULL)
3470 return(UNIXERROR(ERRDOS,ERRbadfid));
3472 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3474 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3475 return ERROR_NT(status);
3477 /* The set is across all open files on this dev/inode pair. */
3478 status =set_delete_on_close_over_all(fsp, delete_on_close);
3479 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3480 return ERROR_NT(status);
3482 break;
3485 case SMB_FILE_POSITION_INFORMATION:
3487 SMB_BIG_UINT position_information;
3489 if (total_data < 8)
3490 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3492 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3493 #ifdef LARGE_SMB_OFF_T
3494 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3495 #else /* LARGE_SMB_OFF_T */
3496 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3497 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3498 #endif /* LARGE_SMB_OFF_T */
3499 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3500 fname, (double)position_information ));
3501 if (fsp)
3502 fsp->position_information = position_information;
3503 break;
3507 * CIFS UNIX extensions.
3510 case SMB_SET_FILE_UNIX_BASIC:
3512 uint32 raw_unixmode;
3514 if (total_data < 100)
3515 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3517 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3518 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3519 size=IVAL(pdata,0); /* first 8 Bytes are size */
3520 #ifdef LARGE_SMB_OFF_T
3521 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3522 #else /* LARGE_SMB_OFF_T */
3523 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3524 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3525 #endif /* LARGE_SMB_OFF_T */
3527 pdata+=24; /* ctime & st_blocks are not changed */
3528 tvs.actime = interpret_long_date(pdata); /* access_time */
3529 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3530 pdata+=16;
3531 set_owner = (uid_t)IVAL(pdata,0);
3532 pdata += 8;
3533 set_grp = (gid_t)IVAL(pdata,0);
3534 pdata += 8;
3535 raw_unixmode = IVAL(pdata,28);
3536 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3537 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3539 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3540 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3541 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3543 if (!VALID_STAT(sbuf)) {
3546 * The only valid use of this is to create character and block
3547 * devices, and named pipes. This is deprecated (IMHO) and
3548 * a new info level should be used for mknod. JRA.
3551 uint32 file_type = IVAL(pdata,0);
3552 #if defined(HAVE_MAKEDEV)
3553 uint32 dev_major = IVAL(pdata,4);
3554 uint32 dev_minor = IVAL(pdata,12);
3555 #endif
3557 uid_t myuid = geteuid();
3558 gid_t mygid = getegid();
3559 SMB_DEV_T dev = (SMB_DEV_T)0;
3561 if (tran_call == TRANSACT2_SETFILEINFO)
3562 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3564 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3565 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3567 #if defined(HAVE_MAKEDEV)
3568 dev = makedev(dev_major, dev_minor);
3569 #endif
3571 /* We can only create as the owner/group we are. */
3573 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3574 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3575 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3576 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3578 switch (file_type) {
3579 #if defined(S_IFIFO)
3580 case UNIX_TYPE_FIFO:
3581 unixmode |= S_IFIFO;
3582 break;
3583 #endif
3584 #if defined(S_IFSOCK)
3585 case UNIX_TYPE_SOCKET:
3586 unixmode |= S_IFSOCK;
3587 break;
3588 #endif
3589 #if defined(S_IFCHR)
3590 case UNIX_TYPE_CHARDEV:
3591 unixmode |= S_IFCHR;
3592 break;
3593 #endif
3594 #if defined(S_IFBLK)
3595 case UNIX_TYPE_BLKDEV:
3596 unixmode |= S_IFBLK;
3597 break;
3598 #endif
3599 default:
3600 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3603 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3604 0%o for file %s\n", (double)dev, unixmode, fname ));
3606 /* Ok - do the mknod. */
3607 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3608 return(UNIXERROR(ERRDOS,ERRnoaccess));
3610 inherit_access_acl(conn, fname, unixmode);
3612 SSVAL(params,0,0);
3613 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3614 return(-1);
3618 * Deal with the UNIX specific mode set.
3621 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3622 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3623 (unsigned int)unixmode, fname ));
3624 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3625 return(UNIXERROR(ERRDOS,ERRnoaccess));
3629 * Deal with the UNIX specific uid set.
3632 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3633 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3634 (unsigned int)set_owner, fname ));
3635 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3636 return(UNIXERROR(ERRDOS,ERRnoaccess));
3640 * Deal with the UNIX specific gid set.
3643 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3644 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3645 (unsigned int)set_owner, fname ));
3646 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3647 return(UNIXERROR(ERRDOS,ERRnoaccess));
3649 break;
3652 case SMB_SET_FILE_UNIX_LINK:
3654 pstring link_target;
3655 char *newname = fname;
3657 /* Set a symbolic link. */
3658 /* Don't allow this if follow links is false. */
3660 if (!lp_symlinks(SNUM(conn)))
3661 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3663 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3665 /* !widelinks forces the target path to be within the share. */
3666 /* This means we can interpret the target as a pathname. */
3667 if (!lp_widelinks(SNUM(conn))) {
3668 pstring rel_name;
3669 char *last_dirp = NULL;
3671 unix_format(link_target);
3672 if (*link_target == '/') {
3673 /* No absolute paths allowed. */
3674 return(UNIXERROR(ERRDOS,ERRnoaccess));
3676 pstrcpy(rel_name, newname);
3677 last_dirp = strrchr_m(rel_name, '/');
3678 if (last_dirp) {
3679 last_dirp[1] = '\0';
3680 } else {
3681 pstrcpy(rel_name, "./");
3683 pstrcat(rel_name, link_target);
3685 if (!check_name(rel_name, conn)) {
3686 return(UNIXERROR(ERRDOS,ERRnoaccess));
3690 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3691 fname, link_target ));
3693 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3694 return(UNIXERROR(ERRDOS,ERRnoaccess));
3695 SSVAL(params,0,0);
3696 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3697 return(-1);
3700 case SMB_SET_FILE_UNIX_HLINK:
3702 pstring oldname;
3703 char *newname = fname;
3705 /* Set a hard link. */
3706 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3707 if (!NT_STATUS_IS_OK(status)) {
3708 return ERROR_NT(status);
3711 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3712 fname, oldname));
3714 status = hardlink_internals(conn, oldname, newname);
3715 if (!NT_STATUS_IS_OK(status)) {
3716 return ERROR_NT(status);
3719 SSVAL(params,0,0);
3720 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3721 return(-1);
3724 case SMB_FILE_RENAME_INFORMATION:
3726 BOOL overwrite;
3727 uint32 root_fid;
3728 uint32 len;
3729 pstring newname;
3730 pstring base_name;
3731 char *p;
3733 if (total_data < 12)
3734 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3736 overwrite = (CVAL(pdata,0) ? True : False);
3737 root_fid = IVAL(pdata,4);
3738 len = IVAL(pdata,8);
3739 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3740 if (!NT_STATUS_IS_OK(status)) {
3741 return ERROR_NT(status);
3744 /* Check the new name has no '/' characters. */
3745 if (strchr_m(newname, '/'))
3746 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3748 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3750 /* Create the base directory. */
3751 pstrcpy(base_name, fname);
3752 p = strrchr_m(base_name, '/');
3753 if (p)
3754 *p = '\0';
3755 /* Append the new name. */
3756 pstrcat(base_name, "/");
3757 pstrcat(base_name, newname);
3759 if (fsp) {
3760 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3761 fsp->fnum, fsp->fsp_name, base_name ));
3762 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3763 } else {
3764 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3765 fname, newname ));
3766 status = rename_internals(conn, fname, base_name, 0, overwrite);
3768 if (!NT_STATUS_IS_OK(status)) {
3769 return ERROR_NT(status);
3771 process_pending_change_notify_queue((time_t)0);
3772 SSVAL(params,0,0);
3773 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3774 return(-1);
3777 #if defined(HAVE_POSIX_ACLS)
3778 case SMB_SET_POSIX_ACL:
3780 uint16 posix_acl_version;
3781 uint16 num_file_acls;
3782 uint16 num_def_acls;
3783 BOOL valid_file_acls = True;
3784 BOOL valid_def_acls = True;
3786 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3787 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3789 posix_acl_version = SVAL(pdata,0);
3790 num_file_acls = SVAL(pdata,2);
3791 num_def_acls = SVAL(pdata,4);
3793 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3794 valid_file_acls = False;
3795 num_file_acls = 0;
3798 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3799 valid_def_acls = False;
3800 num_def_acls = 0;
3803 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3804 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3807 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3808 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3809 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3812 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3813 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3814 return(UNIXERROR(ERRDOS,ERRnoaccess));
3817 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3818 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3819 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3820 return(UNIXERROR(ERRDOS,ERRnoaccess));
3823 SSVAL(params,0,0);
3824 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3825 return(-1);
3827 #endif
3829 default:
3830 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3833 /* get some defaults (no modifications) if any info is zero or -1. */
3834 if (null_mtime(tvs.actime)) {
3835 tvs.actime = sbuf.st_atime;
3838 if (null_mtime(tvs.modtime)) {
3839 tvs.modtime = sbuf.st_mtime;
3842 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3843 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3844 DEBUG(6,("size: %.0f ", (double)size));
3846 if (dosmode) {
3847 if (S_ISDIR(sbuf.st_mode))
3848 dosmode |= aDIR;
3849 else
3850 dosmode &= ~aDIR;
3853 DEBUG(6,("dosmode: %x\n" , dosmode));
3855 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3856 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3857 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3858 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3861 * Only do this test if we are not explicitly
3862 * changing the size of a file.
3864 if (!size)
3865 size = get_file_size(sbuf);
3869 * Try and set the times, size and mode of this file -
3870 * if they are different from the current values
3873 /* check the mode isn't different, before changing it */
3874 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3876 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3878 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3879 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3880 return(UNIXERROR(ERRDOS,ERRnoaccess));
3884 /* Now the size. */
3885 if (size != get_file_size(sbuf)) {
3887 int ret;
3889 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3890 fname, (double)size ));
3892 if (fd == -1) {
3893 files_struct *new_fsp = NULL;
3894 int access_mode = 0;
3895 int action = 0;
3897 if(global_oplock_break) {
3898 /* Queue this file modify as we are the process of an oplock break. */
3900 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3901 DEBUGADD(2,( "in oplock break state.\n"));
3903 push_oplock_pending_smb_message(inbuf, length);
3904 return -1;
3907 new_fsp = open_file_shared(conn, fname, &sbuf,
3908 SET_OPEN_MODE(DOS_OPEN_RDWR),
3909 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3910 FILE_ATTRIBUTE_NORMAL,
3911 INTERNAL_OPEN_ONLY, &access_mode, &action);
3913 if (new_fsp == NULL)
3914 return(UNIXERROR(ERRDOS,ERRbadpath));
3915 ret = vfs_set_filelen(new_fsp, size);
3916 close_file(new_fsp,True);
3917 } else {
3918 ret = vfs_set_filelen(fsp, size);
3921 if (ret == -1)
3922 return (UNIXERROR(ERRHRD,ERRdiskfull));
3926 * Finally the times.
3928 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3929 if(fsp != NULL) {
3931 * This was a setfileinfo on an open file.
3932 * NT does this a lot. We also need to
3933 * set the time here, as it can be read by
3934 * FindFirst/FindNext and with the patch for bug #2045
3935 * in smbd/fileio.c it ensures that this timestamp is
3936 * kept sticky even after a write. We save the request
3937 * away and will set it on file close and after a write. JRA.
3940 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3941 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3942 fsp_set_pending_modtime(fsp, tvs.modtime);
3946 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3948 if(file_utime(conn, fname, &tvs)!=0) {
3949 return(UNIXERROR(ERRDOS,ERRnoaccess));
3953 SSVAL(params,0,0);
3954 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3956 return(-1);
3959 /****************************************************************************
3960 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3961 ****************************************************************************/
3963 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3964 char **pparams, int total_params, char **ppdata, int total_data,
3965 unsigned int max_data_bytes)
3967 char *params = *pparams;
3968 pstring directory;
3969 int ret = -1;
3970 SMB_STRUCT_STAT sbuf;
3971 BOOL bad_path = False;
3972 NTSTATUS status = NT_STATUS_OK;
3974 if (!CAN_WRITE(conn))
3975 return ERROR_DOS(ERRSRV,ERRaccess);
3977 if (total_params < 4)
3978 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3980 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3981 if (!NT_STATUS_IS_OK(status)) {
3982 return ERROR_NT(status);
3985 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3987 unix_convert(directory,conn,0,&bad_path,&sbuf);
3988 if (bad_path) {
3989 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3991 if (check_name(directory,conn))
3992 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3994 if(ret < 0) {
3995 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3996 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3999 /* Realloc the parameter and data sizes */
4000 params = SMB_REALLOC(*pparams,2);
4001 if(params == NULL)
4002 return ERROR_DOS(ERRDOS,ERRnomem);
4003 *pparams = params;
4005 SSVAL(params,0,0);
4007 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4009 return(-1);
4012 /****************************************************************************
4013 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4014 We don't actually do this - we just send a null response.
4015 ****************************************************************************/
4017 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4018 char **pparams, int total_params, char **ppdata, int total_data,
4019 unsigned int max_data_bytes)
4021 static uint16 fnf_handle = 257;
4022 char *params = *pparams;
4023 uint16 info_level;
4025 if (total_params < 6)
4026 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4028 info_level = SVAL(params,4);
4029 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4031 switch (info_level) {
4032 case 1:
4033 case 2:
4034 break;
4035 default:
4036 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4039 /* Realloc the parameter and data sizes */
4040 params = SMB_REALLOC(*pparams,6);
4041 if(params == NULL)
4042 return ERROR_DOS(ERRDOS,ERRnomem);
4043 *pparams = params;
4045 SSVAL(params,0,fnf_handle);
4046 SSVAL(params,2,0); /* No changes */
4047 SSVAL(params,4,0); /* No EA errors */
4049 fnf_handle++;
4051 if(fnf_handle == 0)
4052 fnf_handle = 257;
4054 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4056 return(-1);
4059 /****************************************************************************
4060 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4061 changes). Currently this does nothing.
4062 ****************************************************************************/
4064 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4065 char **pparams, int total_params, char **ppdata, int total_data,
4066 unsigned int max_data_bytes)
4068 char *params = *pparams;
4070 DEBUG(3,("call_trans2findnotifynext\n"));
4072 /* Realloc the parameter and data sizes */
4073 params = SMB_REALLOC(*pparams,4);
4074 if(params == NULL)
4075 return ERROR_DOS(ERRDOS,ERRnomem);
4076 *pparams = params;
4078 SSVAL(params,0,0); /* No changes */
4079 SSVAL(params,2,0); /* No EA errors */
4081 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4083 return(-1);
4086 /****************************************************************************
4087 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4088 ****************************************************************************/
4090 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4091 char **pparams, int total_params, char **ppdata, int total_data,
4092 unsigned int max_data_bytes)
4094 char *params = *pparams;
4095 pstring pathname;
4096 int reply_size = 0;
4097 int max_referral_level;
4099 DEBUG(10,("call_trans2getdfsreferral\n"));
4101 if (total_params < 2)
4102 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4104 max_referral_level = SVAL(params,0);
4106 if(!lp_host_msdfs())
4107 return ERROR_DOS(ERRDOS,ERRbadfunc);
4109 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4110 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4111 return UNIXERROR(ERRDOS,ERRbadfile);
4113 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4114 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4116 return(-1);
4119 #define LMCAT_SPL 0x53
4120 #define LMFUNC_GETJOBID 0x60
4122 /****************************************************************************
4123 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4124 ****************************************************************************/
4126 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4127 char **pparams, int total_params, char **ppdata, int total_data,
4128 unsigned int max_data_bytes)
4130 char *pdata = *ppdata;
4131 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4133 /* check for an invalid fid before proceeding */
4135 if (!fsp)
4136 return(ERROR_DOS(ERRDOS,ERRbadfid));
4138 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4139 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4140 pdata = SMB_REALLOC(*ppdata, 32);
4141 if(pdata == NULL)
4142 return ERROR_DOS(ERRDOS,ERRnomem);
4143 *ppdata = pdata;
4145 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4146 CAN ACCEPT THIS IN UNICODE. JRA. */
4148 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4149 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4150 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4151 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4152 return(-1);
4153 } else {
4154 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4155 return ERROR_DOS(ERRSRV,ERRerror);
4159 /****************************************************************************
4160 Reply to a SMBfindclose (stop trans2 directory search).
4161 ****************************************************************************/
4163 int reply_findclose(connection_struct *conn,
4164 char *inbuf,char *outbuf,int length,int bufsize)
4166 int outsize = 0;
4167 int dptr_num=SVALS(inbuf,smb_vwv0);
4168 START_PROFILE(SMBfindclose);
4170 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4172 dptr_close(&dptr_num);
4174 outsize = set_message(outbuf,0,0,True);
4176 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4178 END_PROFILE(SMBfindclose);
4179 return(outsize);
4182 /****************************************************************************
4183 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4184 ****************************************************************************/
4186 int reply_findnclose(connection_struct *conn,
4187 char *inbuf,char *outbuf,int length,int bufsize)
4189 int outsize = 0;
4190 int dptr_num= -1;
4191 START_PROFILE(SMBfindnclose);
4193 dptr_num = SVAL(inbuf,smb_vwv0);
4195 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4197 /* We never give out valid handles for a
4198 findnotifyfirst - so any dptr_num is ok here.
4199 Just ignore it. */
4201 outsize = set_message(outbuf,0,0,True);
4203 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4205 END_PROFILE(SMBfindnclose);
4206 return(outsize);
4209 /****************************************************************************
4210 Reply to a SMBtranss2 - just ignore it!
4211 ****************************************************************************/
4213 int reply_transs2(connection_struct *conn,
4214 char *inbuf,char *outbuf,int length,int bufsize)
4216 START_PROFILE(SMBtranss2);
4217 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4218 END_PROFILE(SMBtranss2);
4219 return(-1);
4222 /****************************************************************************
4223 Reply to a SMBtrans2.
4224 ****************************************************************************/
4226 int reply_trans2(connection_struct *conn,
4227 char *inbuf,char *outbuf,int length,int bufsize)
4229 int outsize = 0;
4230 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4231 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4232 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4233 #if 0
4234 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4235 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4236 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4237 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4238 int32 timeout = IVALS(inbuf,smb_timeout);
4239 #endif
4240 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4241 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4242 char *params = NULL, *data = NULL;
4243 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4244 START_PROFILE(SMBtrans2);
4246 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4247 /* Queue this open message as we are the process of an
4248 * oplock break. */
4250 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4251 DEBUGADD(2,( "in oplock break state.\n"));
4253 push_oplock_pending_smb_message(inbuf, length);
4254 END_PROFILE(SMBtrans2);
4255 return -1;
4258 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4259 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4260 END_PROFILE(SMBtrans2);
4261 return ERROR_DOS(ERRSRV,ERRaccess);
4264 outsize = set_message(outbuf,0,0,True);
4266 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4267 is so as a sanity check */
4268 if (suwcnt != 1) {
4270 * Need to have rc=0 for ioctl to get job id for OS/2.
4271 * Network printing will fail if function is not successful.
4272 * Similar function in reply.c will be used if protocol
4273 * is LANMAN1.0 instead of LM1.2X002.
4274 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4275 * outbuf doesn't have to be set(only job id is used).
4277 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4278 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4279 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4280 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4281 } else {
4282 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4283 DEBUG(2,("Transaction is %d\n",tran_call));
4284 END_PROFILE(SMBtrans2);
4285 ERROR_DOS(ERRDOS,ERRinvalidparam);
4289 /* Allocate the space for the maximum needed parameters and data */
4290 if (total_params > 0)
4291 params = (char *)SMB_MALLOC(total_params);
4292 if (total_data > 0)
4293 data = (char *)SMB_MALLOC(total_data);
4295 if ((total_params && !params) || (total_data && !data)) {
4296 DEBUG(2,("Out of memory in reply_trans2\n"));
4297 SAFE_FREE(params);
4298 SAFE_FREE(data);
4299 END_PROFILE(SMBtrans2);
4300 return ERROR_DOS(ERRDOS,ERRnomem);
4303 /* Copy the param and data bytes sent with this request into
4304 the params buffer */
4305 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4306 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4308 if (num_params > total_params || num_data > total_data)
4309 exit_server("invalid params in reply_trans2");
4311 if(params) {
4312 unsigned int psoff = SVAL(inbuf, smb_psoff);
4313 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4314 goto bad_param;
4315 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4316 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4317 goto bad_param;
4318 memcpy( params, smb_base(inbuf) + psoff, num_params);
4320 if(data) {
4321 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4322 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4323 goto bad_param;
4324 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4325 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4326 goto bad_param;
4327 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4330 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4332 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4333 /* We need to send an interim response then receive the rest
4334 of the parameter/data bytes */
4335 outsize = set_message(outbuf,0,0,True);
4336 srv_signing_trans_stop();
4337 if (!send_smb(smbd_server_fd(),outbuf))
4338 exit_server("reply_trans2: send_smb failed.");
4340 while (num_data_sofar < total_data ||
4341 num_params_sofar < total_params) {
4342 BOOL ret;
4343 unsigned int param_disp;
4344 unsigned int param_off;
4345 unsigned int data_disp;
4346 unsigned int data_off;
4348 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4351 * The sequence number for the trans reply is always
4352 * based on the last secondary received.
4355 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4357 if ((ret &&
4358 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4359 outsize = set_message(outbuf,0,0,True);
4360 if(ret)
4361 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4362 else
4363 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4364 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4365 goto bad_param;
4368 /* Revise total_params and total_data in case
4369 they have changed downwards */
4370 if (SVAL(inbuf, smb_tpscnt) < total_params)
4371 total_params = SVAL(inbuf, smb_tpscnt);
4372 if (SVAL(inbuf, smb_tdscnt) < total_data)
4373 total_data = SVAL(inbuf, smb_tdscnt);
4375 num_params = SVAL(inbuf,smb_spscnt);
4376 param_off = SVAL(inbuf, smb_spsoff);
4377 param_disp = SVAL(inbuf, smb_spsdisp);
4378 num_params_sofar += num_params;
4380 num_data = SVAL(inbuf, smb_sdscnt);
4381 data_off = SVAL(inbuf, smb_sdsoff);
4382 data_disp = SVAL(inbuf, smb_sdsdisp);
4383 num_data_sofar += num_data;
4385 if (num_params_sofar > total_params || num_data_sofar > total_data)
4386 goto bad_param;
4388 if (num_params) {
4389 if (param_disp + num_params > total_params)
4390 goto bad_param;
4391 if ((param_disp + num_params < param_disp) ||
4392 (param_disp + num_params < num_params))
4393 goto bad_param;
4394 if (param_disp > total_params)
4395 goto bad_param;
4396 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4397 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4398 goto bad_param;
4399 if (params + param_disp < params)
4400 goto bad_param;
4402 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4404 if (num_data) {
4405 if (data_disp + num_data > total_data)
4406 goto bad_param;
4407 if ((data_disp + num_data < data_disp) ||
4408 (data_disp + num_data < num_data))
4409 goto bad_param;
4410 if (data_disp > total_data)
4411 goto bad_param;
4412 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4413 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4414 goto bad_param;
4415 if (data + data_disp < data)
4416 goto bad_param;
4418 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4423 if (Protocol >= PROTOCOL_NT1) {
4424 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4427 /* Now we must call the relevant TRANS2 function */
4428 switch(tran_call) {
4429 case TRANSACT2_OPEN:
4430 START_PROFILE_NESTED(Trans2_open);
4431 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4432 &params, total_params, &data, total_data, max_data_bytes);
4433 END_PROFILE_NESTED(Trans2_open);
4434 break;
4436 case TRANSACT2_FINDFIRST:
4437 START_PROFILE_NESTED(Trans2_findfirst);
4438 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4439 &params, total_params, &data, total_data, max_data_bytes);
4440 END_PROFILE_NESTED(Trans2_findfirst);
4441 break;
4443 case TRANSACT2_FINDNEXT:
4444 START_PROFILE_NESTED(Trans2_findnext);
4445 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4446 &params, total_params, &data, total_data, max_data_bytes);
4447 END_PROFILE_NESTED(Trans2_findnext);
4448 break;
4450 case TRANSACT2_QFSINFO:
4451 START_PROFILE_NESTED(Trans2_qfsinfo);
4452 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4453 &params, total_params, &data, total_data, max_data_bytes);
4454 END_PROFILE_NESTED(Trans2_qfsinfo);
4455 break;
4457 #ifdef HAVE_SYS_QUOTAS
4458 case TRANSACT2_SETFSINFO:
4459 START_PROFILE_NESTED(Trans2_setfsinfo);
4460 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4461 &params, total_params, &data, total_data, max_data_bytes);
4462 END_PROFILE_NESTED(Trans2_setfsinfo);
4463 break;
4464 #endif
4465 case TRANSACT2_QPATHINFO:
4466 case TRANSACT2_QFILEINFO:
4467 START_PROFILE_NESTED(Trans2_qpathinfo);
4468 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4469 &params, total_params, &data, total_data, max_data_bytes);
4470 END_PROFILE_NESTED(Trans2_qpathinfo);
4471 break;
4472 case TRANSACT2_SETPATHINFO:
4473 case TRANSACT2_SETFILEINFO:
4474 START_PROFILE_NESTED(Trans2_setpathinfo);
4475 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4476 &params, total_params, &data, total_data, max_data_bytes);
4477 END_PROFILE_NESTED(Trans2_setpathinfo);
4478 break;
4480 case TRANSACT2_FINDNOTIFYFIRST:
4481 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4482 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4483 &params, total_params, &data, total_data, max_data_bytes);
4484 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4485 break;
4487 case TRANSACT2_FINDNOTIFYNEXT:
4488 START_PROFILE_NESTED(Trans2_findnotifynext);
4489 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4490 &params, total_params, &data, total_data, max_data_bytes);
4491 END_PROFILE_NESTED(Trans2_findnotifynext);
4492 break;
4493 case TRANSACT2_MKDIR:
4494 START_PROFILE_NESTED(Trans2_mkdir);
4495 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4496 &params, total_params, &data, total_data, max_data_bytes);
4497 END_PROFILE_NESTED(Trans2_mkdir);
4498 break;
4500 case TRANSACT2_GET_DFS_REFERRAL:
4501 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4502 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4503 &params, total_params, &data, total_data, max_data_bytes);
4504 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4505 break;
4506 case TRANSACT2_IOCTL:
4507 START_PROFILE_NESTED(Trans2_ioctl);
4508 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4509 &params, total_params, &data, total_data, max_data_bytes);
4510 END_PROFILE_NESTED(Trans2_ioctl);
4511 break;
4512 default:
4513 /* Error in request */
4514 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4515 SAFE_FREE(params);
4516 SAFE_FREE(data);
4517 END_PROFILE(SMBtrans2);
4518 srv_signing_trans_stop();
4519 return ERROR_DOS(ERRSRV,ERRerror);
4522 /* As we do not know how many data packets will need to be
4523 returned here the various call_trans2xxxx calls
4524 must send their own. Thus a call_trans2xxx routine only
4525 returns a value other than -1 when it wants to send
4526 an error packet.
4529 srv_signing_trans_stop();
4531 SAFE_FREE(params);
4532 SAFE_FREE(data);
4533 END_PROFILE(SMBtrans2);
4534 return outsize; /* If a correct response was needed the
4535 call_trans2xxx calls have already sent
4536 it. If outsize != -1 then it is returning */
4538 bad_param:
4540 srv_signing_trans_stop();
4541 SAFE_FREE(params);
4542 SAFE_FREE(data);
4543 END_PROFILE(SMBtrans2);
4544 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);