Added support for OS/2 EA's in smbd server. Test with smbtorture eatest.
[Samba/bb.git] / source3 / smbd / trans2.c
blobb1807705a0bf353ac512c938910e96d65a833b4d
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 int Protocol;
27 extern BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
36 /* given a stat buffer return the allocated size on disk, taking into
37 account sparse files */
38 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
40 SMB_BIG_UINT ret;
41 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
43 #else
44 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
45 #endif
46 if (!ret && fsp && fsp->initial_allocation_size)
47 ret = fsp->initial_allocation_size;
48 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
49 return ret;
52 /****************************************************************************
53 Utility functions for dealing with extended attributes.
54 ****************************************************************************/
56 static const char *prohibited_ea_names[] = {
57 SAMBA_POSIX_INHERITANCE_EA_NAME,
58 NULL
61 /****************************************************************************
62 Refuse to allow clients to overwrite our private xattrs.
63 ****************************************************************************/
65 static BOOL samba_private_attr_name(const char *unix_ea_name)
67 int i;
69 for (i = 0; prohibited_ea_names[i]; i++) {
70 if (strequal( prohibited_ea_names[i], unix_ea_name))
71 return True;
73 return False;
76 struct ea_list {
77 struct ea_list *next, *prev;
78 struct ea_struct ea;
81 /****************************************************************************
82 Get one EA value. Fill in a struct ea_struct.
83 ****************************************************************************/
85 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
86 const char *fname, char *ea_name, struct ea_struct *pea)
88 /* Get the value of this xattr. Max size is 64k. */
89 size_t attr_size = 256;
90 char *val = NULL;
91 ssize_t sizeret;
93 again:
95 val = talloc_realloc(mem_ctx, val, attr_size);
96 if (!val) {
97 return False;
100 if (fsp && fsp->fd != -1) {
101 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
102 } else {
103 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
106 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
107 attr_size = 65536;
108 goto again;
111 if (sizeret == -1) {
112 return False;
115 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
116 dump_data(10, val, sizeret);
118 pea->flags = 0;
119 if (strnequal(ea_name, "user.", 5)) {
120 pea->name = &ea_name[5];
121 } else {
122 pea->name = ea_name;
124 pea->value.data = val;
125 pea->value.length = (size_t)sizeret;
126 return True;
129 /****************************************************************************
130 Return a linked list of the total EA's. Plus a guess as to the total size
131 (NB. The is not the total size on the wire - we need to convert to DOS
132 codepage for that).
133 ****************************************************************************/
135 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)
137 /* Get a list of all xattrs. Max namesize is 64k. */
138 size_t ea_namelist_size = 1024;
139 char *ea_namelist;
140 char *p;
141 ssize_t sizeret;
142 int i;
143 struct ea_list *ea_list_head = NULL;
145 if (pea_total_len) {
146 *pea_total_len = 0;
149 if (!lp_ea_support(SNUM(conn))) {
150 return NULL;
153 for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
154 ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
155 if (fsp && fsp->fd != -1) {
156 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
157 } else {
158 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
161 if (sizeret == -1 && errno == ERANGE) {
162 ea_namelist_size *= 2;
163 } else {
164 break;
168 if (sizeret == -1)
169 return NULL;
171 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
173 if (sizeret) {
174 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
175 struct ea_list *listp, *tmp;
177 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
178 continue;
180 listp = talloc(mem_ctx, sizeof(struct ea_list));
181 if (!listp)
182 return NULL;
184 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
185 return NULL;
188 if (pea_total_len) {
189 *pea_total_len += 4 + strlen(p) + 1 + listp->ea.value.length;
191 DLIST_ADD_END(ea_list_head, listp, tmp);
195 /* Add on 4 for total length. */
196 if (pea_total_len) {
197 *pea_total_len += 4;
199 return ea_list_head;
202 /****************************************************************************
203 Fill a qfilepathinfo buffer with EA's.
204 ****************************************************************************/
206 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
207 connection_struct *conn, files_struct *fsp, const char *fname)
209 unsigned int ret_data_size = 4;
210 char *p = pdata;
211 size_t total_ea_len;
212 TALLOC_CTX *mem_ctx = talloc_init("fill_ea_buffer");
213 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
215 SMB_ASSERT(total_data_size >= 4);
217 SIVAL(pdata,0,0);
218 if (!mem_ctx) {
219 return 4;
222 if (!ea_list) {
223 talloc_destroy(mem_ctx);
224 return 4;
227 if (total_ea_len > total_data_size) {
228 talloc_destroy(mem_ctx);
229 return 4;
232 total_data_size -= 4;
233 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
234 size_t dos_namelen;
235 fstring dos_ea_name;
236 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
237 dos_namelen = strlen(dos_ea_name);
238 if (dos_namelen > 255 || dos_namelen == 0) {
239 break;
241 if (ea_list->ea.value.length > 65535) {
242 break;
244 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
245 break;
248 /* We know we have room. */
249 SCVAL(p,0,ea_list->ea.flags);
250 SCVAL(p,1,dos_namelen);
251 SSVAL(p,2,ea_list->ea.value.length);
252 fstrcpy(p+4, dos_ea_name);
253 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
255 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
256 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
259 ret_data_size = PTR_DIFF(p, pdata);
260 talloc_destroy(mem_ctx);
261 SIVAL(pdata,0,ret_data_size);
262 return ret_data_size;
265 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
267 size_t total_ea_len = 0;
268 TALLOC_CTX *mem_ctx = talloc_init("estimate_ea_size");
270 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
271 talloc_destroy(mem_ctx);
272 return total_ea_len;
275 /****************************************************************************
276 Set or delete an extended attribute.
277 ****************************************************************************/
279 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
280 char *pdata, int total_data)
282 unsigned int namelen;
283 unsigned int ealen;
284 int ret;
285 fstring unix_ea_name;
287 if (!lp_ea_support(SNUM(conn))) {
288 return NT_STATUS_EAS_NOT_SUPPORTED;
291 if (total_data < 8) {
292 return NT_STATUS_INVALID_PARAMETER;
295 if (IVAL(pdata,0) > total_data) {
296 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
297 return NT_STATUS_INVALID_PARAMETER;
300 pdata += 4;
301 namelen = CVAL(pdata,1);
302 ealen = SVAL(pdata,2);
303 pdata += 4;
304 if (total_data < 8 + namelen + 1 + ealen) {
305 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
306 (unsigned int)total_data, namelen, ealen));
307 return NT_STATUS_INVALID_PARAMETER;
310 if (pdata[namelen] != '\0') {
311 DEBUG(10,("set_ea: ea name not null terminated\n"));
312 return NT_STATUS_INVALID_PARAMETER;
315 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
316 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
317 pdata += (namelen + 1);
319 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
320 if (ealen) {
321 DEBUG(10,("set_ea: data :\n"));
322 dump_data(10, pdata, ealen);
325 if (samba_private_attr_name(unix_ea_name)) {
326 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
327 return NT_STATUS_ACCESS_DENIED;
330 if (ealen == 0) {
331 /* Remove the attribute. */
332 if (fsp && (fsp->fd != -1)) {
333 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
334 unix_ea_name, fsp->fsp_name));
335 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
336 } else {
337 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
338 unix_ea_name, fname));
339 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
341 #ifdef ENOATTR
342 /* Removing a non existent attribute always succeeds. */
343 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
344 if (ret == -1 && errno == ENOATTR) {
345 ret = 0;
347 #endif
348 } else {
349 if (fsp && (fsp->fd != -1)) {
350 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
351 unix_ea_name, fsp->fsp_name));
352 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
353 } else {
354 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
355 unix_ea_name, fname));
356 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
360 if (ret == -1) {
361 if (errno == ENOTSUP) {
362 return NT_STATUS_EAS_NOT_SUPPORTED;
364 return map_nt_error_from_unix(errno);
367 return NT_STATUS_OK;
370 /****************************************************************************
371 Send the required number of replies back.
372 We assume all fields other than the data fields are
373 set correctly for the type of call.
374 HACK ! Always assumes smb_setup field is zero.
375 ****************************************************************************/
377 static int send_trans2_replies(char *outbuf,
378 int bufsize,
379 char *params,
380 int paramsize,
381 char *pdata,
382 int datasize)
384 /* As we are using a protocol > LANMAN1 then the max_send
385 variable must have been set in the sessetupX call.
386 This takes precedence over the max_xmit field in the
387 global struct. These different max_xmit variables should
388 be merged as this is now too confusing */
390 extern int max_send;
391 int data_to_send = datasize;
392 int params_to_send = paramsize;
393 int useable_space;
394 char *pp = params;
395 char *pd = pdata;
396 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
397 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
398 int data_alignment_offset = 0;
400 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
402 set_message(outbuf,10,0,True);
404 /* If there genuinely are no parameters or data to send just send the empty packet */
406 if(params_to_send == 0 && data_to_send == 0) {
407 if (!send_smb(smbd_server_fd(),outbuf))
408 exit_server("send_trans2_replies: send_smb failed.");
409 return 0;
412 /* When sending params and data ensure that both are nicely aligned */
413 /* Only do this alignment when there is also data to send - else
414 can cause NT redirector problems. */
416 if (((params_to_send % 4) != 0) && (data_to_send != 0))
417 data_alignment_offset = 4 - (params_to_send % 4);
419 /* Space is bufsize minus Netbios over TCP header minus SMB header */
420 /* The alignment_offset is to align the param bytes on an even byte
421 boundary. NT 4.0 Beta needs this to work correctly. */
423 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
425 /* useable_space can never be more than max_send minus the alignment offset. */
427 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
429 while (params_to_send || data_to_send) {
430 /* Calculate whether we will totally or partially fill this packet */
432 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
434 /* We can never send more than useable_space */
436 * Note that 'useable_space' does not include the alignment offsets,
437 * but we must include the alignment offsets in the calculation of
438 * the length of the data we send over the wire, as the alignment offsets
439 * are sent here. Fix from Marc_Jacobsen@hp.com.
442 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
444 set_message(outbuf, 10, total_sent_thistime, True);
446 /* Set total params and data to be sent */
447 SSVAL(outbuf,smb_tprcnt,paramsize);
448 SSVAL(outbuf,smb_tdrcnt,datasize);
450 /* Calculate how many parameters and data we can fit into
451 * this packet. Parameters get precedence
454 params_sent_thistime = MIN(params_to_send,useable_space);
455 data_sent_thistime = useable_space - params_sent_thistime;
456 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
458 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
460 /* smb_proff is the offset from the start of the SMB header to the
461 parameter bytes, however the first 4 bytes of outbuf are
462 the Netbios over TCP header. Thus use smb_base() to subtract
463 them from the calculation */
465 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
467 if(params_sent_thistime == 0)
468 SSVAL(outbuf,smb_prdisp,0);
469 else
470 /* Absolute displacement of param bytes sent in this packet */
471 SSVAL(outbuf,smb_prdisp,pp - params);
473 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
474 if(data_sent_thistime == 0) {
475 SSVAL(outbuf,smb_droff,0);
476 SSVAL(outbuf,smb_drdisp, 0);
477 } else {
478 /* The offset of the data bytes is the offset of the
479 parameter bytes plus the number of parameters being sent this time */
480 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
481 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
482 SSVAL(outbuf,smb_drdisp, pd - pdata);
485 /* Copy the param bytes into the packet */
487 if(params_sent_thistime)
488 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
490 /* Copy in the data bytes */
491 if(data_sent_thistime)
492 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
493 data_alignment_offset,pd,data_sent_thistime);
495 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
496 params_sent_thistime, data_sent_thistime, useable_space));
497 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
498 params_to_send, data_to_send, paramsize, datasize));
500 /* Send the packet */
501 if (!send_smb(smbd_server_fd(),outbuf))
502 exit_server("send_trans2_replies: send_smb failed.");
504 pp += params_sent_thistime;
505 pd += data_sent_thistime;
507 params_to_send -= params_sent_thistime;
508 data_to_send -= data_sent_thistime;
510 /* Sanity check */
511 if(params_to_send < 0 || data_to_send < 0) {
512 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
513 params_to_send, data_to_send));
514 return -1;
518 return 0;
521 /****************************************************************************
522 Reply to a TRANSACT2_OPEN.
523 ****************************************************************************/
525 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
526 char **pparams, int total_params, char **ppdata, int total_data)
528 char *params = *pparams;
529 int16 open_mode;
530 int16 open_attr;
531 BOOL oplock_request;
532 #if 0
533 BOOL return_additional_info;
534 int16 open_sattr;
535 time_t open_time;
536 #endif
537 int16 open_ofun;
538 int32 open_size;
539 char *pname;
540 pstring fname;
541 mode_t unixmode;
542 SMB_OFF_T size=0;
543 int fmode=0,mtime=0,rmode;
544 SMB_INO_T inode = 0;
545 SMB_STRUCT_STAT sbuf;
546 int smb_action = 0;
547 BOOL bad_path = False;
548 files_struct *fsp;
549 NTSTATUS status;
552 * Ensure we have enough parameters to perform the operation.
555 if (total_params < 29)
556 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
558 open_mode = SVAL(params, 2);
559 open_attr = SVAL(params,6);
560 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
561 #if 0
562 return_additional_info = BITSETW(params,0);
563 open_sattr = SVAL(params, 4);
564 open_time = make_unix_date3(params+8);
565 #endif
566 open_ofun = SVAL(params,12);
567 open_size = IVAL(params,14);
568 pname = &params[28];
570 if (IS_IPC(conn))
571 return(ERROR_DOS(ERRSRV,ERRaccess));
573 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
574 if (!NT_STATUS_IS_OK(status)) {
575 return ERROR_NT(status);
578 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
579 fname,open_mode, open_attr, open_ofun, open_size));
581 /* XXXX we need to handle passed times, sattr and flags */
583 unix_convert(fname,conn,0,&bad_path,&sbuf);
585 if (!check_name(fname,conn)) {
586 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
589 unixmode = unix_mode(conn,open_attr | aARCH, fname);
591 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
592 oplock_request, &rmode,&smb_action);
594 if (!fsp) {
595 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
598 size = get_file_size(sbuf);
599 fmode = dos_mode(conn,fname,&sbuf);
600 mtime = sbuf.st_mtime;
601 inode = sbuf.st_ino;
602 if (fmode & aDIR) {
603 close_file(fsp,False);
604 return(ERROR_DOS(ERRDOS,ERRnoaccess));
607 /* Realloc the size of parameters and data we will return */
608 params = Realloc(*pparams, 28);
609 if( params == NULL )
610 return(ERROR_DOS(ERRDOS,ERRnomem));
611 *pparams = params;
613 memset((char *)params,'\0',28);
614 SSVAL(params,0,fsp->fnum);
615 SSVAL(params,2,fmode);
616 put_dos_date2(params,4, mtime);
617 SIVAL(params,8, (uint32)size);
618 SSVAL(params,12,rmode);
620 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
621 smb_action |= EXTENDED_OPLOCK_GRANTED;
623 SSVAL(params,18,smb_action);
626 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
628 SIVAL(params,20,inode);
630 /* Send the required number of replies */
631 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
633 return -1;
636 /*********************************************************
637 Routine to check if a given string matches exactly.
638 as a special case a mask of "." does NOT match. That
639 is required for correct wildcard semantics
640 Case can be significant or not.
641 **********************************************************/
643 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
645 if (mask[0] == '.' && mask[1] == 0)
646 return False;
647 if (case_sig)
648 return strcmp(str,mask)==0;
649 if (StrCaseCmp(str,mask) != 0) {
650 return False;
652 if (ms_has_wild(str)) {
653 return False;
655 return True;
658 /****************************************************************************
659 Return the filetype for UNIX extensions.
660 ****************************************************************************/
662 static uint32 unix_filetype(mode_t mode)
664 if(S_ISREG(mode))
665 return UNIX_TYPE_FILE;
666 else if(S_ISDIR(mode))
667 return UNIX_TYPE_DIR;
668 #ifdef S_ISLNK
669 else if(S_ISLNK(mode))
670 return UNIX_TYPE_SYMLINK;
671 #endif
672 #ifdef S_ISCHR
673 else if(S_ISCHR(mode))
674 return UNIX_TYPE_CHARDEV;
675 #endif
676 #ifdef S_ISBLK
677 else if(S_ISBLK(mode))
678 return UNIX_TYPE_BLKDEV;
679 #endif
680 #ifdef S_ISFIFO
681 else if(S_ISFIFO(mode))
682 return UNIX_TYPE_FIFO;
683 #endif
684 #ifdef S_ISSOCK
685 else if(S_ISSOCK(mode))
686 return UNIX_TYPE_SOCKET;
687 #endif
689 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
690 return UNIX_TYPE_UNKNOWN;
693 /****************************************************************************
694 Return the major devicenumber for UNIX extensions.
695 ****************************************************************************/
697 static uint32 unix_dev_major(SMB_DEV_T dev)
699 #if defined(HAVE_DEVICE_MAJOR_FN)
700 return (uint32)major(dev);
701 #else
702 return (uint32)(dev >> 8);
703 #endif
706 /****************************************************************************
707 Return the minor devicenumber for UNIX extensions.
708 ****************************************************************************/
710 static uint32 unix_dev_minor(SMB_DEV_T dev)
712 #if defined(HAVE_DEVICE_MINOR_FN)
713 return (uint32)minor(dev);
714 #else
715 return (uint32)(dev & 0xff);
716 #endif
719 /****************************************************************************
720 Map wire perms onto standard UNIX permissions. Obey share restrictions.
721 ****************************************************************************/
723 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
725 mode_t ret = 0;
727 if (perms == SMB_MODE_NO_CHANGE)
728 return pst->st_mode;
730 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
731 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
732 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
733 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
734 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
735 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
736 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
737 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
738 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
739 #ifdef S_ISVTX
740 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
741 #endif
742 #ifdef S_ISGID
743 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
744 #endif
745 #ifdef S_ISUID
746 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
747 #endif
749 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
750 ret &= lp_dir_mask(SNUM(conn));
751 /* Add in force bits */
752 ret |= lp_force_dir_mode(SNUM(conn));
753 } else {
754 /* Apply mode mask */
755 ret &= lp_create_mask(SNUM(conn));
756 /* Add in force bits */
757 ret |= lp_force_create_mode(SNUM(conn));
760 return ret;
763 /****************************************************************************
764 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
765 ****************************************************************************/
767 time_t interpret_long_unix_date(char *p)
769 DEBUG(1,("interpret_long_unix_date\n"));
770 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
771 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
772 return -1;
773 } else {
774 return interpret_long_date(p);
778 /****************************************************************************
779 Get a level dependent lanman2 dir entry.
780 ****************************************************************************/
782 static BOOL get_lanman2_dir_entry(connection_struct *conn,
783 void *inbuf, void *outbuf,
784 char *path_mask,int dirtype,int info_level,
785 int requires_resume_key,
786 BOOL dont_descend,char **ppdata,
787 char *base_data, int space_remaining,
788 BOOL *out_of_space, BOOL *got_exact_match,
789 int *last_name_off)
791 const char *dname;
792 BOOL found = False;
793 SMB_STRUCT_STAT sbuf;
794 pstring mask;
795 pstring pathreal;
796 pstring fname;
797 char *p, *q, *pdata = *ppdata;
798 uint32 reskey=0;
799 int prev_dirpos=0;
800 int mode=0;
801 SMB_OFF_T file_size = 0;
802 SMB_BIG_UINT allocation_size = 0;
803 uint32 len;
804 time_t mdate=0, adate=0, cdate=0;
805 char *nameptr;
806 BOOL was_8_3;
807 int nt_extmode; /* Used for NT connections instead of mode */
808 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
810 *fname = 0;
811 *out_of_space = False;
812 *got_exact_match = False;
814 if (!conn->dirptr)
815 return(False);
817 p = strrchr_m(path_mask,'/');
818 if(p != NULL) {
819 if(p[1] == '\0')
820 pstrcpy(mask,"*.*");
821 else
822 pstrcpy(mask, p+1);
823 } else
824 pstrcpy(mask, path_mask);
826 while (!found) {
827 BOOL got_match;
829 /* Needed if we run out of space */
830 prev_dirpos = TellDir(conn->dirptr);
831 dname = ReadDirName(conn->dirptr);
834 * Due to bugs in NT client redirectors we are not using
835 * resume keys any more - set them to zero.
836 * Check out the related comments in findfirst/findnext.
837 * JRA.
840 reskey = 0;
842 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
843 (long)conn->dirptr,TellDir(conn->dirptr)));
845 if (!dname)
846 return(False);
848 pstrcpy(fname,dname);
850 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
851 got_match = mask_match(fname, mask, case_sensitive);
853 if(!got_match && !mangle_is_8_3(fname, False)) {
856 * It turns out that NT matches wildcards against
857 * both long *and* short names. This may explain some
858 * of the wildcard wierdness from old DOS clients
859 * that some people have been seeing.... JRA.
862 pstring newname;
863 pstrcpy( newname, fname);
864 mangle_map( newname, True, False, SNUM(conn));
865 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
866 got_match = mask_match(newname, mask, case_sensitive);
869 if(got_match) {
870 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
871 if (dont_descend && !isdots)
872 continue;
874 pstrcpy(pathreal,conn->dirpath);
875 if(needslash)
876 pstrcat(pathreal,"/");
877 pstrcat(pathreal,dname);
879 if (INFO_LEVEL_IS_UNIX(info_level)) {
880 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
881 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
882 pathreal,strerror(errno)));
883 continue;
885 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
887 /* Needed to show the msdfs symlinks as
888 * directories */
890 if(lp_host_msdfs() &&
891 lp_msdfs_root(SNUM(conn)) &&
892 is_msdfs_link(conn, pathreal, NULL, NULL,
893 &sbuf)) {
895 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
896 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
898 } else {
900 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
901 pathreal,strerror(errno)));
902 continue;
906 mode = dos_mode(conn,pathreal,&sbuf);
908 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
909 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
910 continue;
913 file_size = get_file_size(sbuf);
914 allocation_size = get_allocation_size(NULL,&sbuf);
915 mdate = sbuf.st_mtime;
916 adate = sbuf.st_atime;
917 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
919 if (lp_dos_filetime_resolution(SNUM(conn))) {
920 cdate &= ~1;
921 mdate &= ~1;
922 adate &= ~1;
925 if(mode & aDIR)
926 file_size = 0;
928 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
930 found = True;
934 mangle_map(fname,False,True,SNUM(conn));
936 p = pdata;
937 nameptr = p;
939 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
941 switch (info_level) {
942 case SMB_INFO_STANDARD:
943 if(requires_resume_key) {
944 SIVAL(p,0,reskey);
945 p += 4;
947 put_dos_date2(p,l1_fdateCreation,cdate);
948 put_dos_date2(p,l1_fdateLastAccess,adate);
949 put_dos_date2(p,l1_fdateLastWrite,mdate);
950 SIVAL(p,l1_cbFile,(uint32)file_size);
951 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
952 SSVAL(p,l1_attrFile,mode);
953 p += l1_achName;
954 nameptr = p;
955 p += align_string(outbuf, p, 0);
956 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
957 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
958 SCVAL(nameptr, -1, len-2);
959 else
960 SCVAL(nameptr, -1, len-1);
961 p += len;
962 break;
964 case SMB_INFO_QUERY_EA_SIZE:
965 if(requires_resume_key) {
966 SIVAL(p,0,reskey);
967 p += 4;
969 put_dos_date2(p,l2_fdateCreation,cdate);
970 put_dos_date2(p,l2_fdateLastAccess,adate);
971 put_dos_date2(p,l2_fdateLastWrite,mdate);
972 SIVAL(p,l2_cbFile,(uint32)file_size);
973 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
974 SSVAL(p,l2_attrFile,mode);
975 SIVAL(p,l2_cbList,0); /* No extended attributes */
976 p += l2_achName;
977 nameptr = p;
978 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
979 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
980 SCVAL(nameptr, -1, len-2);
981 else
982 SCVAL(nameptr, -1, len-1);
983 p += len;
984 break;
986 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
987 was_8_3 = mangle_is_8_3(fname, True);
988 p += 4;
989 SIVAL(p,0,reskey); p += 4;
990 put_long_date(p,cdate); p += 8;
991 put_long_date(p,adate); p += 8;
992 put_long_date(p,mdate); p += 8;
993 put_long_date(p,mdate); p += 8;
994 SOFF_T(p,0,file_size);
995 SOFF_T(p,8,allocation_size);
996 p += 16;
997 SIVAL(p,0,nt_extmode); p += 4;
998 q = p; p += 4;
999 SIVAL(p,0,0); p += 4;
1000 /* Clear the short name buffer. This is
1001 * IMPORTANT as not doing so will trigger
1002 * a Win2k client bug. JRA.
1004 memset(p,'\0',26);
1005 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1006 pstring mangled_name;
1007 pstrcpy(mangled_name, fname);
1008 mangle_map(mangled_name,True,True,SNUM(conn));
1009 mangled_name[12] = 0;
1010 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1011 SSVAL(p, 0, len);
1012 } else {
1013 SSVAL(p,0,0);
1014 *(p+2) = 0;
1016 p += 2 + 24;
1017 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1018 SIVAL(q,0,len);
1019 p += len;
1020 len = PTR_DIFF(p, pdata);
1021 len = (len + 3) & ~3;
1022 SIVAL(pdata,0,len);
1023 p = pdata + len;
1024 break;
1026 case SMB_FIND_FILE_DIRECTORY_INFO:
1027 p += 4;
1028 SIVAL(p,0,reskey); p += 4;
1029 put_long_date(p,cdate); p += 8;
1030 put_long_date(p,adate); p += 8;
1031 put_long_date(p,mdate); p += 8;
1032 put_long_date(p,mdate); p += 8;
1033 SOFF_T(p,0,file_size);
1034 SOFF_T(p,8,allocation_size);
1035 p += 16;
1036 SIVAL(p,0,nt_extmode); p += 4;
1037 p += 4;
1038 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1039 SIVAL(p, -4, len);
1040 p += len;
1041 len = PTR_DIFF(p, pdata);
1042 len = (len + 3) & ~3;
1043 SIVAL(pdata,0,len);
1044 p = pdata + len;
1045 break;
1047 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1048 p += 4;
1049 SIVAL(p,0,reskey); p += 4;
1050 put_long_date(p,cdate); p += 8;
1051 put_long_date(p,adate); p += 8;
1052 put_long_date(p,mdate); p += 8;
1053 put_long_date(p,mdate); p += 8;
1054 SOFF_T(p,0,file_size);
1055 SOFF_T(p,8,allocation_size);
1056 p += 16;
1057 SIVAL(p,0,nt_extmode);
1058 p += 4;
1060 SIVAL(p,4,0); /* ea size */
1061 len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII);
1062 SIVAL(p, 0, len);
1063 p += 8 + len;
1065 len = PTR_DIFF(p, pdata);
1066 len = (len + 3) & ~3;
1067 SIVAL(pdata,0,len);
1068 p = pdata + len;
1069 break;
1071 case SMB_FIND_FILE_NAMES_INFO:
1072 p += 4;
1073 SIVAL(p,0,reskey); p += 4;
1074 p += 4;
1075 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1076 acl on a dir (tridge) */
1077 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1078 SIVAL(p, -4, 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_LEVEL_261:
1087 p += 4;
1088 SIVAL(p,0,reskey); p += 4;
1089 put_long_date(p,cdate); p += 8;
1090 put_long_date(p,adate); p += 8;
1091 put_long_date(p,mdate); p += 8;
1092 put_long_date(p,mdate); p += 8;
1093 SOFF_T(p,0,file_size);
1094 SOFF_T(p,8,allocation_size);
1095 p += 16;
1096 SIVAL(p,0,nt_extmode);
1097 p += 4;
1098 len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII);
1099 SIVAL(p, 0, len);
1100 memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */
1101 p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */
1102 len = PTR_DIFF(p, pdata);
1103 len = (len + 3) & ~3;
1104 SIVAL(pdata,0,len);
1105 p = pdata + len;
1106 break;
1108 case SMB_FIND_FILE_LEVEL_262:
1109 was_8_3 = mangle_is_8_3(fname, True);
1110 p += 4;
1111 SIVAL(p,0,reskey); p += 4;
1112 put_long_date(p,cdate); p += 8;
1113 put_long_date(p,adate); p += 8;
1114 put_long_date(p,mdate); p += 8;
1115 put_long_date(p,mdate); p += 8;
1116 SOFF_T(p,0,file_size);
1117 SOFF_T(p,8,allocation_size);
1118 p += 16;
1119 SIVAL(p,0,nt_extmode); p += 4;
1120 q = p; p += 4;
1121 SIVAL(p,0,0); p += 4;
1122 /* Clear the short name buffer. This is
1123 * IMPORTANT as not doing so will trigger
1124 * a Win2k client bug. JRA.
1126 memset(p,'\0',26);
1127 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1128 pstring mangled_name;
1129 pstrcpy(mangled_name, fname);
1130 mangle_map(mangled_name,True,True,SNUM(conn));
1131 mangled_name[12] = 0;
1132 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1133 SSVAL(p, 0, len);
1134 } else {
1135 SSVAL(p,0,0);
1136 *(p+2) = 0;
1138 p += 2 + 24;
1139 memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */
1140 p += 10;
1141 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1142 SIVAL(q,0,len);
1143 p += len;
1144 len = PTR_DIFF(p, pdata);
1145 len = (len + 3) & ~3;
1146 SIVAL(pdata,0,len);
1147 p = pdata + len;
1148 break;
1150 /* CIFS UNIX Extension. */
1152 case SMB_FIND_FILE_UNIX:
1153 p+= 4;
1154 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1156 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1157 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1158 p+= 8;
1160 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1161 p+= 8;
1163 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
1164 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1165 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1166 p+= 24;
1168 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1169 SIVAL(p,4,0);
1170 p+= 8;
1172 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1173 SIVAL(p,4,0);
1174 p+= 8;
1176 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1177 p+= 4;
1179 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1180 SIVAL(p,4,0);
1181 p+= 8;
1183 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1184 SIVAL(p,4,0);
1185 p+= 8;
1187 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1188 p+= 8;
1190 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1191 SIVAL(p,4,0);
1192 p+= 8;
1194 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1195 SIVAL(p,4,0);
1196 p+= 8;
1198 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1199 p += len;
1201 len = PTR_DIFF(p, pdata);
1202 len = (len + 3) & ~3;
1203 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1204 p = pdata + len;
1205 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1207 break;
1209 default:
1210 return(False);
1214 if (PTR_DIFF(p,pdata) > space_remaining) {
1215 /* Move the dirptr back to prev_dirpos */
1216 SeekDir(conn->dirptr, prev_dirpos);
1217 *out_of_space = True;
1218 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1219 return False; /* Not finished - just out of space */
1222 /* Setup the last_filename pointer, as an offset from base_data */
1223 *last_name_off = PTR_DIFF(nameptr,base_data);
1224 /* Advance the data pointer to the next slot */
1225 *ppdata = p;
1227 return(found);
1230 /****************************************************************************
1231 Reply to a TRANS2_FINDFIRST.
1232 ****************************************************************************/
1234 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1235 char **pparams, int total_params, char **ppdata, int total_data)
1237 /* We must be careful here that we don't return more than the
1238 allowed number of data bytes. If this means returning fewer than
1239 maxentries then so be it. We assume that the redirector has
1240 enough room for the fixed number of parameter bytes it has
1241 requested. */
1242 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1243 char *params = *pparams;
1244 char *pdata = *ppdata;
1245 int dirtype = SVAL(params,0);
1246 int maxentries = SVAL(params,2);
1247 BOOL close_after_first = BITSETW(params+4,0);
1248 BOOL close_if_end = BITSETW(params+4,1);
1249 BOOL requires_resume_key = BITSETW(params+4,2);
1250 int info_level = SVAL(params,6);
1251 pstring directory;
1252 pstring mask;
1253 char *p, *wcard;
1254 int last_name_off=0;
1255 int dptr_num = -1;
1256 int numentries = 0;
1257 int i;
1258 BOOL finished = False;
1259 BOOL dont_descend = False;
1260 BOOL out_of_space = False;
1261 int space_remaining;
1262 BOOL bad_path = False;
1263 SMB_STRUCT_STAT sbuf;
1264 NTSTATUS ntstatus = NT_STATUS_OK;
1266 if (total_params < 12)
1267 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1269 *directory = *mask = 0;
1271 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1272 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
1273 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1274 info_level, max_data_bytes));
1276 switch (info_level) {
1277 case SMB_INFO_STANDARD:
1278 case SMB_INFO_QUERY_EA_SIZE:
1279 case SMB_FIND_FILE_DIRECTORY_INFO:
1280 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1281 case SMB_FIND_FILE_NAMES_INFO:
1282 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1283 case SMB_FIND_FILE_LEVEL_261:
1284 case SMB_FIND_FILE_LEVEL_262:
1285 break;
1286 case SMB_FIND_FILE_UNIX:
1287 if (!lp_unix_extensions())
1288 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1289 break;
1290 default:
1291 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1294 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1295 if (!NT_STATUS_IS_OK(ntstatus)) {
1296 return ERROR_NT(ntstatus);
1299 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1301 unix_convert(directory,conn,0,&bad_path,&sbuf);
1302 if(!check_name(directory,conn)) {
1303 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1306 p = strrchr_m(directory,'/');
1307 if(p == NULL) {
1308 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1309 if((directory[0] == '.') && (directory[1] == '\0'))
1310 pstrcpy(mask,"*");
1311 else
1312 pstrcpy(mask,directory);
1313 pstrcpy(directory,"./");
1314 } else {
1315 pstrcpy(mask,p+1);
1316 *p = 0;
1319 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1321 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1322 if( pdata == NULL )
1323 return(ERROR_DOS(ERRDOS,ERRnomem));
1325 *ppdata = pdata;
1326 memset((char *)pdata,'\0',max_data_bytes + 1024);
1328 /* Realloc the params space */
1329 params = Realloc(*pparams, 10);
1330 if (params == NULL)
1331 return ERROR_DOS(ERRDOS,ERRnomem);
1332 *pparams = params;
1334 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1335 if (dptr_num < 0)
1336 return(UNIXERROR(ERRDOS,ERRbadfile));
1338 /* Save the wildcard match and attribs we are using on this directory -
1339 needed as lanman2 assumes these are being saved between calls */
1341 if(!(wcard = strdup(mask))) {
1342 dptr_close(&dptr_num);
1343 return ERROR_DOS(ERRDOS,ERRnomem);
1346 dptr_set_wcard(dptr_num, wcard);
1347 dptr_set_attr(dptr_num, dirtype);
1349 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1351 /* We don't need to check for VOL here as this is returned by
1352 a different TRANS2 call. */
1354 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1355 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1356 dont_descend = True;
1358 p = pdata;
1359 space_remaining = max_data_bytes;
1360 out_of_space = False;
1362 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1363 BOOL got_exact_match = False;
1365 /* this is a heuristic to avoid seeking the dirptr except when
1366 absolutely necessary. It allows for a filename of about 40 chars */
1367 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1368 out_of_space = True;
1369 finished = False;
1370 } else {
1371 finished = !get_lanman2_dir_entry(conn,
1372 inbuf, outbuf,
1373 mask,dirtype,info_level,
1374 requires_resume_key,dont_descend,
1375 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1376 &last_name_off);
1379 if (finished && out_of_space)
1380 finished = False;
1382 if (!finished && !out_of_space)
1383 numentries++;
1386 * As an optimisation if we know we aren't looking
1387 * for a wildcard name (ie. the name matches the wildcard exactly)
1388 * then we can finish on any (first) match.
1389 * This speeds up large directory searches. JRA.
1392 if(got_exact_match)
1393 finished = True;
1395 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1398 /* Check if we can close the dirptr */
1399 if(close_after_first || (finished && close_if_end)) {
1400 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1401 dptr_close(&dptr_num);
1405 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1406 * from observation of NT.
1409 if(numentries == 0) {
1410 dptr_close(&dptr_num);
1411 return ERROR_DOS(ERRDOS,ERRbadfile);
1414 /* At this point pdata points to numentries directory entries. */
1416 /* Set up the return parameter block */
1417 SSVAL(params,0,dptr_num);
1418 SSVAL(params,2,numentries);
1419 SSVAL(params,4,finished);
1420 SSVAL(params,6,0); /* Never an EA error */
1421 SSVAL(params,8,last_name_off);
1423 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1425 if ((! *directory) && dptr_path(dptr_num))
1426 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1428 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1429 smb_fn_name(CVAL(inbuf,smb_com)),
1430 mask, directory, dirtype, numentries ) );
1433 * Force a name mangle here to ensure that the
1434 * mask as an 8.3 name is top of the mangled cache.
1435 * The reasons for this are subtle. Don't remove
1436 * this code unless you know what you are doing
1437 * (see PR#13758). JRA.
1440 if(!mangle_is_8_3_wildcards( mask, False))
1441 mangle_map(mask, True, True, SNUM(conn));
1443 return(-1);
1446 /****************************************************************************
1447 Reply to a TRANS2_FINDNEXT.
1448 ****************************************************************************/
1450 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1451 char **pparams, int total_params, char **ppdata, int total_data)
1453 /* We must be careful here that we don't return more than the
1454 allowed number of data bytes. If this means returning fewer than
1455 maxentries then so be it. We assume that the redirector has
1456 enough room for the fixed number of parameter bytes it has
1457 requested. */
1458 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1459 char *params = *pparams;
1460 char *pdata = *ppdata;
1461 int dptr_num = SVAL(params,0);
1462 int maxentries = SVAL(params,2);
1463 uint16 info_level = SVAL(params,4);
1464 uint32 resume_key = IVAL(params,6);
1465 BOOL close_after_request = BITSETW(params+10,0);
1466 BOOL close_if_end = BITSETW(params+10,1);
1467 BOOL requires_resume_key = BITSETW(params+10,2);
1468 BOOL continue_bit = BITSETW(params+10,3);
1469 pstring resume_name;
1470 pstring mask;
1471 pstring directory;
1472 char *p;
1473 uint16 dirtype;
1474 int numentries = 0;
1475 int i, last_name_off=0;
1476 BOOL finished = False;
1477 BOOL dont_descend = False;
1478 BOOL out_of_space = False;
1479 int space_remaining;
1480 NTSTATUS ntstatus = NT_STATUS_OK;
1482 if (total_params < 12)
1483 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1485 *mask = *directory = *resume_name = 0;
1487 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1488 if (!NT_STATUS_IS_OK(ntstatus)) {
1489 return ERROR_NT(ntstatus);
1492 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1493 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1494 resume_key = %d resume name = %s continue=%d level = %d\n",
1495 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1496 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1498 switch (info_level) {
1499 case SMB_INFO_STANDARD:
1500 case SMB_INFO_QUERY_EA_SIZE:
1501 case SMB_FIND_FILE_DIRECTORY_INFO:
1502 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1503 case SMB_FIND_FILE_NAMES_INFO:
1504 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1505 break;
1506 case SMB_FIND_FILE_UNIX:
1507 if (!lp_unix_extensions())
1508 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1509 break;
1510 default:
1511 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1514 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1515 if(pdata == NULL)
1516 return ERROR_DOS(ERRDOS,ERRnomem);
1518 *ppdata = pdata;
1519 memset((char *)pdata,'\0',max_data_bytes + 1024);
1521 /* Realloc the params space */
1522 params = Realloc(*pparams, 6*SIZEOFWORD);
1523 if( params == NULL )
1524 return ERROR_DOS(ERRDOS,ERRnomem);
1526 *pparams = params;
1528 /* Check that the dptr is valid */
1529 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1530 return ERROR_DOS(ERRDOS,ERRnofiles);
1532 string_set(&conn->dirpath,dptr_path(dptr_num));
1534 /* Get the wildcard mask from the dptr */
1535 if((p = dptr_wcard(dptr_num))== NULL) {
1536 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1537 return ERROR_DOS(ERRDOS,ERRnofiles);
1540 pstrcpy(mask, p);
1541 pstrcpy(directory,conn->dirpath);
1543 /* Get the attr mask from the dptr */
1544 dirtype = dptr_attr(dptr_num);
1546 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1547 dptr_num, mask, dirtype,
1548 (long)conn->dirptr,
1549 TellDir(conn->dirptr)));
1551 /* We don't need to check for VOL here as this is returned by
1552 a different TRANS2 call. */
1554 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1555 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1556 dont_descend = True;
1558 p = pdata;
1559 space_remaining = max_data_bytes;
1560 out_of_space = False;
1563 * Seek to the correct position. We no longer use the resume key but
1564 * depend on the last file name instead.
1567 if(requires_resume_key && *resume_name && !continue_bit) {
1570 * Fix for NT redirector problem triggered by resume key indexes
1571 * changing between directory scans. We now return a resume key of 0
1572 * and instead look for the filename to continue from (also given
1573 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1574 * findfirst/findnext (as is usual) then the directory pointer
1575 * should already be at the correct place. Check this by scanning
1576 * backwards looking for an exact (ie. case sensitive) filename match.
1577 * If we get to the beginning of the directory and haven't found it then scan
1578 * forwards again looking for a match. JRA.
1581 int current_pos, start_pos;
1582 const char *dname = NULL;
1583 pstring dname_pstring;
1584 void *dirptr = conn->dirptr;
1585 start_pos = TellDir(dirptr);
1586 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1587 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1589 SeekDir(dirptr, current_pos);
1590 dname = ReadDirName(dirptr);
1591 if (dname) {
1593 * Remember, mangle_map is called by
1594 * get_lanman2_dir_entry(), so the resume name
1595 * could be mangled. Ensure we do the same
1596 * here.
1599 /* make sure we get a copy that mangle_map can modify */
1601 pstrcpy(dname_pstring, dname);
1602 mangle_map( dname_pstring, False, True, SNUM(conn));
1604 if(strcsequal( resume_name, dname_pstring)) {
1605 SeekDir(dirptr, current_pos+1);
1606 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1607 break;
1613 * Scan forward from start if not found going backwards.
1616 if(current_pos < 0) {
1617 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1618 SeekDir(dirptr, start_pos);
1619 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1622 * Remember, mangle_map is called by
1623 * get_lanman2_dir_entry(), so the resume name
1624 * could be mangled. Ensure we do the same
1625 * here.
1628 if(dname) {
1629 /* make sure we get a copy that mangle_map can modify */
1631 pstrcpy(dname_pstring, dname);
1632 mangle_map(dname_pstring, False, True, SNUM(conn));
1634 if(strcsequal( resume_name, dname_pstring)) {
1635 SeekDir(dirptr, current_pos+1);
1636 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1637 break;
1640 } /* end for */
1641 } /* end if current_pos */
1642 } /* end if requires_resume_key && !continue_bit */
1644 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1645 BOOL got_exact_match = False;
1647 /* this is a heuristic to avoid seeking the dirptr except when
1648 absolutely necessary. It allows for a filename of about 40 chars */
1649 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1650 out_of_space = True;
1651 finished = False;
1652 } else {
1653 finished = !get_lanman2_dir_entry(conn,
1654 inbuf, outbuf,
1655 mask,dirtype,info_level,
1656 requires_resume_key,dont_descend,
1657 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1658 &last_name_off);
1661 if (finished && out_of_space)
1662 finished = False;
1664 if (!finished && !out_of_space)
1665 numentries++;
1668 * As an optimisation if we know we aren't looking
1669 * for a wildcard name (ie. the name matches the wildcard exactly)
1670 * then we can finish on any (first) match.
1671 * This speeds up large directory searches. JRA.
1674 if(got_exact_match)
1675 finished = True;
1677 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1680 /* Check if we can close the dirptr */
1681 if(close_after_request || (finished && close_if_end)) {
1682 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1683 dptr_close(&dptr_num); /* This frees up the saved mask */
1686 /* Set up the return parameter block */
1687 SSVAL(params,0,numentries);
1688 SSVAL(params,2,finished);
1689 SSVAL(params,4,0); /* Never an EA error */
1690 SSVAL(params,6,last_name_off);
1692 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1694 if ((! *directory) && dptr_path(dptr_num))
1695 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1697 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1698 smb_fn_name(CVAL(inbuf,smb_com)),
1699 mask, directory, dirtype, numentries ) );
1701 return(-1);
1704 /****************************************************************************
1705 Reply to a TRANS2_QFSINFO (query filesystem info).
1706 ****************************************************************************/
1708 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1709 int length, int bufsize,
1710 char **pparams, int total_params, char **ppdata, int total_data)
1712 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1713 char *pdata = *ppdata;
1714 char *params = *pparams;
1715 uint16 info_level = SVAL(params,0);
1716 int data_len, len;
1717 SMB_STRUCT_STAT st;
1718 char *vname = volume_label(SNUM(conn));
1719 int snum = SNUM(conn);
1720 char *fstype = lp_fstype(SNUM(conn));
1721 int quota_flag = 0;
1723 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1725 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1726 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1727 return ERROR_DOS(ERRSRV,ERRinvdevice);
1730 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1731 if ( pdata == NULL )
1732 return ERROR_DOS(ERRDOS,ERRnomem);
1734 *ppdata = pdata;
1735 memset((char *)pdata,'\0',max_data_bytes + 1024);
1737 switch (info_level) {
1738 case SMB_INFO_ALLOCATION:
1740 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1741 data_len = 18;
1742 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1743 block_size = lp_block_size(snum);
1744 if (bsize < block_size) {
1745 SMB_BIG_UINT factor = block_size/bsize;
1746 bsize = block_size;
1747 dsize /= factor;
1748 dfree /= factor;
1750 if (bsize > block_size) {
1751 SMB_BIG_UINT factor = bsize/block_size;
1752 bsize = block_size;
1753 dsize *= factor;
1754 dfree *= factor;
1756 bytes_per_sector = 512;
1757 sectors_per_unit = bsize/bytes_per_sector;
1759 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1760 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1761 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1763 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1764 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1765 SIVAL(pdata,l1_cUnit,dsize);
1766 SIVAL(pdata,l1_cUnitAvail,dfree);
1767 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1768 break;
1771 case SMB_INFO_VOLUME:
1772 /* Return volume name */
1774 * Add volume serial number - hash of a combination of
1775 * the called hostname and the service name.
1777 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1778 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1779 SCVAL(pdata,l2_vol_cch,len);
1780 data_len = l2_vol_szVolLabel + len;
1781 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1782 (unsigned)st.st_ctime, len, vname));
1783 break;
1785 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1786 case SMB_FS_ATTRIBUTE_INFORMATION:
1789 #if defined(HAVE_SYS_QUOTAS)
1790 quota_flag = FILE_VOLUME_QUOTAS;
1791 #endif
1793 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1794 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1795 quota_flag); /* FS ATTRIBUTES */
1797 SIVAL(pdata,4,255); /* Max filename component length */
1798 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1799 and will think we can't do long filenames */
1800 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1801 SIVAL(pdata,8,len);
1802 data_len = 12 + len;
1803 break;
1805 case SMB_QUERY_FS_LABEL_INFO:
1806 case SMB_FS_LABEL_INFORMATION:
1807 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1808 data_len = 4 + len;
1809 SIVAL(pdata,0,len);
1810 break;
1812 case SMB_QUERY_FS_VOLUME_INFO:
1813 case SMB_FS_VOLUME_INFORMATION:
1816 * Add volume serial number - hash of a combination of
1817 * the called hostname and the service name.
1819 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1820 (str_checksum(local_machine)<<16));
1822 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1823 SIVAL(pdata,12,len);
1824 data_len = 18+len;
1825 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1826 (int)strlen(vname),vname, lp_servicename(snum)));
1827 break;
1829 case SMB_QUERY_FS_SIZE_INFO:
1830 case SMB_FS_SIZE_INFORMATION:
1832 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1833 data_len = 24;
1834 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1835 block_size = lp_block_size(snum);
1836 if (bsize < block_size) {
1837 SMB_BIG_UINT factor = block_size/bsize;
1838 bsize = block_size;
1839 dsize /= factor;
1840 dfree /= factor;
1842 if (bsize > block_size) {
1843 SMB_BIG_UINT factor = bsize/block_size;
1844 bsize = block_size;
1845 dsize *= factor;
1846 dfree *= factor;
1848 bytes_per_sector = 512;
1849 sectors_per_unit = bsize/bytes_per_sector;
1850 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1851 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1852 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1853 SBIG_UINT(pdata,0,dsize);
1854 SBIG_UINT(pdata,8,dfree);
1855 SIVAL(pdata,16,sectors_per_unit);
1856 SIVAL(pdata,20,bytes_per_sector);
1857 break;
1860 case SMB_FS_FULL_SIZE_INFORMATION:
1862 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1863 data_len = 32;
1864 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1865 block_size = lp_block_size(snum);
1866 if (bsize < block_size) {
1867 SMB_BIG_UINT factor = block_size/bsize;
1868 bsize = block_size;
1869 dsize /= factor;
1870 dfree /= factor;
1872 if (bsize > block_size) {
1873 SMB_BIG_UINT factor = bsize/block_size;
1874 bsize = block_size;
1875 dsize *= factor;
1876 dfree *= factor;
1878 bytes_per_sector = 512;
1879 sectors_per_unit = bsize/bytes_per_sector;
1880 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1881 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1882 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1883 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1884 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1885 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1886 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1887 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1888 break;
1891 case SMB_QUERY_FS_DEVICE_INFO:
1892 case SMB_FS_DEVICE_INFORMATION:
1893 data_len = 8;
1894 SIVAL(pdata,0,0); /* dev type */
1895 SIVAL(pdata,4,0); /* characteristics */
1896 break;
1898 #ifdef HAVE_SYS_QUOTAS
1899 case SMB_FS_QUOTA_INFORMATION:
1901 * what we have to send --metze:
1903 * Unknown1: 24 NULL bytes
1904 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1905 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1906 * Quota Flags: 2 byte :
1907 * Unknown3: 6 NULL bytes
1909 * 48 bytes total
1911 * details for Quota Flags:
1913 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1914 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1915 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1916 * 0x0001 Enable Quotas: enable quota for this fs
1920 /* we need to fake up a fsp here,
1921 * because its not send in this call
1923 files_struct fsp;
1924 SMB_NTQUOTA_STRUCT quotas;
1926 ZERO_STRUCT(fsp);
1927 ZERO_STRUCT(quotas);
1929 fsp.conn = conn;
1930 fsp.fnum = -1;
1931 fsp.fd = -1;
1933 /* access check */
1934 if (conn->admin_user != True) {
1935 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1936 lp_servicename(SNUM(conn)),conn->user));
1937 return ERROR_DOS(ERRDOS,ERRnoaccess);
1940 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1941 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1942 return ERROR_DOS(ERRSRV,ERRerror);
1945 data_len = 48;
1947 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1949 /* Unknown1 24 NULL bytes*/
1950 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1951 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1952 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1954 /* Default Soft Quota 8 bytes */
1955 SBIG_UINT(pdata,24,quotas.softlim);
1957 /* Default Hard Quota 8 bytes */
1958 SBIG_UINT(pdata,32,quotas.hardlim);
1960 /* Quota flag 2 bytes */
1961 SSVAL(pdata,40,quotas.qflags);
1963 /* Unknown3 6 NULL bytes */
1964 SSVAL(pdata,42,0);
1965 SIVAL(pdata,44,0);
1967 break;
1969 #endif /* HAVE_SYS_QUOTAS */
1970 case SMB_FS_OBJECTID_INFORMATION:
1971 data_len = 64;
1972 break;
1975 * Query the version and capabilities of the CIFS UNIX extensions
1976 * in use.
1979 case SMB_QUERY_CIFS_UNIX_INFO:
1980 if (!lp_unix_extensions())
1981 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1982 data_len = 12;
1983 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1984 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1985 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1986 break;
1988 case SMB_MAC_QUERY_FS_INFO:
1990 * Thursby MAC extension... ONLY on NTFS filesystems
1991 * once we do streams then we don't need this
1993 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1994 data_len = 88;
1995 SIVAL(pdata,84,0x100); /* Don't support mac... */
1996 break;
1998 /* drop through */
1999 default:
2000 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2004 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2006 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2008 return -1;
2011 #ifdef HAVE_SYS_QUOTAS
2012 /****************************************************************************
2013 Reply to a TRANS2_SETFSINFO (set filesystem info).
2014 ****************************************************************************/
2016 static int call_trans2setfsinfo(connection_struct *conn,
2017 char *inbuf, char *outbuf, int length, int bufsize,
2018 char **pparams, int total_params, char **ppdata, int total_data)
2020 char *pdata = *ppdata;
2021 char *params = *pparams;
2022 files_struct *fsp = NULL;
2023 uint16 info_level;
2024 int outsize;
2025 SMB_NTQUOTA_STRUCT quotas;
2027 ZERO_STRUCT(quotas);
2029 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2031 /* access check */
2032 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
2033 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2034 lp_servicename(SNUM(conn)),conn->user));
2035 return ERROR_DOS(ERRSRV,ERRaccess);
2038 /* */
2039 if (total_params < 4) {
2040 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2041 total_params));
2042 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2045 fsp = file_fsp(params,0);
2047 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2048 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2049 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2052 info_level = SVAL(params,2);
2054 switch(info_level) {
2055 case SMB_FS_QUOTA_INFORMATION:
2056 /* note: normaly there're 48 bytes,
2057 * but we didn't use the last 6 bytes for now
2058 * --metze
2060 if (total_data < 42) {
2061 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2062 total_data));
2063 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2066 /* unknown_1 24 NULL bytes in pdata*/
2068 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2069 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2070 #ifdef LARGE_SMB_OFF_T
2071 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2072 #else /* LARGE_SMB_OFF_T */
2073 if ((IVAL(pdata,28) != 0)&&
2074 ((quotas.softlim != 0xFFFFFFFF)||
2075 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2076 /* more than 32 bits? */
2077 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2079 #endif /* LARGE_SMB_OFF_T */
2081 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2082 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2083 #ifdef LARGE_SMB_OFF_T
2084 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2085 #else /* LARGE_SMB_OFF_T */
2086 if ((IVAL(pdata,36) != 0)&&
2087 ((quotas.hardlim != 0xFFFFFFFF)||
2088 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2089 /* more than 32 bits? */
2090 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2092 #endif /* LARGE_SMB_OFF_T */
2094 /* quota_flags 2 bytes **/
2095 quotas.qflags = SVAL(pdata,40);
2097 /* unknown_2 6 NULL bytes follow*/
2099 /* now set the quotas */
2100 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2101 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2102 return ERROR_DOS(ERRSRV,ERRerror);
2105 break;
2106 default:
2107 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2108 info_level));
2109 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2110 break;
2114 * sending this reply works fine,
2115 * but I'm not sure it's the same
2116 * like windows do...
2117 * --metze
2119 outsize = set_message(outbuf,10,0,True);
2121 return outsize;
2123 #endif /* HAVE_SYS_QUOTAS */
2125 /****************************************************************************
2126 * Utility function to set bad path error.
2127 ****************************************************************************/
2129 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2131 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2132 err, (int)bad_path ));
2134 if(err == ENOENT) {
2135 if (bad_path) {
2136 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2137 } else {
2138 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2141 return UNIXERROR(def_class,def_code);
2144 /****************************************************************************
2145 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2146 file name or file id).
2147 ****************************************************************************/
2149 static int call_trans2qfilepathinfo(connection_struct *conn,
2150 char *inbuf, char *outbuf, int length,
2151 int bufsize,
2152 char **pparams, int total_params, char **ppdata, int total_data)
2154 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2155 char *params = *pparams;
2156 char *pdata = *ppdata;
2157 uint16 tran_call = SVAL(inbuf, smb_setup0);
2158 uint16 info_level;
2159 int mode=0;
2160 SMB_OFF_T file_size=0;
2161 SMB_BIG_UINT allocation_size=0;
2162 unsigned int data_size;
2163 unsigned int param_size = 2;
2164 SMB_STRUCT_STAT sbuf;
2165 pstring fname, dos_fname;
2166 char *fullpathname;
2167 char *base_name;
2168 char *p;
2169 SMB_OFF_T pos = 0;
2170 BOOL bad_path = False;
2171 BOOL delete_pending = False;
2172 int len;
2173 time_t c_time;
2174 files_struct *fsp = NULL;
2175 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2177 if (!params)
2178 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2180 if (tran_call == TRANSACT2_QFILEINFO) {
2181 if (total_params < 4)
2182 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2184 fsp = file_fsp(params,0);
2185 info_level = SVAL(params,2);
2187 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2189 if(fsp && (fsp->fake_file_handle)) {
2191 * This is actually for the QUOTA_FAKE_FILE --metze
2194 pstrcpy(fname, fsp->fsp_name);
2195 unix_convert(fname,conn,0,&bad_path,&sbuf);
2196 if (!check_name(fname,conn)) {
2197 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2198 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2201 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2203 * This is actually a QFILEINFO on a directory
2204 * handle (returned from an NT SMB). NT5.0 seems
2205 * to do this call. JRA.
2207 pstrcpy(fname, fsp->fsp_name);
2208 unix_convert(fname,conn,0,&bad_path,&sbuf);
2209 if (!check_name(fname,conn)) {
2210 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2211 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2214 if (INFO_LEVEL_IS_UNIX(info_level)) {
2215 /* Always do lstat for UNIX calls. */
2216 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2217 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2218 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2220 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2221 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2222 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2225 delete_pending = fsp->directory_delete_on_close;
2226 } else {
2228 * Original code - this is an open file.
2230 CHECK_FSP(fsp,conn);
2232 pstrcpy(fname, fsp->fsp_name);
2233 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2234 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2235 return(UNIXERROR(ERRDOS,ERRbadfid));
2237 pos = fsp->position_information;
2238 delete_pending = fsp->delete_on_close;
2239 desired_access = fsp->desired_access;
2241 } else {
2242 NTSTATUS status = NT_STATUS_OK;
2244 /* qpathinfo */
2245 if (total_params < 6)
2246 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2248 info_level = SVAL(params,0);
2250 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2252 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2253 if (!NT_STATUS_IS_OK(status)) {
2254 return ERROR_NT(status);
2257 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2259 unix_convert(fname,conn,0,&bad_path,&sbuf);
2260 if (!check_name(fname,conn)) {
2261 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2262 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2265 if (INFO_LEVEL_IS_UNIX(info_level)) {
2266 /* Always do lstat for UNIX calls. */
2267 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2268 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2269 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2271 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2272 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2273 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2277 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2278 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2280 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2281 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2283 p = strrchr_m(fname,'/');
2284 if (!p)
2285 base_name = fname;
2286 else
2287 base_name = p+1;
2289 mode = dos_mode(conn,fname,&sbuf);
2290 if (!mode)
2291 mode = FILE_ATTRIBUTE_NORMAL;
2293 fullpathname = fname;
2294 file_size = get_file_size(sbuf);
2295 allocation_size = get_allocation_size(fsp,&sbuf);
2296 if (mode & aDIR)
2297 file_size = 0;
2299 params = Realloc(*pparams,2);
2300 if (params == NULL)
2301 return ERROR_DOS(ERRDOS,ERRnomem);
2302 *pparams = params;
2303 memset((char *)params,'\0',2);
2304 data_size = max_data_bytes + 1024;
2305 pdata = Realloc(*ppdata, data_size);
2306 if ( pdata == NULL )
2307 return ERROR_DOS(ERRDOS,ERRnomem);
2308 *ppdata = pdata;
2310 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2311 /* uggh, EAs for OS2 */
2312 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2313 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2316 memset((char *)pdata,'\0',data_size);
2318 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2320 if (lp_dos_filetime_resolution(SNUM(conn))) {
2321 c_time &= ~1;
2322 sbuf.st_atime &= ~1;
2323 sbuf.st_mtime &= ~1;
2324 sbuf.st_mtime &= ~1;
2327 /* NT expects the name to be in an exact form of the *full*
2328 filename. See the trans2 torture test */
2329 if (strequal(base_name,".")) {
2330 pstrcpy(dos_fname, "\\");
2331 } else {
2332 pstr_sprintf(dos_fname, "\\%s", fname);
2333 string_replace(dos_fname, '/', '\\');
2336 switch (info_level) {
2337 case SMB_INFO_STANDARD:
2338 case SMB_INFO_QUERY_EA_SIZE:
2339 data_size = (info_level==1?22:26);
2340 put_dos_date2(pdata,l1_fdateCreation,c_time);
2341 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2342 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2343 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2344 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2345 SSVAL(pdata,l1_attrFile,mode);
2346 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
2347 break;
2349 case SMB_INFO_IS_NAME_VALID:
2350 if (tran_call == TRANSACT2_QFILEINFO) {
2351 /* os/2 needs this ? really ?*/
2352 return ERROR_DOS(ERRDOS,ERRbadfunc);
2354 data_size = 0;
2355 param_size = 0;
2356 break;
2358 case SMB_INFO_QUERY_EAS_FROM_LIST:
2359 data_size = 24;
2360 put_dos_date2(pdata,0,c_time);
2361 put_dos_date2(pdata,4,sbuf.st_atime);
2362 put_dos_date2(pdata,8,sbuf.st_mtime);
2363 SIVAL(pdata,12,(uint32)file_size);
2364 SIVAL(pdata,16,(uint32)allocation_size);
2365 SIVAL(pdata,20,mode);
2366 break;
2368 case SMB_INFO_QUERY_ALL_EAS:
2369 /* We have data_size bytes to put EA's into. */
2370 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2371 break;
2373 case SMB_FILE_BASIC_INFORMATION:
2374 case SMB_QUERY_FILE_BASIC_INFO:
2376 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
2377 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2378 else {
2379 data_size = 40;
2380 SIVAL(pdata,36,0);
2382 put_long_date(pdata,c_time);
2383 put_long_date(pdata+8,sbuf.st_atime);
2384 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2385 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2386 SIVAL(pdata,32,mode);
2388 DEBUG(5,("SMB_QFBI - "));
2390 time_t create_time = c_time;
2391 DEBUG(5,("create: %s ", ctime(&create_time)));
2393 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2394 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2395 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2396 DEBUG(5,("mode: %x\n", mode));
2398 break;
2400 case SMB_FILE_STANDARD_INFORMATION:
2401 case SMB_QUERY_FILE_STANDARD_INFO:
2403 data_size = 24;
2404 SOFF_T(pdata,0,allocation_size);
2405 SOFF_T(pdata,8,file_size);
2406 if (delete_pending & sbuf.st_nlink)
2407 SIVAL(pdata,16,sbuf.st_nlink - 1);
2408 else
2409 SIVAL(pdata,16,sbuf.st_nlink);
2410 SCVAL(pdata,20,0);
2411 SCVAL(pdata,21,(mode&aDIR)?1:0);
2412 break;
2414 case SMB_FILE_EA_INFORMATION:
2415 case SMB_QUERY_FILE_EA_INFO:
2417 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2418 data_size = 4;
2419 SIVAL(pdata,0,ea_size);
2420 break;
2423 /* Get the 8.3 name - used if NT SMB was negotiated. */
2424 case SMB_QUERY_FILE_ALT_NAME_INFO:
2425 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2427 pstring short_name;
2429 pstrcpy(short_name,base_name);
2430 /* Mangle if not already 8.3 */
2431 if(!mangle_is_8_3(short_name, True)) {
2432 mangle_map(short_name,True,True,SNUM(conn));
2434 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2435 data_size = 4 + len;
2436 SIVAL(pdata,0,len);
2437 break;
2440 case SMB_QUERY_FILE_NAME_INFO:
2442 this must be *exactly* right for ACLs on mapped drives to work
2444 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2445 data_size = 4 + len;
2446 SIVAL(pdata,0,len);
2447 break;
2449 case SMB_FILE_ALLOCATION_INFORMATION:
2450 case SMB_QUERY_FILE_ALLOCATION_INFO:
2451 data_size = 8;
2452 SOFF_T(pdata,0,allocation_size);
2453 break;
2455 case SMB_FILE_END_OF_FILE_INFORMATION:
2456 case SMB_QUERY_FILE_END_OF_FILEINFO:
2457 data_size = 8;
2458 SOFF_T(pdata,0,file_size);
2459 break;
2461 case SMB_QUERY_FILE_ALL_INFO:
2462 case SMB_FILE_ALL_INFORMATION:
2463 put_long_date(pdata,c_time);
2464 put_long_date(pdata+8,sbuf.st_atime);
2465 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2466 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2467 SIVAL(pdata,32,mode);
2468 pdata += 40;
2469 SOFF_T(pdata,0,allocation_size);
2470 SOFF_T(pdata,8,file_size);
2471 if (delete_pending && sbuf.st_nlink)
2472 SIVAL(pdata,16,sbuf.st_nlink - 1);
2473 else
2474 SIVAL(pdata,16,sbuf.st_nlink);
2475 SCVAL(pdata,20,delete_pending);
2476 SCVAL(pdata,21,(mode&aDIR)?1:0);
2477 pdata += 24;
2478 pdata += 4; /* EA info */
2479 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2480 SIVAL(pdata,0,len);
2481 pdata += 4 + len;
2482 data_size = PTR_DIFF(pdata,(*ppdata));
2483 break;
2485 case SMB_FILE_INTERNAL_INFORMATION:
2486 /* This should be an index number - looks like
2487 dev/ino to me :-)
2489 I think this causes us to fail the IFSKIT
2490 BasicFileInformationTest. -tpot */
2492 SIVAL(pdata,0,sbuf.st_dev);
2493 SIVAL(pdata,4,sbuf.st_ino);
2494 data_size = 8;
2495 break;
2497 case SMB_FILE_ACCESS_INFORMATION:
2498 SIVAL(pdata,0,desired_access);
2499 data_size = 4;
2500 break;
2502 case SMB_FILE_NAME_INFORMATION:
2503 /* Pathname with leading '\'. */
2505 size_t byte_len;
2506 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2507 SIVAL(pdata,0,byte_len);
2508 data_size = 4 + byte_len;
2509 break;
2512 case SMB_FILE_DISPOSITION_INFORMATION:
2513 data_size = 1;
2514 SCVAL(pdata,0,delete_pending);
2515 break;
2517 case SMB_FILE_POSITION_INFORMATION:
2518 data_size = 8;
2519 SOFF_T(pdata,0,pos);
2520 break;
2522 case SMB_FILE_MODE_INFORMATION:
2523 SIVAL(pdata,0,mode);
2524 data_size = 4;
2525 break;
2527 case SMB_FILE_ALIGNMENT_INFORMATION:
2528 SIVAL(pdata,0,0); /* No alignment needed. */
2529 data_size = 4;
2530 break;
2532 #if 0
2534 * NT4 server just returns "invalid query" to this - if we try to answer
2535 * it then NTws gets a BSOD! (tridge).
2536 * W2K seems to want this. JRA.
2538 case SMB_QUERY_FILE_STREAM_INFO:
2539 #endif
2540 case SMB_FILE_STREAM_INFORMATION:
2541 if (mode & aDIR) {
2542 data_size = 0;
2543 } else {
2544 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2545 SIVAL(pdata,0,0); /* ??? */
2546 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2547 SOFF_T(pdata,8,file_size);
2548 SIVAL(pdata,16,allocation_size);
2549 SIVAL(pdata,20,0); /* ??? */
2550 data_size = 24 + byte_len;
2552 break;
2554 case SMB_QUERY_COMPRESSION_INFO:
2555 case SMB_FILE_COMPRESSION_INFORMATION:
2556 SOFF_T(pdata,0,file_size);
2557 SIVAL(pdata,8,0); /* ??? */
2558 SIVAL(pdata,12,0); /* ??? */
2559 data_size = 16;
2560 break;
2562 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2563 put_long_date(pdata,c_time);
2564 put_long_date(pdata+8,sbuf.st_atime);
2565 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2566 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2567 SIVAL(pdata,32,allocation_size);
2568 SOFF_T(pdata,40,file_size);
2569 SIVAL(pdata,48,mode);
2570 SIVAL(pdata,52,0); /* ??? */
2571 data_size = 56;
2572 break;
2574 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2575 SIVAL(pdata,0,mode);
2576 SIVAL(pdata,4,0);
2577 data_size = 8;
2578 break;
2581 * CIFS UNIX Extensions.
2584 case SMB_QUERY_FILE_UNIX_BASIC:
2586 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2588 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2589 pdata += 8;
2591 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2592 pdata += 8;
2594 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2595 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2596 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2597 pdata += 24;
2599 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2600 SIVAL(pdata,4,0);
2601 pdata += 8;
2603 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2604 SIVAL(pdata,4,0);
2605 pdata += 8;
2607 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2608 pdata += 4;
2610 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2611 SIVAL(pdata,4,0);
2612 pdata += 8;
2614 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2615 SIVAL(pdata,4,0);
2616 pdata += 8;
2618 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2619 pdata += 8;
2621 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2622 SIVAL(pdata,4,0);
2623 pdata += 8;
2625 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2626 SIVAL(pdata,4,0);
2627 pdata += 8+1;
2628 data_size = PTR_DIFF(pdata,(*ppdata));
2631 int i;
2632 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2634 for (i=0; i<100; i++)
2635 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2636 DEBUG(4,("\n"));
2639 break;
2641 case SMB_QUERY_FILE_UNIX_LINK:
2643 pstring buffer;
2645 #ifdef S_ISLNK
2646 if(!S_ISLNK(sbuf.st_mode))
2647 return(UNIXERROR(ERRSRV,ERRbadlink));
2648 #else
2649 return(UNIXERROR(ERRDOS,ERRbadlink));
2650 #endif
2651 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2652 if (len == -1)
2653 return(UNIXERROR(ERRDOS,ERRnoaccess));
2654 buffer[len] = 0;
2655 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2656 pdata += len;
2657 data_size = PTR_DIFF(pdata,(*ppdata));
2659 break;
2662 default:
2663 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2666 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2668 return(-1);
2671 /****************************************************************************
2672 Deal with the internal needs of setting the delete on close flag. Note that
2673 as the tdb locking is recursive, it is safe to call this from within
2674 open_file_shared. JRA.
2675 ****************************************************************************/
2677 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2680 * Only allow delete on close for writable shares.
2683 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2684 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2685 fsp->fsp_name ));
2686 return NT_STATUS_ACCESS_DENIED;
2689 * Only allow delete on close for files/directories opened with delete intent.
2692 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2693 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2694 fsp->fsp_name ));
2695 return NT_STATUS_ACCESS_DENIED;
2698 if(fsp->is_directory) {
2699 fsp->directory_delete_on_close = delete_on_close;
2700 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2701 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2702 } else {
2703 fsp->delete_on_close = delete_on_close;
2704 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2705 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2708 return NT_STATUS_OK;
2711 /****************************************************************************
2712 Sets the delete on close flag over all share modes on this file.
2713 Modify the share mode entry for all files open
2714 on this device and inode to tell other smbds we have
2715 changed the delete on close flag. This will be noticed
2716 in the close code, the last closer will delete the file
2717 if flag is set.
2718 ****************************************************************************/
2720 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2722 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2723 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2725 if (fsp->is_directory || fsp->is_stat)
2726 return NT_STATUS_OK;
2728 if (lock_share_entry_fsp(fsp) == False)
2729 return NT_STATUS_ACCESS_DENIED;
2731 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2732 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2733 fsp->fsp_name ));
2734 unlock_share_entry_fsp(fsp);
2735 return NT_STATUS_ACCESS_DENIED;
2738 unlock_share_entry_fsp(fsp);
2739 return NT_STATUS_OK;
2742 /****************************************************************************
2743 Returns true if this pathname is within the share, and thus safe.
2744 ****************************************************************************/
2746 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2748 #ifdef PATH_MAX
2749 char resolved_name[PATH_MAX+1];
2750 #else
2751 pstring resolved_name;
2752 #endif
2753 fstring last_component;
2754 pstring link_dest;
2755 pstring link_test;
2756 char *p;
2757 BOOL bad_path = False;
2758 SMB_STRUCT_STAT sbuf;
2760 pstrcpy(link_dest, link_dest_in);
2761 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2763 /* Store the UNIX converted path. */
2764 pstrcpy(link_dest_out, link_dest);
2766 p = strrchr(link_dest, '/');
2767 if (p) {
2768 fstrcpy(last_component, p+1);
2769 *p = '\0';
2770 } else {
2771 fstrcpy(last_component, link_dest);
2772 pstrcpy(link_dest, "./");
2775 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2776 return -1;
2778 pstrcpy(link_dest, resolved_name);
2779 pstrcat(link_dest, "/");
2780 pstrcat(link_dest, last_component);
2782 if (*link_dest != '/') {
2783 /* Relative path. */
2784 pstrcpy(link_test, conn->connectpath);
2785 pstrcat(link_test, "/");
2786 pstrcat(link_test, link_dest);
2787 } else {
2788 pstrcpy(link_test, link_dest);
2792 * Check if the link is within the share.
2795 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2796 errno = EACCES;
2797 return -1;
2799 return 0;
2802 /****************************************************************************
2803 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2804 code.
2805 ****************************************************************************/
2807 NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname)
2809 BOOL bad_path_src = False;
2810 BOOL bad_path_dest = False;
2811 SMB_STRUCT_STAT sbuf1, sbuf2;
2812 BOOL rc, rcdest;
2813 pstring last_component_src;
2814 pstring last_component_dest;
2815 NTSTATUS status = NT_STATUS_OK;
2817 ZERO_STRUCT(sbuf1);
2818 ZERO_STRUCT(sbuf2);
2820 /* No wildcards. */
2821 if (ms_has_wild(name) || ms_has_wild(newname)) {
2822 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2825 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
2826 if (!rc && bad_path_src) {
2827 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2830 /* Quick check for "." and ".." */
2831 if (last_component_src[0] == '.') {
2832 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
2833 return NT_STATUS_OBJECT_NAME_INVALID;
2837 /* source must already exist. */
2838 if (!VALID_STAT(sbuf1)) {
2839 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2842 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
2843 if (!rcdest && bad_path_dest) {
2844 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2847 /* Quick check for "." and ".." */
2848 if (last_component_dest[0] == '.') {
2849 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
2850 return NT_STATUS_OBJECT_NAME_INVALID;
2854 /* Disallow if already exists. */
2855 if (VALID_STAT(sbuf2)) {
2856 return NT_STATUS_OBJECT_NAME_COLLISION;
2859 /* No links from a directory. */
2860 if (S_ISDIR(sbuf1.st_mode)) {
2861 return NT_STATUS_FILE_IS_A_DIRECTORY;
2864 if (ensure_link_is_safe(conn, newname, newname) != 0)
2865 return NT_STATUS_ACCESS_DENIED;
2867 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", name, newname ));
2869 if (SMB_VFS_LINK(conn,name,newname) != 0) {
2870 status = map_nt_error_from_unix(errno);
2871 DEBUG(3,("hardlink_internals: Error %s link %s -> %s\n",
2872 nt_errstr(status), name,newname));
2875 return status;
2878 /****************************************************************************
2879 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2880 ****************************************************************************/
2882 static int call_trans2setfilepathinfo(connection_struct *conn,
2883 char *inbuf, char *outbuf, int length, int bufsize,
2884 char **pparams, int total_params, char **ppdata, int total_data)
2886 char *params = *pparams;
2887 char *pdata = *ppdata;
2888 uint16 tran_call = SVAL(inbuf, smb_setup0);
2889 uint16 info_level;
2890 int dosmode=0;
2891 SMB_OFF_T size=0;
2892 struct utimbuf tvs;
2893 SMB_STRUCT_STAT sbuf;
2894 pstring fname;
2895 int fd = -1;
2896 BOOL bad_path = False;
2897 files_struct *fsp = NULL;
2898 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2899 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2900 mode_t unixmode = 0;
2901 NTSTATUS status = NT_STATUS_OK;
2903 if (!params)
2904 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2906 if (tran_call == TRANSACT2_SETFILEINFO) {
2907 if (total_params < 4)
2908 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2910 fsp = file_fsp(params,0);
2911 info_level = SVAL(params,2);
2913 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2915 * This is actually a SETFILEINFO on a directory
2916 * handle (returned from an NT SMB). NT5.0 seems
2917 * to do this call. JRA.
2919 pstrcpy(fname, fsp->fsp_name);
2920 unix_convert(fname,conn,0,&bad_path,&sbuf);
2921 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2922 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2923 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2925 } else if (fsp && fsp->print_file) {
2927 * Doing a DELETE_ON_CLOSE should cancel a print job.
2929 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2930 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2932 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2934 SSVAL(params,0,0);
2935 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2936 return(-1);
2937 } else
2938 return (UNIXERROR(ERRDOS,ERRbadpath));
2939 } else {
2941 * Original code - this is an open file.
2943 CHECK_FSP(fsp,conn);
2945 pstrcpy(fname, fsp->fsp_name);
2946 fd = fsp->fd;
2948 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2949 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2950 return(UNIXERROR(ERRDOS,ERRbadfid));
2953 } else {
2954 /* set path info */
2955 if (total_params < 6)
2956 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2958 info_level = SVAL(params,0);
2959 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2960 if (!NT_STATUS_IS_OK(status)) {
2961 return ERROR_NT(status);
2963 unix_convert(fname,conn,0,&bad_path,&sbuf);
2966 * For CIFS UNIX extensions the target name may not exist.
2969 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2970 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2971 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2974 if(!check_name(fname, conn)) {
2975 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2980 if (!CAN_WRITE(conn))
2981 return ERROR_DOS(ERRSRV,ERRaccess);
2983 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2984 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2986 if (VALID_STAT(sbuf))
2987 unixmode = sbuf.st_mode;
2989 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
2990 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
2992 /* Realloc the parameter and data sizes */
2993 params = Realloc(*pparams,2);
2994 if(params == NULL)
2995 return ERROR_DOS(ERRDOS,ERRnomem);
2996 *pparams = params;
2998 SSVAL(params,0,0);
3000 if (fsp) {
3001 /* the pending modtime overrides the current modtime */
3002 sbuf.st_mtime = fsp->pending_modtime;
3005 size = get_file_size(sbuf);
3006 tvs.modtime = sbuf.st_mtime;
3007 tvs.actime = sbuf.st_atime;
3008 dosmode = dos_mode(conn,fname,&sbuf);
3009 unixmode = sbuf.st_mode;
3011 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3012 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3014 switch (info_level) {
3015 case SMB_INFO_STANDARD:
3017 if (total_data < 12)
3018 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3020 /* access time */
3021 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3022 /* write time */
3023 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3024 break;
3027 case SMB_INFO_SET_EA:
3028 status = set_ea(conn, fsp, fname, pdata, total_data);
3029 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3030 return ERROR_NT(status);
3031 break;
3033 /* XXXX um, i don't think this is right.
3034 it's also not in the cifs6.txt spec.
3036 case SMB_INFO_QUERY_EAS_FROM_LIST:
3037 if (total_data < 28)
3038 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3040 tvs.actime = make_unix_date2(pdata+8);
3041 tvs.modtime = make_unix_date2(pdata+12);
3042 size = IVAL(pdata,16);
3043 dosmode = IVAL(pdata,24);
3044 break;
3046 /* XXXX nor this. not in cifs6.txt, either. */
3047 case SMB_INFO_QUERY_ALL_EAS:
3048 if (total_data < 28)
3049 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3051 tvs.actime = make_unix_date2(pdata+8);
3052 tvs.modtime = make_unix_date2(pdata+12);
3053 size = IVAL(pdata,16);
3054 dosmode = IVAL(pdata,24);
3055 break;
3057 case SMB_SET_FILE_BASIC_INFO:
3058 case SMB_FILE_BASIC_INFORMATION:
3060 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3061 time_t write_time;
3062 time_t changed_time;
3064 if (total_data < 36)
3065 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3067 /* Ignore create time at offset pdata. */
3069 /* access time */
3070 tvs.actime = interpret_long_date(pdata+8);
3072 write_time = interpret_long_date(pdata+16);
3073 changed_time = interpret_long_date(pdata+24);
3075 tvs.modtime = MIN(write_time, changed_time);
3077 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3078 tvs.modtime = write_time;
3080 /* Prefer a defined time to an undefined one. */
3081 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3082 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3083 ? changed_time : write_time);
3085 /* attributes */
3086 dosmode = IVAL(pdata,32);
3087 break;
3090 case SMB_FILE_ALLOCATION_INFORMATION:
3091 case SMB_SET_FILE_ALLOCATION_INFO:
3093 int ret = -1;
3094 SMB_BIG_UINT allocation_size;
3096 if (total_data < 8)
3097 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3099 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3100 #ifdef LARGE_SMB_OFF_T
3101 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3102 #else /* LARGE_SMB_OFF_T */
3103 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3104 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3105 #endif /* LARGE_SMB_OFF_T */
3106 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3107 fname, (double)allocation_size ));
3109 if (allocation_size)
3110 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3112 if(allocation_size != get_file_size(sbuf)) {
3113 SMB_STRUCT_STAT new_sbuf;
3115 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3116 fname, (double)allocation_size ));
3118 if (fd == -1) {
3119 files_struct *new_fsp = NULL;
3120 int access_mode = 0;
3121 int action = 0;
3123 if(global_oplock_break) {
3124 /* Queue this file modify as we are the process of an oplock break. */
3126 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3127 DEBUGADD(2,( "in oplock break state.\n"));
3129 push_oplock_pending_smb_message(inbuf, length);
3130 return -1;
3133 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3134 SET_OPEN_MODE(DOS_OPEN_RDWR),
3135 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3136 0, 0, &access_mode, &action);
3138 if (new_fsp == NULL)
3139 return(UNIXERROR(ERRDOS,ERRbadpath));
3140 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3141 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3142 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3143 new_fsp->fnum, strerror(errno)));
3144 ret = -1;
3146 close_file(new_fsp,True);
3147 } else {
3148 ret = vfs_allocate_file_space(fsp, allocation_size);
3149 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3150 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3151 fsp->fnum, strerror(errno)));
3152 ret = -1;
3155 if (ret == -1)
3156 return ERROR_NT(NT_STATUS_DISK_FULL);
3158 /* Allocate can truncate size... */
3159 size = get_file_size(new_sbuf);
3162 break;
3165 case SMB_FILE_END_OF_FILE_INFORMATION:
3166 case SMB_SET_FILE_END_OF_FILE_INFO:
3168 if (total_data < 8)
3169 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3171 size = IVAL(pdata,0);
3172 #ifdef LARGE_SMB_OFF_T
3173 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3174 #else /* LARGE_SMB_OFF_T */
3175 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3176 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3177 #endif /* LARGE_SMB_OFF_T */
3178 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3179 break;
3182 case SMB_FILE_DISPOSITION_INFORMATION:
3183 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3185 BOOL delete_on_close;
3187 if (total_data < 1)
3188 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3190 delete_on_close = (CVAL(pdata,0) ? True : False);
3192 /* Just ignore this set on a path. */
3193 if (tran_call != TRANSACT2_SETFILEINFO)
3194 break;
3196 if (fsp == NULL)
3197 return(UNIXERROR(ERRDOS,ERRbadfid));
3199 status = set_delete_on_close_internal(fsp, delete_on_close);
3201 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3202 return ERROR_NT(status);
3204 /* The set is across all open files on this dev/inode pair. */
3205 status =set_delete_on_close_over_all(fsp, delete_on_close);
3206 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3207 return ERROR_NT(status);
3209 break;
3212 case SMB_FILE_POSITION_INFORMATION:
3214 SMB_BIG_UINT position_information;
3216 if (total_data < 8)
3217 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3219 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3220 #ifdef LARGE_SMB_OFF_T
3221 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3222 #else /* LARGE_SMB_OFF_T */
3223 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3224 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3225 #endif /* LARGE_SMB_OFF_T */
3226 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3227 fname, (double)position_information ));
3228 if (fsp)
3229 fsp->position_information = position_information;
3230 break;
3234 * CIFS UNIX extensions.
3237 case SMB_SET_FILE_UNIX_BASIC:
3239 uint32 raw_unixmode;
3241 if (total_data < 100)
3242 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3244 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3245 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3246 size=IVAL(pdata,0); /* first 8 Bytes are size */
3247 #ifdef LARGE_SMB_OFF_T
3248 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3249 #else /* LARGE_SMB_OFF_T */
3250 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3251 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3252 #endif /* LARGE_SMB_OFF_T */
3254 pdata+=24; /* ctime & st_blocks are not changed */
3255 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3256 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3257 pdata+=16;
3258 set_owner = (uid_t)IVAL(pdata,0);
3259 pdata += 8;
3260 set_grp = (gid_t)IVAL(pdata,0);
3261 pdata += 8;
3262 raw_unixmode = IVAL(pdata,28);
3263 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3264 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3266 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3267 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3268 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3270 if (!VALID_STAT(sbuf)) {
3273 * The only valid use of this is to create character and block
3274 * devices, and named pipes. This is deprecated (IMHO) and
3275 * a new info level should be used for mknod. JRA.
3278 #if !defined(HAVE_MAKEDEV_FN)
3279 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3280 #else /* HAVE_MAKEDEV_FN */
3281 uint32 file_type = IVAL(pdata,0);
3282 uint32 dev_major = IVAL(pdata,4);
3283 uint32 dev_minor = IVAL(pdata,12);
3285 uid_t myuid = geteuid();
3286 gid_t mygid = getegid();
3287 SMB_DEV_T dev;
3289 if (tran_call == TRANSACT2_SETFILEINFO)
3290 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3292 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3293 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3295 dev = makedev(dev_major, dev_minor);
3297 /* We can only create as the owner/group we are. */
3299 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3300 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3301 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3302 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3304 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3305 file_type != UNIX_TYPE_FIFO)
3306 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3308 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3309 0%o for file %s\n", (double)dev, unixmode, fname ));
3311 /* Ok - do the mknod. */
3312 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3313 return(UNIXERROR(ERRDOS,ERRnoaccess));
3315 inherit_access_acl(conn, fname, unixmode);
3317 SSVAL(params,0,0);
3318 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3319 return(-1);
3320 #endif /* HAVE_MAKEDEV_FN */
3325 * Deal with the UNIX specific mode set.
3328 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3329 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3330 (unsigned int)unixmode, fname ));
3331 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3332 return(UNIXERROR(ERRDOS,ERRnoaccess));
3336 * Deal with the UNIX specific uid set.
3339 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3340 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3341 (unsigned int)set_owner, fname ));
3342 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3343 return(UNIXERROR(ERRDOS,ERRnoaccess));
3347 * Deal with the UNIX specific gid set.
3350 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3351 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3352 (unsigned int)set_owner, fname ));
3353 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3354 return(UNIXERROR(ERRDOS,ERRnoaccess));
3356 break;
3359 case SMB_SET_FILE_UNIX_LINK:
3361 pstring link_dest;
3362 /* Set a symbolic link. */
3363 /* Don't allow this if follow links is false. */
3365 if (!lp_symlinks(SNUM(conn)))
3366 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3368 srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 return ERROR_NT(status);
3373 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
3374 return(UNIXERROR(ERRDOS,ERRnoaccess));
3376 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3377 fname, link_dest ));
3379 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
3380 return(UNIXERROR(ERRDOS,ERRnoaccess));
3381 SSVAL(params,0,0);
3382 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3383 return(-1);
3386 case SMB_SET_FILE_UNIX_HLINK:
3388 pstring link_dest;
3390 /* Set a hard link. */
3391 srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
3392 if (!NT_STATUS_IS_OK(status)) {
3393 return ERROR_NT(status);
3396 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3397 fname, link_dest ));
3399 status = hardlink_internals(conn, fname, link_dest);
3400 if (!NT_STATUS_IS_OK(status)) {
3401 return ERROR_NT(status);
3404 SSVAL(params,0,0);
3405 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3406 return(-1);
3409 case SMB_FILE_RENAME_INFORMATION:
3411 BOOL overwrite;
3412 uint32 root_fid;
3413 uint32 len;
3414 pstring newname;
3415 pstring base_name;
3416 char *p;
3418 if (total_data < 12)
3419 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3421 overwrite = (CVAL(pdata,0) ? True : False);
3422 root_fid = IVAL(pdata,4);
3423 len = IVAL(pdata,8);
3424 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3425 if (!NT_STATUS_IS_OK(status)) {
3426 return ERROR_NT(status);
3429 /* Check the new name has no '/' characters. */
3430 if (strchr_m(newname, '/'))
3431 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3433 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3435 /* Create the base directory. */
3436 pstrcpy(base_name, fname);
3437 p = strrchr_m(base_name, '/');
3438 if (p)
3439 *p = '\0';
3440 /* Append the new name. */
3441 pstrcat(base_name, "/");
3442 pstrcat(base_name, newname);
3444 if (fsp) {
3445 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3446 fsp->fnum, fsp->fsp_name, base_name ));
3447 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3448 } else {
3449 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3450 fname, newname ));
3451 status = rename_internals(conn, fname, base_name, 0, overwrite);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 return ERROR_NT(status);
3456 process_pending_change_notify_queue((time_t)0);
3457 SSVAL(params,0,0);
3458 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3459 return(-1);
3461 default:
3462 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3465 /* get some defaults (no modifications) if any info is zero or -1. */
3466 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3467 tvs.actime = sbuf.st_atime;
3469 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3470 tvs.modtime = sbuf.st_mtime;
3472 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3473 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3474 DEBUG(6,("size: %.0f ", (double)size));
3476 if (dosmode) {
3477 if (S_ISDIR(sbuf.st_mode))
3478 dosmode |= aDIR;
3479 else
3480 dosmode &= ~aDIR;
3483 DEBUG(6,("dosmode: %x\n" , dosmode));
3485 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3486 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3487 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3488 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3491 * Only do this test if we are not explicitly
3492 * changing the size of a file.
3494 if (!size)
3495 size = get_file_size(sbuf);
3499 * Try and set the times, size and mode of this file -
3500 * if they are different from the current values
3502 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3503 if(fsp != NULL) {
3505 * This was a setfileinfo on an open file.
3506 * NT does this a lot. It's actually pointless
3507 * setting the time here, as it will be overwritten
3508 * on the next write, so we save the request
3509 * away and will set it on file close. JRA.
3512 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3513 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3514 fsp->pending_modtime = tvs.modtime;
3517 } else {
3519 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3521 if(file_utime(conn, fname, &tvs)!=0)
3522 return(UNIXERROR(ERRDOS,ERRnoaccess));
3526 /* check the mode isn't different, before changing it */
3527 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3529 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3531 if(file_chmod(conn, fname, dosmode, NULL)) {
3532 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
3533 return(UNIXERROR(ERRDOS,ERRnoaccess));
3537 if (size != get_file_size(sbuf)) {
3539 int ret;
3541 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3542 fname, (double)size ));
3544 if (fd == -1) {
3545 files_struct *new_fsp = NULL;
3546 int access_mode = 0;
3547 int action = 0;
3549 if(global_oplock_break) {
3550 /* Queue this file modify as we are the process of an oplock break. */
3552 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3553 DEBUGADD(2,( "in oplock break state.\n"));
3555 push_oplock_pending_smb_message(inbuf, length);
3556 return -1;
3559 new_fsp = open_file_shared(conn, fname, &sbuf,
3560 SET_OPEN_MODE(DOS_OPEN_RDWR),
3561 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3562 0, 0, &access_mode, &action);
3564 if (new_fsp == NULL)
3565 return(UNIXERROR(ERRDOS,ERRbadpath));
3566 ret = vfs_set_filelen(new_fsp, size);
3567 close_file(new_fsp,True);
3568 } else {
3569 ret = vfs_set_filelen(fsp, size);
3572 if (ret == -1)
3573 return (UNIXERROR(ERRHRD,ERRdiskfull));
3576 SSVAL(params,0,0);
3577 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3579 return(-1);
3582 /****************************************************************************
3583 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3584 ****************************************************************************/
3586 static int call_trans2mkdir(connection_struct *conn,
3587 char *inbuf, char *outbuf, int length, int bufsize,
3588 char **pparams, int total_params, char **ppdata, int total_data)
3590 char *params = *pparams;
3591 pstring directory;
3592 int ret = -1;
3593 SMB_STRUCT_STAT sbuf;
3594 BOOL bad_path = False;
3595 NTSTATUS status = NT_STATUS_OK;
3597 if (!CAN_WRITE(conn))
3598 return ERROR_DOS(ERRSRV,ERRaccess);
3600 if (total_params < 4)
3601 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3603 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 return ERROR_NT(status);
3608 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3610 unix_convert(directory,conn,0,&bad_path,&sbuf);
3611 if (check_name(directory,conn))
3612 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3614 if(ret < 0) {
3615 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3616 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3619 /* Realloc the parameter and data sizes */
3620 params = Realloc(*pparams,2);
3621 if(params == NULL)
3622 return ERROR_DOS(ERRDOS,ERRnomem);
3623 *pparams = params;
3625 SSVAL(params,0,0);
3627 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3629 return(-1);
3632 /****************************************************************************
3633 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3634 We don't actually do this - we just send a null response.
3635 ****************************************************************************/
3637 static int call_trans2findnotifyfirst(connection_struct *conn,
3638 char *inbuf, char *outbuf, int length, int bufsize,
3639 char **pparams, int total_params, char **ppdata, int total_data)
3641 static uint16 fnf_handle = 257;
3642 char *params = *pparams;
3643 uint16 info_level;
3645 if (total_params < 6)
3646 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3648 info_level = SVAL(params,4);
3649 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3651 switch (info_level) {
3652 case 1:
3653 case 2:
3654 break;
3655 default:
3656 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3659 /* Realloc the parameter and data sizes */
3660 params = Realloc(*pparams,6);
3661 if(params == NULL)
3662 return ERROR_DOS(ERRDOS,ERRnomem);
3663 *pparams = params;
3665 SSVAL(params,0,fnf_handle);
3666 SSVAL(params,2,0); /* No changes */
3667 SSVAL(params,4,0); /* No EA errors */
3669 fnf_handle++;
3671 if(fnf_handle == 0)
3672 fnf_handle = 257;
3674 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3676 return(-1);
3679 /****************************************************************************
3680 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3681 changes). Currently this does nothing.
3682 ****************************************************************************/
3684 static int call_trans2findnotifynext(connection_struct *conn,
3685 char *inbuf, char *outbuf, int length, int bufsize,
3686 char **pparams, int total_params, char **ppdata, int total_data)
3688 char *params = *pparams;
3690 DEBUG(3,("call_trans2findnotifynext\n"));
3692 /* Realloc the parameter and data sizes */
3693 params = Realloc(*pparams,4);
3694 if(params == NULL)
3695 return ERROR_DOS(ERRDOS,ERRnomem);
3696 *pparams = params;
3698 SSVAL(params,0,0); /* No changes */
3699 SSVAL(params,2,0); /* No EA errors */
3701 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3703 return(-1);
3706 /****************************************************************************
3707 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3708 ****************************************************************************/
3710 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3711 char* outbuf, int length, int bufsize,
3712 char **pparams, int total_params, char **ppdata, int total_data)
3714 char *params = *pparams;
3715 pstring pathname;
3716 int reply_size = 0;
3717 int max_referral_level;
3719 DEBUG(10,("call_trans2getdfsreferral\n"));
3721 if (total_params < 2)
3722 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3724 max_referral_level = SVAL(params,0);
3726 if(!lp_host_msdfs())
3727 return ERROR_DOS(ERRDOS,ERRbadfunc);
3729 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3730 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3731 return UNIXERROR(ERRDOS,ERRbadfile);
3733 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3734 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3736 return(-1);
3739 #define LMCAT_SPL 0x53
3740 #define LMFUNC_GETJOBID 0x60
3742 /****************************************************************************
3743 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3744 ****************************************************************************/
3746 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3747 char* outbuf, int length, int bufsize,
3748 char **pparams, int total_params, char **ppdata, int total_data)
3750 char *pdata = *ppdata;
3751 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3753 /* check for an invalid fid before proceeding */
3755 if (!fsp)
3756 return(ERROR_DOS(ERRDOS,ERRbadfid));
3758 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3759 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3760 pdata = Realloc(*ppdata, 32);
3761 if(pdata == NULL)
3762 return ERROR_DOS(ERRDOS,ERRnomem);
3763 *ppdata = pdata;
3765 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3766 CAN ACCEPT THIS IN UNICODE. JRA. */
3768 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3769 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3770 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3771 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3772 return(-1);
3773 } else {
3774 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3775 return ERROR_DOS(ERRSRV,ERRerror);
3779 /****************************************************************************
3780 Reply to a SMBfindclose (stop trans2 directory search).
3781 ****************************************************************************/
3783 int reply_findclose(connection_struct *conn,
3784 char *inbuf,char *outbuf,int length,int bufsize)
3786 int outsize = 0;
3787 int dptr_num=SVALS(inbuf,smb_vwv0);
3788 START_PROFILE(SMBfindclose);
3790 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3792 dptr_close(&dptr_num);
3794 outsize = set_message(outbuf,0,0,True);
3796 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3798 END_PROFILE(SMBfindclose);
3799 return(outsize);
3802 /****************************************************************************
3803 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3804 ****************************************************************************/
3806 int reply_findnclose(connection_struct *conn,
3807 char *inbuf,char *outbuf,int length,int bufsize)
3809 int outsize = 0;
3810 int dptr_num= -1;
3811 START_PROFILE(SMBfindnclose);
3813 dptr_num = SVAL(inbuf,smb_vwv0);
3815 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3817 /* We never give out valid handles for a
3818 findnotifyfirst - so any dptr_num is ok here.
3819 Just ignore it. */
3821 outsize = set_message(outbuf,0,0,True);
3823 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3825 END_PROFILE(SMBfindnclose);
3826 return(outsize);
3829 /****************************************************************************
3830 Reply to a SMBtranss2 - just ignore it!
3831 ****************************************************************************/
3833 int reply_transs2(connection_struct *conn,
3834 char *inbuf,char *outbuf,int length,int bufsize)
3836 START_PROFILE(SMBtranss2);
3837 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3838 END_PROFILE(SMBtranss2);
3839 return(-1);
3842 /****************************************************************************
3843 Reply to a SMBtrans2.
3844 ****************************************************************************/
3846 int reply_trans2(connection_struct *conn,
3847 char *inbuf,char *outbuf,int length,int bufsize)
3849 int outsize = 0;
3850 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3851 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3852 #if 0
3853 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3854 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3855 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3856 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3857 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3858 int32 timeout = IVALS(inbuf,smb_timeout);
3859 #endif
3860 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3861 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3862 char *params = NULL, *data = NULL;
3863 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3864 START_PROFILE(SMBtrans2);
3866 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3867 /* Queue this open message as we are the process of an
3868 * oplock break. */
3870 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3871 DEBUGADD(2,( "in oplock break state.\n"));
3873 push_oplock_pending_smb_message(inbuf, length);
3874 END_PROFILE(SMBtrans2);
3875 return -1;
3878 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3879 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3880 END_PROFILE(SMBtrans2);
3881 return ERROR_DOS(ERRSRV,ERRaccess);
3884 outsize = set_message(outbuf,0,0,True);
3886 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3887 is so as a sanity check */
3888 if (suwcnt != 1) {
3890 * Need to have rc=0 for ioctl to get job id for OS/2.
3891 * Network printing will fail if function is not successful.
3892 * Similar function in reply.c will be used if protocol
3893 * is LANMAN1.0 instead of LM1.2X002.
3894 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3895 * outbuf doesn't have to be set(only job id is used).
3897 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3898 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3899 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3900 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3901 } else {
3902 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3903 DEBUG(2,("Transaction is %d\n",tran_call));
3904 END_PROFILE(SMBtrans2);
3905 ERROR_DOS(ERRDOS,ERRinvalidparam);
3909 /* Allocate the space for the maximum needed parameters and data */
3910 if (total_params > 0)
3911 params = (char *)malloc(total_params);
3912 if (total_data > 0)
3913 data = (char *)malloc(total_data);
3915 if ((total_params && !params) || (total_data && !data)) {
3916 DEBUG(2,("Out of memory in reply_trans2\n"));
3917 SAFE_FREE(params);
3918 SAFE_FREE(data);
3919 END_PROFILE(SMBtrans2);
3920 return ERROR_DOS(ERRDOS,ERRnomem);
3923 /* Copy the param and data bytes sent with this request into
3924 the params buffer */
3925 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3926 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3928 if (num_params > total_params || num_data > total_data)
3929 exit_server("invalid params in reply_trans2");
3931 if(params) {
3932 unsigned int psoff = SVAL(inbuf, smb_psoff);
3933 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3934 goto bad_param;
3935 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
3936 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
3937 goto bad_param;
3938 memcpy( params, smb_base(inbuf) + psoff, num_params);
3940 if(data) {
3941 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3942 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3943 goto bad_param;
3944 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
3945 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
3946 goto bad_param;
3947 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3950 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3952 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3953 /* We need to send an interim response then receive the rest
3954 of the parameter/data bytes */
3955 outsize = set_message(outbuf,0,0,True);
3956 srv_signing_trans_stop();
3957 if (!send_smb(smbd_server_fd(),outbuf))
3958 exit_server("reply_trans2: send_smb failed.");
3960 while (num_data_sofar < total_data ||
3961 num_params_sofar < total_params) {
3962 BOOL ret;
3963 unsigned int param_disp;
3964 unsigned int param_off;
3965 unsigned int data_disp;
3966 unsigned int data_off;
3968 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3971 * The sequence number for the trans reply is always
3972 * based on the last secondary received.
3975 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3977 if ((ret &&
3978 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3979 outsize = set_message(outbuf,0,0,True);
3980 if(ret)
3981 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3982 else
3983 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3984 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3985 goto bad_param;
3988 /* Revise total_params and total_data in case
3989 they have changed downwards */
3990 if (SVAL(inbuf, smb_tpscnt) < total_params)
3991 total_params = SVAL(inbuf, smb_tpscnt);
3992 if (SVAL(inbuf, smb_tdscnt) < total_data)
3993 total_data = SVAL(inbuf, smb_tdscnt);
3995 num_params = SVAL(inbuf,smb_spscnt);
3996 param_off = SVAL(inbuf, smb_spsoff);
3997 param_disp = SVAL(inbuf, smb_spsdisp);
3998 num_params_sofar += num_params;
4000 num_data = SVAL(inbuf, smb_sdscnt);
4001 data_off = SVAL(inbuf, smb_sdsoff);
4002 data_disp = SVAL(inbuf, smb_sdsdisp);
4003 num_data_sofar += num_data;
4005 if (num_params_sofar > total_params || num_data_sofar > total_data)
4006 goto bad_param;
4008 if (num_params) {
4009 if (param_disp + num_params >= total_params)
4010 goto bad_param;
4011 if ((param_disp + num_params < param_disp) ||
4012 (param_disp + num_params < num_params))
4013 goto bad_param;
4014 if (param_disp > total_params)
4015 goto bad_param;
4016 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4017 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4018 goto bad_param;
4019 if (params + param_disp < params)
4020 goto bad_param;
4022 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4024 if (num_data) {
4025 if (data_disp + num_data >= total_data)
4026 goto bad_param;
4027 if ((data_disp + num_data < data_disp) ||
4028 (data_disp + num_data < num_data))
4029 goto bad_param;
4030 if (data_disp > total_data)
4031 goto bad_param;
4032 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4033 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4034 goto bad_param;
4035 if (data + data_disp < data)
4036 goto bad_param;
4038 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4043 if (Protocol >= PROTOCOL_NT1) {
4044 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4047 /* Now we must call the relevant TRANS2 function */
4048 switch(tran_call) {
4049 case TRANSACT2_OPEN:
4050 START_PROFILE_NESTED(Trans2_open);
4051 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4052 &params, total_params, &data, total_data);
4053 END_PROFILE_NESTED(Trans2_open);
4054 break;
4056 case TRANSACT2_FINDFIRST:
4057 START_PROFILE_NESTED(Trans2_findfirst);
4058 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4059 &params, total_params, &data, total_data);
4060 END_PROFILE_NESTED(Trans2_findfirst);
4061 break;
4063 case TRANSACT2_FINDNEXT:
4064 START_PROFILE_NESTED(Trans2_findnext);
4065 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4066 &params, total_params, &data, total_data);
4067 END_PROFILE_NESTED(Trans2_findnext);
4068 break;
4070 case TRANSACT2_QFSINFO:
4071 START_PROFILE_NESTED(Trans2_qfsinfo);
4072 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4073 &params, total_params, &data, total_data);
4074 END_PROFILE_NESTED(Trans2_qfsinfo);
4075 break;
4077 #ifdef HAVE_SYS_QUOTAS
4078 case TRANSACT2_SETFSINFO:
4079 START_PROFILE_NESTED(Trans2_setfsinfo);
4080 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4081 &params, total_params, &data, total_data);
4082 END_PROFILE_NESTED(Trans2_setfsinfo);
4083 break;
4084 #endif
4085 case TRANSACT2_QPATHINFO:
4086 case TRANSACT2_QFILEINFO:
4087 START_PROFILE_NESTED(Trans2_qpathinfo);
4088 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4089 &params, total_params, &data, total_data);
4090 END_PROFILE_NESTED(Trans2_qpathinfo);
4091 break;
4092 case TRANSACT2_SETPATHINFO:
4093 case TRANSACT2_SETFILEINFO:
4094 START_PROFILE_NESTED(Trans2_setpathinfo);
4095 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4096 &params, total_params, &data, total_data);
4097 END_PROFILE_NESTED(Trans2_setpathinfo);
4098 break;
4100 case TRANSACT2_FINDNOTIFYFIRST:
4101 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4102 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4103 &params, total_params, &data, total_data);
4104 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4105 break;
4107 case TRANSACT2_FINDNOTIFYNEXT:
4108 START_PROFILE_NESTED(Trans2_findnotifynext);
4109 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4110 &params, total_params, &data, total_data);
4111 END_PROFILE_NESTED(Trans2_findnotifynext);
4112 break;
4113 case TRANSACT2_MKDIR:
4114 START_PROFILE_NESTED(Trans2_mkdir);
4115 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4116 &params, total_params, &data, total_data);
4117 END_PROFILE_NESTED(Trans2_mkdir);
4118 break;
4120 case TRANSACT2_GET_DFS_REFERRAL:
4121 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4122 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4123 &params, total_params, &data, total_data);
4124 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4125 break;
4126 case TRANSACT2_IOCTL:
4127 START_PROFILE_NESTED(Trans2_ioctl);
4128 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4129 &params, total_params, &data, total_data);
4130 END_PROFILE_NESTED(Trans2_ioctl);
4131 break;
4132 default:
4133 /* Error in request */
4134 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4135 SAFE_FREE(params);
4136 SAFE_FREE(data);
4137 END_PROFILE(SMBtrans2);
4138 srv_signing_trans_stop();
4139 return ERROR_DOS(ERRSRV,ERRerror);
4142 /* As we do not know how many data packets will need to be
4143 returned here the various call_trans2xxxx calls
4144 must send their own. Thus a call_trans2xxx routine only
4145 returns a value other than -1 when it wants to send
4146 an error packet.
4149 srv_signing_trans_stop();
4151 SAFE_FREE(params);
4152 SAFE_FREE(data);
4153 END_PROFILE(SMBtrans2);
4154 return outsize; /* If a correct response was needed the
4155 call_trans2xxx calls have already sent
4156 it. If outsize != -1 then it is returning */
4158 bad_param:
4160 srv_signing_trans_stop();
4161 SAFE_FREE(params);
4162 SAFE_FREE(data);
4163 END_PROFILE(SMBtrans2);
4164 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);