r4231: commiting changes to 3.0.10
[Samba/gbeck.git] / source / smbd / trans2.c
blob720ede9c767b346e2a3f18e2443bebefe3e42924
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 int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 /********************************************************************
37 Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
38 Only do this for Windows clients.
39 ********************************************************************/
41 SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
43 /* Only roundup for Windows clients. */
44 enum remote_arch_types ra_type = get_remote_arch();
45 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
46 val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
48 return val;
51 /********************************************************************
52 Given a stat buffer return the allocated size on disk, taking into
53 account sparse files.
54 ********************************************************************/
56 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
58 SMB_BIG_UINT ret;
60 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
61 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
62 #else
63 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
64 #endif
66 if (!ret && fsp && fsp->initial_allocation_size)
67 ret = fsp->initial_allocation_size;
69 ret = smb_roundup(ret);
71 return ret;
74 /****************************************************************************
75 Utility functions for dealing with extended attributes.
76 ****************************************************************************/
78 static const char *prohibited_ea_names[] = {
79 SAMBA_POSIX_INHERITANCE_EA_NAME,
80 SAMBA_XATTR_DOS_ATTRIB,
81 NULL
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static BOOL samba_private_attr_name(const char *unix_ea_name)
90 int i;
92 for (i = 0; prohibited_ea_names[i]; i++) {
93 if (strequal( prohibited_ea_names[i], unix_ea_name))
94 return True;
96 return False;
99 struct ea_list {
100 struct ea_list *next, *prev;
101 struct ea_struct ea;
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
113 char *val = NULL;
114 ssize_t sizeret;
116 again:
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119 if (!val) {
120 return False;
123 if (fsp && fsp->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
125 } else {
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130 attr_size = 65536;
131 goto again;
134 if (sizeret == -1) {
135 return False;
138 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
139 dump_data(10, val, sizeret);
141 pea->flags = 0;
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
144 } else {
145 pea->name = ea_name;
147 pea->value.data = val;
148 pea->value.length = (size_t)sizeret;
149 return True;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
158 /* Get a list of all xattrs. Max namesize is 64k. */
159 size_t ea_namelist_size = 1024;
160 char *ea_namelist;
161 char *p;
162 ssize_t sizeret;
163 int i;
164 struct ea_list *ea_list_head = NULL;
166 *pea_total_len = 0;
168 if (!lp_ea_support(SNUM(conn))) {
169 return NULL;
172 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
173 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
174 if (fsp && fsp->fd != -1) {
175 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176 } else {
177 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
180 if (sizeret == -1 && errno == ERANGE) {
181 ea_namelist_size *= 2;
182 } else {
183 break;
187 if (sizeret == -1)
188 return NULL;
190 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
192 if (sizeret) {
193 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194 struct ea_list *listp, *tmp;
196 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
197 continue;
199 listp = TALLOC_P(mem_ctx, struct ea_list);
200 if (!listp)
201 return NULL;
203 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
204 return NULL;
208 fstring dos_ea_name;
209 push_ascii_fstring(dos_ea_name, listp->ea.name);
210 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
212 *pea_total_len, dos_ea_name,
213 (unsigned int)listp->ea.value.length ));
215 DLIST_ADD_END(ea_list_head, listp, tmp);
217 /* Add on 4 for total length. */
218 if (*pea_total_len) {
219 *pea_total_len += 4;
223 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
224 return ea_list_head;
227 /****************************************************************************
228 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229 that was filled.
230 ****************************************************************************/
232 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
233 connection_struct *conn, files_struct *fsp, const char *fname)
235 unsigned int ret_data_size = 4;
236 char *p = pdata;
237 size_t total_ea_len;
238 TALLOC_CTX *mem_ctx;
239 struct ea_list *ea_list;
241 SMB_ASSERT(total_data_size >= 4);
243 SIVAL(pdata,0,0);
244 if (!lp_ea_support(SNUM(conn))) {
245 return 4;
247 mem_ctx = talloc_init("fill_ea_buffer");
248 if (!mem_ctx) {
249 return 4;
252 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
253 if (!ea_list) {
254 talloc_destroy(mem_ctx);
255 return 4;
258 if (total_ea_len > total_data_size) {
259 talloc_destroy(mem_ctx);
260 return 4;
263 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 size_t dos_namelen;
265 fstring dos_ea_name;
266 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
267 dos_namelen = strlen(dos_ea_name);
268 if (dos_namelen > 255 || dos_namelen == 0) {
269 break;
271 if (ea_list->ea.value.length > 65535) {
272 break;
274 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
275 break;
278 /* We know we have room. */
279 SCVAL(p,0,ea_list->ea.flags);
280 SCVAL(p,1,dos_namelen);
281 SSVAL(p,2,ea_list->ea.value.length);
282 fstrcpy(p+4, dos_ea_name);
283 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
285 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
289 ret_data_size = PTR_DIFF(p, pdata);
290 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
291 ret_data_size, total_ea_len ));
292 talloc_destroy(mem_ctx);
293 SIVAL(pdata,0,ret_data_size);
294 return ret_data_size;
297 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
299 size_t total_ea_len = 0;
300 TALLOC_CTX *mem_ctx = NULL;
302 if (!lp_ea_support(SNUM(conn))) {
303 return 0;
305 mem_ctx = talloc_init("estimate_ea_size");
306 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
307 talloc_destroy(mem_ctx);
308 return total_ea_len;
311 /****************************************************************************
312 Ensure the EA name is case insensitive by matching any existing EA name.
313 ****************************************************************************/
315 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
317 size_t total_ea_len;
318 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
319 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
321 for (; ea_list; ea_list = ea_list->next) {
322 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
323 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
324 &unix_ea_name[5], ea_list->ea.name));
325 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 break;
329 talloc_destroy(mem_ctx);
332 /****************************************************************************
333 Set or delete an extended attribute.
334 ****************************************************************************/
336 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
337 char *pdata, int total_data)
339 unsigned int namelen;
340 unsigned int ealen;
341 int ret;
342 fstring unix_ea_name;
344 if (!lp_ea_support(SNUM(conn))) {
345 return NT_STATUS_EAS_NOT_SUPPORTED;
348 if (total_data < 8) {
349 return NT_STATUS_INVALID_PARAMETER;
352 if (IVAL(pdata,0) > total_data) {
353 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
354 return NT_STATUS_INVALID_PARAMETER;
357 pdata += 4;
358 namelen = CVAL(pdata,1);
359 ealen = SVAL(pdata,2);
360 pdata += 4;
361 if (total_data < 8 + namelen + 1 + ealen) {
362 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
363 (unsigned int)total_data, namelen, ealen));
364 return NT_STATUS_INVALID_PARAMETER;
367 if (pdata[namelen] != '\0') {
368 DEBUG(10,("set_ea: ea name not null terminated\n"));
369 return NT_STATUS_INVALID_PARAMETER;
372 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
373 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
374 pdata += (namelen + 1);
376 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
378 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
379 if (ealen) {
380 DEBUG(10,("set_ea: data :\n"));
381 dump_data(10, pdata, ealen);
384 if (samba_private_attr_name(unix_ea_name)) {
385 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
386 return NT_STATUS_ACCESS_DENIED;
389 if (ealen == 0) {
390 /* Remove the attribute. */
391 if (fsp && (fsp->fd != -1)) {
392 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
393 unix_ea_name, fsp->fsp_name));
394 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
395 } else {
396 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
397 unix_ea_name, fname));
398 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
400 #ifdef ENOATTR
401 /* Removing a non existent attribute always succeeds. */
402 if (ret == -1 && errno == ENOATTR) {
403 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
404 ret = 0;
406 #endif
407 } else {
408 if (fsp && (fsp->fd != -1)) {
409 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
410 unix_ea_name, fsp->fsp_name));
411 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
412 } else {
413 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
414 unix_ea_name, fname));
415 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
419 if (ret == -1) {
420 #ifdef ENOTSUP
421 if (errno == ENOTSUP) {
422 return NT_STATUS_EAS_NOT_SUPPORTED;
424 #endif
425 return map_nt_error_from_unix(errno);
428 return NT_STATUS_OK;
431 /****************************************************************************
432 Send the required number of replies back.
433 We assume all fields other than the data fields are
434 set correctly for the type of call.
435 HACK ! Always assumes smb_setup field is zero.
436 ****************************************************************************/
438 static int send_trans2_replies(char *outbuf,
439 int bufsize,
440 char *params,
441 int paramsize,
442 char *pdata,
443 int datasize)
445 /* As we are using a protocol > LANMAN1 then the max_send
446 variable must have been set in the sessetupX call.
447 This takes precedence over the max_xmit field in the
448 global struct. These different max_xmit variables should
449 be merged as this is now too confusing */
451 extern int max_send;
452 int data_to_send = datasize;
453 int params_to_send = paramsize;
454 int useable_space;
455 char *pp = params;
456 char *pd = pdata;
457 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
458 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
459 int data_alignment_offset = 0;
461 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
463 set_message(outbuf,10,0,True);
465 /* If there genuinely are no parameters or data to send just send the empty packet */
467 if(params_to_send == 0 && data_to_send == 0) {
468 if (!send_smb(smbd_server_fd(),outbuf))
469 exit_server("send_trans2_replies: send_smb failed.");
470 return 0;
473 /* When sending params and data ensure that both are nicely aligned */
474 /* Only do this alignment when there is also data to send - else
475 can cause NT redirector problems. */
477 if (((params_to_send % 4) != 0) && (data_to_send != 0))
478 data_alignment_offset = 4 - (params_to_send % 4);
480 /* Space is bufsize minus Netbios over TCP header minus SMB header */
481 /* The alignment_offset is to align the param bytes on an even byte
482 boundary. NT 4.0 Beta needs this to work correctly. */
484 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
486 /* useable_space can never be more than max_send minus the alignment offset. */
488 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
490 while (params_to_send || data_to_send) {
491 /* Calculate whether we will totally or partially fill this packet */
493 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
495 /* We can never send more than useable_space */
497 * Note that 'useable_space' does not include the alignment offsets,
498 * but we must include the alignment offsets in the calculation of
499 * the length of the data we send over the wire, as the alignment offsets
500 * are sent here. Fix from Marc_Jacobsen@hp.com.
503 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
505 set_message(outbuf, 10, total_sent_thistime, True);
507 /* Set total params and data to be sent */
508 SSVAL(outbuf,smb_tprcnt,paramsize);
509 SSVAL(outbuf,smb_tdrcnt,datasize);
511 /* Calculate how many parameters and data we can fit into
512 * this packet. Parameters get precedence
515 params_sent_thistime = MIN(params_to_send,useable_space);
516 data_sent_thistime = useable_space - params_sent_thistime;
517 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
519 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
521 /* smb_proff is the offset from the start of the SMB header to the
522 parameter bytes, however the first 4 bytes of outbuf are
523 the Netbios over TCP header. Thus use smb_base() to subtract
524 them from the calculation */
526 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
528 if(params_sent_thistime == 0)
529 SSVAL(outbuf,smb_prdisp,0);
530 else
531 /* Absolute displacement of param bytes sent in this packet */
532 SSVAL(outbuf,smb_prdisp,pp - params);
534 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
535 if(data_sent_thistime == 0) {
536 SSVAL(outbuf,smb_droff,0);
537 SSVAL(outbuf,smb_drdisp, 0);
538 } else {
539 /* The offset of the data bytes is the offset of the
540 parameter bytes plus the number of parameters being sent this time */
541 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
542 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
543 SSVAL(outbuf,smb_drdisp, pd - pdata);
546 /* Copy the param bytes into the packet */
548 if(params_sent_thistime)
549 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
551 /* Copy in the data bytes */
552 if(data_sent_thistime)
553 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
554 data_alignment_offset,pd,data_sent_thistime);
556 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
557 params_sent_thistime, data_sent_thistime, useable_space));
558 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
559 params_to_send, data_to_send, paramsize, datasize));
561 /* Send the packet */
562 if (!send_smb(smbd_server_fd(),outbuf))
563 exit_server("send_trans2_replies: send_smb failed.");
565 pp += params_sent_thistime;
566 pd += data_sent_thistime;
568 params_to_send -= params_sent_thistime;
569 data_to_send -= data_sent_thistime;
571 /* Sanity check */
572 if(params_to_send < 0 || data_to_send < 0) {
573 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
574 params_to_send, data_to_send));
575 return -1;
579 return 0;
582 /****************************************************************************
583 Reply to a TRANSACT2_OPEN.
584 ****************************************************************************/
586 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
587 char **pparams, int total_params, char **ppdata, int total_data)
589 char *params = *pparams;
590 int16 open_mode;
591 int16 open_attr;
592 BOOL oplock_request;
593 #if 0
594 BOOL return_additional_info;
595 int16 open_sattr;
596 time_t open_time;
597 #endif
598 int16 open_ofun;
599 int32 open_size;
600 char *pname;
601 pstring fname;
602 SMB_OFF_T size=0;
603 int fmode=0,mtime=0,rmode;
604 SMB_INO_T inode = 0;
605 SMB_STRUCT_STAT sbuf;
606 int smb_action = 0;
607 BOOL bad_path = False;
608 files_struct *fsp;
609 NTSTATUS status;
612 * Ensure we have enough parameters to perform the operation.
615 if (total_params < 29)
616 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
618 open_mode = SVAL(params, 2);
619 open_attr = SVAL(params,6);
620 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
621 #if 0
622 return_additional_info = BITSETW(params,0);
623 open_sattr = SVAL(params, 4);
624 open_time = make_unix_date3(params+8);
625 #endif
626 open_ofun = SVAL(params,12);
627 open_size = IVAL(params,14);
628 pname = &params[28];
630 if (IS_IPC(conn))
631 return(ERROR_DOS(ERRSRV,ERRaccess));
633 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
634 if (!NT_STATUS_IS_OK(status)) {
635 return ERROR_NT(status);
638 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
639 fname,open_mode, open_attr, open_ofun, open_size));
641 /* XXXX we need to handle passed times, sattr and flags */
643 unix_convert(fname,conn,0,&bad_path,&sbuf);
644 if (bad_path) {
645 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
648 if (!check_name(fname,conn)) {
649 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
652 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
653 oplock_request, &rmode,&smb_action);
655 if (!fsp) {
656 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
657 /* We have re-scheduled this call. */
658 clear_cached_errors();
659 return -1;
661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
664 size = get_file_size(sbuf);
665 fmode = dos_mode(conn,fname,&sbuf);
666 mtime = sbuf.st_mtime;
667 inode = sbuf.st_ino;
668 if (fmode & aDIR) {
669 close_file(fsp,False);
670 return(ERROR_DOS(ERRDOS,ERRnoaccess));
673 /* Realloc the size of parameters and data we will return */
674 params = SMB_REALLOC(*pparams, 28);
675 if( params == NULL )
676 return(ERROR_DOS(ERRDOS,ERRnomem));
677 *pparams = params;
679 memset((char *)params,'\0',28);
680 SSVAL(params,0,fsp->fnum);
681 SSVAL(params,2,fmode);
682 put_dos_date2(params,4, mtime);
683 SIVAL(params,8, (uint32)size);
684 SSVAL(params,12,rmode);
686 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
687 smb_action |= EXTENDED_OPLOCK_GRANTED;
689 SSVAL(params,18,smb_action);
692 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
694 SIVAL(params,20,inode);
696 /* Send the required number of replies */
697 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
699 return -1;
702 /*********************************************************
703 Routine to check if a given string matches exactly.
704 as a special case a mask of "." does NOT match. That
705 is required for correct wildcard semantics
706 Case can be significant or not.
707 **********************************************************/
709 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
711 if (mask[0] == '.' && mask[1] == 0)
712 return False;
713 if (case_sig)
714 return strcmp(str,mask)==0;
715 if (StrCaseCmp(str,mask) != 0) {
716 return False;
718 if (ms_has_wild(str)) {
719 return False;
721 return True;
724 /****************************************************************************
725 Return the filetype for UNIX extensions.
726 ****************************************************************************/
728 static uint32 unix_filetype(mode_t mode)
730 if(S_ISREG(mode))
731 return UNIX_TYPE_FILE;
732 else if(S_ISDIR(mode))
733 return UNIX_TYPE_DIR;
734 #ifdef S_ISLNK
735 else if(S_ISLNK(mode))
736 return UNIX_TYPE_SYMLINK;
737 #endif
738 #ifdef S_ISCHR
739 else if(S_ISCHR(mode))
740 return UNIX_TYPE_CHARDEV;
741 #endif
742 #ifdef S_ISBLK
743 else if(S_ISBLK(mode))
744 return UNIX_TYPE_BLKDEV;
745 #endif
746 #ifdef S_ISFIFO
747 else if(S_ISFIFO(mode))
748 return UNIX_TYPE_FIFO;
749 #endif
750 #ifdef S_ISSOCK
751 else if(S_ISSOCK(mode))
752 return UNIX_TYPE_SOCKET;
753 #endif
755 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
756 return UNIX_TYPE_UNKNOWN;
759 /****************************************************************************
760 Map wire perms onto standard UNIX permissions. Obey share restrictions.
761 ****************************************************************************/
763 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
765 mode_t ret = 0;
767 if (perms == SMB_MODE_NO_CHANGE)
768 return pst->st_mode;
770 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
771 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
772 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
773 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
774 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
775 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
776 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
777 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
778 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
779 #ifdef S_ISVTX
780 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
781 #endif
782 #ifdef S_ISGID
783 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
784 #endif
785 #ifdef S_ISUID
786 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
787 #endif
789 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
790 ret &= lp_dir_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_dir_mode(SNUM(conn));
793 } else {
794 /* Apply mode mask */
795 ret &= lp_create_mask(SNUM(conn));
796 /* Add in force bits */
797 ret |= lp_force_create_mode(SNUM(conn));
800 return ret;
803 /****************************************************************************
804 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
805 ****************************************************************************/
807 time_t interpret_long_unix_date(char *p)
809 DEBUG(10,("interpret_long_unix_date\n"));
810 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
811 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
812 return -1;
813 } else {
814 return interpret_long_date(p);
818 /****************************************************************************
819 Get a level dependent lanman2 dir entry.
820 ****************************************************************************/
822 static BOOL get_lanman2_dir_entry(connection_struct *conn,
823 void *inbuf, void *outbuf,
824 char *path_mask,int dirtype,int info_level,
825 int requires_resume_key,
826 BOOL dont_descend,char **ppdata,
827 char *base_data, int space_remaining,
828 BOOL *out_of_space, BOOL *got_exact_match,
829 int *last_name_off)
831 const char *dname;
832 BOOL found = False;
833 SMB_STRUCT_STAT sbuf;
834 pstring mask;
835 pstring pathreal;
836 pstring fname;
837 char *p, *q, *pdata = *ppdata;
838 uint32 reskey=0;
839 int prev_dirpos=0;
840 int mode=0;
841 SMB_OFF_T file_size = 0;
842 SMB_BIG_UINT allocation_size = 0;
843 uint32 len;
844 time_t mdate=0, adate=0, cdate=0;
845 char *nameptr;
846 BOOL was_8_3;
847 int nt_extmode; /* Used for NT connections instead of mode */
848 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
850 *fname = 0;
851 *out_of_space = False;
852 *got_exact_match = False;
854 if (!conn->dirptr)
855 return(False);
857 p = strrchr_m(path_mask,'/');
858 if(p != NULL) {
859 if(p[1] == '\0')
860 pstrcpy(mask,"*.*");
861 else
862 pstrcpy(mask, p+1);
863 } else
864 pstrcpy(mask, path_mask);
866 while (!found) {
867 BOOL got_match;
869 /* Needed if we run out of space */
870 prev_dirpos = TellDir(conn->dirptr);
871 dname = ReadDirName(conn->dirptr);
874 * Due to bugs in NT client redirectors we are not using
875 * resume keys any more - set them to zero.
876 * Check out the related comments in findfirst/findnext.
877 * JRA.
880 reskey = 0;
882 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
883 (long)conn->dirptr,TellDir(conn->dirptr)));
885 if (!dname)
886 return(False);
888 pstrcpy(fname,dname);
890 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
891 got_match = mask_match(fname, mask, conn->case_sensitive);
893 if(!got_match && !mangle_is_8_3(fname, False)) {
896 * It turns out that NT matches wildcards against
897 * both long *and* short names. This may explain some
898 * of the wildcard wierdness from old DOS clients
899 * that some people have been seeing.... JRA.
902 pstring newname;
903 pstrcpy( newname, fname);
904 mangle_map( newname, True, False, SNUM(conn));
905 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
906 got_match = mask_match(newname, mask, conn->case_sensitive);
909 if(got_match) {
910 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
911 if (dont_descend && !isdots)
912 continue;
914 pstrcpy(pathreal,conn->dirpath);
915 if(needslash)
916 pstrcat(pathreal,"/");
917 pstrcat(pathreal,dname);
919 if (INFO_LEVEL_IS_UNIX(info_level)) {
920 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
921 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
922 pathreal,strerror(errno)));
923 continue;
925 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
927 /* Needed to show the msdfs symlinks as
928 * directories */
930 if(lp_host_msdfs() &&
931 lp_msdfs_root(SNUM(conn)) &&
932 is_msdfs_link(conn, pathreal, NULL, NULL,
933 &sbuf)) {
935 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
936 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
938 } else {
940 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
941 pathreal,strerror(errno)));
942 continue;
946 mode = dos_mode(conn,pathreal,&sbuf);
948 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
949 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
950 continue;
953 file_size = get_file_size(sbuf);
954 allocation_size = get_allocation_size(NULL,&sbuf);
955 mdate = sbuf.st_mtime;
956 adate = sbuf.st_atime;
957 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
959 if (lp_dos_filetime_resolution(SNUM(conn))) {
960 cdate &= ~1;
961 mdate &= ~1;
962 adate &= ~1;
965 if(mode & aDIR)
966 file_size = 0;
968 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
970 found = True;
974 mangle_map(fname,False,True,SNUM(conn));
976 p = pdata;
977 nameptr = p;
979 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
981 switch (info_level) {
982 case SMB_INFO_STANDARD:
983 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
984 if(requires_resume_key) {
985 SIVAL(p,0,reskey);
986 p += 4;
988 put_dos_date2(p,l1_fdateCreation,cdate);
989 put_dos_date2(p,l1_fdateLastAccess,adate);
990 put_dos_date2(p,l1_fdateLastWrite,mdate);
991 SIVAL(p,l1_cbFile,(uint32)file_size);
992 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
993 SSVAL(p,l1_attrFile,mode);
994 p += l1_achName;
995 nameptr = p;
996 p += align_string(outbuf, p, 0);
997 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
998 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
999 if (len > 2) {
1000 SCVAL(nameptr, -1, len - 2);
1001 } else {
1002 SCVAL(nameptr, -1, 0);
1004 } else {
1005 if (len > 1) {
1006 SCVAL(nameptr, -1, len - 1);
1007 } else {
1008 SCVAL(nameptr, -1, 0);
1011 p += len;
1012 break;
1014 case SMB_INFO_QUERY_EA_SIZE:
1015 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1016 if(requires_resume_key) {
1017 SIVAL(p,0,reskey);
1018 p += 4;
1020 put_dos_date2(p,l2_fdateCreation,cdate);
1021 put_dos_date2(p,l2_fdateLastAccess,adate);
1022 put_dos_date2(p,l2_fdateLastWrite,mdate);
1023 SIVAL(p,l2_cbFile,(uint32)file_size);
1024 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1025 SSVAL(p,l2_attrFile,mode);
1027 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1028 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1030 p += l2_achName;
1031 nameptr = p - 1;
1032 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1033 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1034 if (len > 2) {
1035 len -= 2;
1036 } else {
1037 len = 0;
1039 } else {
1040 if (len > 1) {
1041 len -= 1;
1042 } else {
1043 len = 0;
1046 SCVAL(nameptr,0,len);
1047 p += len;
1048 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1049 break;
1051 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1052 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1053 was_8_3 = mangle_is_8_3(fname, True);
1054 p += 4;
1055 SIVAL(p,0,reskey); p += 4;
1056 put_long_date(p,cdate); p += 8;
1057 put_long_date(p,adate); p += 8;
1058 put_long_date(p,mdate); p += 8;
1059 put_long_date(p,mdate); p += 8;
1060 SOFF_T(p,0,file_size); p += 8;
1061 SOFF_T(p,0,allocation_size); p += 8;
1062 SIVAL(p,0,nt_extmode); p += 4;
1063 q = p; p += 4; /* q is placeholder for name length. */
1065 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1066 SIVAL(p,0,ea_size); /* Extended attributes */
1067 p += 4;
1069 /* Clear the short name buffer. This is
1070 * IMPORTANT as not doing so will trigger
1071 * a Win2k client bug. JRA.
1073 memset(p,'\0',26);
1074 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1075 pstring mangled_name;
1076 pstrcpy(mangled_name, fname);
1077 mangle_map(mangled_name,True,True,SNUM(conn));
1078 mangled_name[12] = 0;
1079 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1080 SSVAL(p, 0, len);
1081 } else {
1082 SSVAL(p,0,0);
1083 *(p+2) = 0;
1085 p += 2 + 24;
1086 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1087 SIVAL(q,0,len);
1088 p += len;
1089 len = PTR_DIFF(p, pdata);
1090 len = (len + 3) & ~3;
1091 SIVAL(pdata,0,len);
1092 p = pdata + len;
1093 break;
1095 case SMB_FIND_FILE_DIRECTORY_INFO:
1096 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1097 p += 4;
1098 SIVAL(p,0,reskey); p += 4;
1099 put_long_date(p,cdate); p += 8;
1100 put_long_date(p,adate); p += 8;
1101 put_long_date(p,mdate); p += 8;
1102 put_long_date(p,mdate); p += 8;
1103 SOFF_T(p,0,file_size); p += 8;
1104 SOFF_T(p,0,allocation_size); p += 8;
1105 SIVAL(p,0,nt_extmode); p += 4;
1106 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1107 SIVAL(p,0,len);
1108 p += 4 + len;
1109 len = PTR_DIFF(p, pdata);
1110 len = (len + 3) & ~3;
1111 SIVAL(pdata,0,len);
1112 p = pdata + len;
1113 break;
1115 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1116 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1117 p += 4;
1118 SIVAL(p,0,reskey); p += 4;
1119 put_long_date(p,cdate); p += 8;
1120 put_long_date(p,adate); p += 8;
1121 put_long_date(p,mdate); p += 8;
1122 put_long_date(p,mdate); p += 8;
1123 SOFF_T(p,0,file_size); p += 8;
1124 SOFF_T(p,0,allocation_size); p += 8;
1125 SIVAL(p,0,nt_extmode); p += 4;
1126 q = p; p += 4; /* q is placeholder for name length. */
1128 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1129 SIVAL(p,0,ea_size); /* Extended attributes */
1130 p +=4;
1132 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1133 SIVAL(q, 0, len);
1134 p += len;
1136 len = PTR_DIFF(p, pdata);
1137 len = (len + 3) & ~3;
1138 SIVAL(pdata,0,len);
1139 p = pdata + len;
1140 break;
1142 case SMB_FIND_FILE_NAMES_INFO:
1143 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1144 p += 4;
1145 SIVAL(p,0,reskey); p += 4;
1146 p += 4;
1147 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1148 acl on a dir (tridge) */
1149 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1150 SIVAL(p, -4, len);
1151 p += len;
1152 len = PTR_DIFF(p, pdata);
1153 len = (len + 3) & ~3;
1154 SIVAL(pdata,0,len);
1155 p = pdata + len;
1156 break;
1158 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1159 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1160 p += 4;
1161 SIVAL(p,0,reskey); p += 4;
1162 put_long_date(p,cdate); p += 8;
1163 put_long_date(p,adate); p += 8;
1164 put_long_date(p,mdate); p += 8;
1165 put_long_date(p,mdate); p += 8;
1166 SOFF_T(p,0,file_size); p += 8;
1167 SOFF_T(p,0,allocation_size); p += 8;
1168 SIVAL(p,0,nt_extmode); p += 4;
1169 q = p; p += 4; /* q is placeholder for name length. */
1171 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1172 SIVAL(p,0,ea_size); /* Extended attributes */
1173 p +=4;
1175 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1176 SIVAL(p,0,sbuf.st_dev); p += 4;
1177 SIVAL(p,0,sbuf.st_ino); p += 4;
1178 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1179 SIVAL(q, 0, len);
1180 p += len;
1181 len = PTR_DIFF(p, pdata);
1182 len = (len + 3) & ~3;
1183 SIVAL(pdata,0,len);
1184 p = pdata + len;
1185 break;
1187 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1188 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1189 was_8_3 = mangle_is_8_3(fname, True);
1190 p += 4;
1191 SIVAL(p,0,reskey); p += 4;
1192 put_long_date(p,cdate); p += 8;
1193 put_long_date(p,adate); p += 8;
1194 put_long_date(p,mdate); p += 8;
1195 put_long_date(p,mdate); p += 8;
1196 SOFF_T(p,0,file_size); p += 8;
1197 SOFF_T(p,0,allocation_size); p += 8;
1198 SIVAL(p,0,nt_extmode); p += 4;
1199 q = p; p += 4; /* q is placeholder for name length */
1201 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1202 SIVAL(p,0,ea_size); /* Extended attributes */
1203 p +=4;
1205 /* Clear the short name buffer. This is
1206 * IMPORTANT as not doing so will trigger
1207 * a Win2k client bug. JRA.
1209 memset(p,'\0',26);
1210 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1211 pstring mangled_name;
1212 pstrcpy(mangled_name, fname);
1213 mangle_map(mangled_name,True,True,SNUM(conn));
1214 mangled_name[12] = 0;
1215 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1216 SSVAL(p, 0, len);
1217 } else {
1218 SSVAL(p,0,0);
1219 *(p+2) = 0;
1221 p += 26;
1222 SSVAL(p,0,0); p += 2; /* Reserved ? */
1223 SIVAL(p,0,sbuf.st_dev); p += 4;
1224 SIVAL(p,0,sbuf.st_ino); p += 4;
1225 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1226 SIVAL(q,0,len);
1227 p += len;
1228 len = PTR_DIFF(p, pdata);
1229 len = (len + 3) & ~3;
1230 SIVAL(pdata,0,len);
1231 p = pdata + len;
1232 break;
1234 /* CIFS UNIX Extension. */
1236 case SMB_FIND_FILE_UNIX:
1237 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1238 p+= 4;
1239 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1241 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1242 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1243 p+= 8;
1245 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1246 p+= 8;
1248 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1249 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1250 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1251 p+= 24;
1253 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1254 SIVAL(p,4,0);
1255 p+= 8;
1257 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1258 SIVAL(p,4,0);
1259 p+= 8;
1261 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1262 p+= 4;
1264 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1265 SIVAL(p,4,0);
1266 p+= 8;
1268 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1269 SIVAL(p,4,0);
1270 p+= 8;
1272 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1273 p+= 8;
1275 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1276 SIVAL(p,4,0);
1277 p+= 8;
1279 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1280 SIVAL(p,4,0);
1281 p+= 8;
1283 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1284 p += len;
1286 len = PTR_DIFF(p, pdata);
1287 len = (len + 3) & ~3;
1288 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1289 p = pdata + len;
1290 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1292 break;
1294 default:
1295 return(False);
1299 if (PTR_DIFF(p,pdata) > space_remaining) {
1300 /* Move the dirptr back to prev_dirpos */
1301 SeekDir(conn->dirptr, prev_dirpos);
1302 *out_of_space = True;
1303 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1304 return False; /* Not finished - just out of space */
1307 /* Setup the last_filename pointer, as an offset from base_data */
1308 *last_name_off = PTR_DIFF(nameptr,base_data);
1309 /* Advance the data pointer to the next slot */
1310 *ppdata = p;
1312 return(found);
1315 /****************************************************************************
1316 Reply to a TRANS2_FINDFIRST.
1317 ****************************************************************************/
1319 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1320 char **pparams, int total_params, char **ppdata, int total_data)
1322 /* We must be careful here that we don't return more than the
1323 allowed number of data bytes. If this means returning fewer than
1324 maxentries then so be it. We assume that the redirector has
1325 enough room for the fixed number of parameter bytes it has
1326 requested. */
1327 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1328 char *params = *pparams;
1329 char *pdata = *ppdata;
1330 int dirtype = SVAL(params,0);
1331 int maxentries = SVAL(params,2);
1332 BOOL close_after_first = BITSETW(params+4,0);
1333 BOOL close_if_end = BITSETW(params+4,1);
1334 BOOL requires_resume_key = BITSETW(params+4,2);
1335 int info_level = SVAL(params,6);
1336 pstring directory;
1337 pstring mask;
1338 char *p, *wcard;
1339 int last_name_off=0;
1340 int dptr_num = -1;
1341 int numentries = 0;
1342 int i;
1343 BOOL finished = False;
1344 BOOL dont_descend = False;
1345 BOOL out_of_space = False;
1346 int space_remaining;
1347 BOOL bad_path = False;
1348 SMB_STRUCT_STAT sbuf;
1349 NTSTATUS ntstatus = NT_STATUS_OK;
1351 if (total_params < 12)
1352 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1354 *directory = *mask = 0;
1356 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1357 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1358 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1359 info_level, max_data_bytes));
1361 if (!maxentries) {
1362 /* W2K3 seems to treat zero as 1. */
1363 maxentries = 1;
1366 switch (info_level) {
1367 case SMB_INFO_STANDARD:
1368 case SMB_INFO_QUERY_EA_SIZE:
1369 case SMB_FIND_FILE_DIRECTORY_INFO:
1370 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1371 case SMB_FIND_FILE_NAMES_INFO:
1372 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1373 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1374 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1375 break;
1376 case SMB_FIND_FILE_UNIX:
1377 if (!lp_unix_extensions())
1378 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1379 break;
1380 default:
1381 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1384 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1385 if (!NT_STATUS_IS_OK(ntstatus)) {
1386 return ERROR_NT(ntstatus);
1389 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1391 unix_convert(directory,conn,0,&bad_path,&sbuf);
1392 if (bad_path) {
1393 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1395 if(!check_name(directory,conn)) {
1396 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1399 p = strrchr_m(directory,'/');
1400 if(p == NULL) {
1401 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1402 if((directory[0] == '.') && (directory[1] == '\0'))
1403 pstrcpy(mask,"*");
1404 else
1405 pstrcpy(mask,directory);
1406 pstrcpy(directory,"./");
1407 } else {
1408 pstrcpy(mask,p+1);
1409 *p = 0;
1412 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1414 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1415 if( pdata == NULL )
1416 return(ERROR_DOS(ERRDOS,ERRnomem));
1418 *ppdata = pdata;
1419 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1421 /* Realloc the params space */
1422 params = SMB_REALLOC(*pparams, 10);
1423 if (params == NULL)
1424 return ERROR_DOS(ERRDOS,ERRnomem);
1425 *pparams = params;
1427 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1428 if (dptr_num < 0)
1429 return(UNIXERROR(ERRDOS,ERRbadfile));
1431 /* Save the wildcard match and attribs we are using on this directory -
1432 needed as lanman2 assumes these are being saved between calls */
1434 if(!(wcard = SMB_STRDUP(mask))) {
1435 dptr_close(&dptr_num);
1436 return ERROR_DOS(ERRDOS,ERRnomem);
1439 dptr_set_wcard(dptr_num, wcard);
1440 dptr_set_attr(dptr_num, dirtype);
1442 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1444 /* We don't need to check for VOL here as this is returned by
1445 a different TRANS2 call. */
1447 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1448 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1449 dont_descend = True;
1451 p = pdata;
1452 space_remaining = max_data_bytes;
1453 out_of_space = False;
1455 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1456 BOOL got_exact_match = False;
1458 /* this is a heuristic to avoid seeking the dirptr except when
1459 absolutely necessary. It allows for a filename of about 40 chars */
1460 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1461 out_of_space = True;
1462 finished = False;
1463 } else {
1464 finished = !get_lanman2_dir_entry(conn,
1465 inbuf, outbuf,
1466 mask,dirtype,info_level,
1467 requires_resume_key,dont_descend,
1468 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1469 &last_name_off);
1472 if (finished && out_of_space)
1473 finished = False;
1475 if (!finished && !out_of_space)
1476 numentries++;
1479 * As an optimisation if we know we aren't looking
1480 * for a wildcard name (ie. the name matches the wildcard exactly)
1481 * then we can finish on any (first) match.
1482 * This speeds up large directory searches. JRA.
1485 if(got_exact_match)
1486 finished = True;
1488 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1491 /* Check if we can close the dirptr */
1492 if(close_after_first || (finished && close_if_end)) {
1493 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1494 dptr_close(&dptr_num);
1498 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1499 * from observation of NT.
1502 if(numentries == 0) {
1503 dptr_close(&dptr_num);
1504 return ERROR_DOS(ERRDOS,ERRbadfile);
1507 /* At this point pdata points to numentries directory entries. */
1509 /* Set up the return parameter block */
1510 SSVAL(params,0,dptr_num);
1511 SSVAL(params,2,numentries);
1512 SSVAL(params,4,finished);
1513 SSVAL(params,6,0); /* Never an EA error */
1514 SSVAL(params,8,last_name_off);
1516 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1518 if ((! *directory) && dptr_path(dptr_num))
1519 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1521 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1522 smb_fn_name(CVAL(inbuf,smb_com)),
1523 mask, directory, dirtype, numentries ) );
1526 * Force a name mangle here to ensure that the
1527 * mask as an 8.3 name is top of the mangled cache.
1528 * The reasons for this are subtle. Don't remove
1529 * this code unless you know what you are doing
1530 * (see PR#13758). JRA.
1533 if(!mangle_is_8_3_wildcards( mask, False))
1534 mangle_map(mask, True, True, SNUM(conn));
1536 return(-1);
1539 /****************************************************************************
1540 Reply to a TRANS2_FINDNEXT.
1541 ****************************************************************************/
1543 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1544 char **pparams, int total_params, char **ppdata, int total_data)
1546 /* We must be careful here that we don't return more than the
1547 allowed number of data bytes. If this means returning fewer than
1548 maxentries then so be it. We assume that the redirector has
1549 enough room for the fixed number of parameter bytes it has
1550 requested. */
1551 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1552 char *params = *pparams;
1553 char *pdata = *ppdata;
1554 int dptr_num = SVAL(params,0);
1555 int maxentries = SVAL(params,2);
1556 uint16 info_level = SVAL(params,4);
1557 uint32 resume_key = IVAL(params,6);
1558 BOOL close_after_request = BITSETW(params+10,0);
1559 BOOL close_if_end = BITSETW(params+10,1);
1560 BOOL requires_resume_key = BITSETW(params+10,2);
1561 BOOL continue_bit = BITSETW(params+10,3);
1562 pstring resume_name;
1563 pstring mask;
1564 pstring directory;
1565 char *p;
1566 uint16 dirtype;
1567 int numentries = 0;
1568 int i, last_name_off=0;
1569 BOOL finished = False;
1570 BOOL dont_descend = False;
1571 BOOL out_of_space = False;
1572 int space_remaining;
1573 NTSTATUS ntstatus = NT_STATUS_OK;
1575 if (total_params < 12)
1576 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1578 *mask = *directory = *resume_name = 0;
1580 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1581 if (!NT_STATUS_IS_OK(ntstatus)) {
1582 return ERROR_NT(ntstatus);
1585 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1586 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1587 resume_key = %d resume name = %s continue=%d level = %d\n",
1588 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1589 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1591 if (!maxentries) {
1592 /* W2K3 seems to treat zero as 1. */
1593 maxentries = 1;
1596 switch (info_level) {
1597 case SMB_INFO_STANDARD:
1598 case SMB_INFO_QUERY_EA_SIZE:
1599 case SMB_FIND_FILE_DIRECTORY_INFO:
1600 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1601 case SMB_FIND_FILE_NAMES_INFO:
1602 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1603 break;
1604 case SMB_FIND_FILE_UNIX:
1605 if (!lp_unix_extensions())
1606 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1607 break;
1608 default:
1609 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1612 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1613 if(pdata == NULL)
1614 return ERROR_DOS(ERRDOS,ERRnomem);
1616 *ppdata = pdata;
1617 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1619 /* Realloc the params space */
1620 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1621 if( params == NULL )
1622 return ERROR_DOS(ERRDOS,ERRnomem);
1624 *pparams = params;
1626 /* Check that the dptr is valid */
1627 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1628 return ERROR_DOS(ERRDOS,ERRnofiles);
1630 string_set(&conn->dirpath,dptr_path(dptr_num));
1632 /* Get the wildcard mask from the dptr */
1633 if((p = dptr_wcard(dptr_num))== NULL) {
1634 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1635 return ERROR_DOS(ERRDOS,ERRnofiles);
1638 pstrcpy(mask, p);
1639 pstrcpy(directory,conn->dirpath);
1641 /* Get the attr mask from the dptr */
1642 dirtype = dptr_attr(dptr_num);
1644 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1645 dptr_num, mask, dirtype,
1646 (long)conn->dirptr,
1647 TellDir(conn->dirptr)));
1649 /* We don't need to check for VOL here as this is returned by
1650 a different TRANS2 call. */
1652 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1653 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1654 dont_descend = True;
1656 p = pdata;
1657 space_remaining = max_data_bytes;
1658 out_of_space = False;
1661 * Seek to the correct position. We no longer use the resume key but
1662 * depend on the last file name instead.
1665 if(*resume_name && !continue_bit) {
1668 * Fix for NT redirector problem triggered by resume key indexes
1669 * changing between directory scans. We now return a resume key of 0
1670 * and instead look for the filename to continue from (also given
1671 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1672 * findfirst/findnext (as is usual) then the directory pointer
1673 * should already be at the correct place. Check this by scanning
1674 * backwards looking for an exact (ie. case sensitive) filename match.
1675 * If we get to the beginning of the directory and haven't found it then scan
1676 * forwards again looking for a match. JRA.
1679 int current_pos, start_pos;
1680 const char *dname = NULL;
1681 pstring dname_pstring;
1682 void *dirptr = conn->dirptr;
1683 start_pos = TellDir(dirptr);
1684 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1685 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1687 SeekDir(dirptr, current_pos);
1688 dname = ReadDirName(dirptr);
1689 if (dname) {
1691 * Remember, mangle_map is called by
1692 * get_lanman2_dir_entry(), so the resume name
1693 * could be mangled. Ensure we do the same
1694 * here.
1697 /* make sure we get a copy that mangle_map can modify */
1699 pstrcpy(dname_pstring, dname);
1700 mangle_map( dname_pstring, False, True, SNUM(conn));
1702 if(strcsequal( resume_name, dname_pstring)) {
1703 SeekDir(dirptr, current_pos+1);
1704 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1705 break;
1711 * Scan forward from start if not found going backwards.
1714 if(current_pos < 0) {
1715 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1716 SeekDir(dirptr, start_pos);
1717 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) {
1720 * Remember, mangle_map is called by
1721 * get_lanman2_dir_entry(), so the resume name
1722 * could be mangled. Ensure we do the same
1723 * here.
1726 if(dname) {
1727 /* make sure we get a copy that mangle_map can modify */
1729 pstrcpy(dname_pstring, dname);
1730 mangle_map(dname_pstring, False, True, SNUM(conn));
1732 if(strcsequal( resume_name, dname_pstring)) {
1733 SeekDir(dirptr, current_pos+1);
1734 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1735 break;
1738 } /* end for */
1739 } /* end if current_pos */
1740 /* Can't find the name. Just resume from where we were... */
1741 if (dname == 0) {
1742 SeekDir(dirptr, start_pos);
1744 } /* end if resume_name && !continue_bit */
1746 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1747 BOOL got_exact_match = False;
1749 /* this is a heuristic to avoid seeking the dirptr except when
1750 absolutely necessary. It allows for a filename of about 40 chars */
1751 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1752 out_of_space = True;
1753 finished = False;
1754 } else {
1755 finished = !get_lanman2_dir_entry(conn,
1756 inbuf, outbuf,
1757 mask,dirtype,info_level,
1758 requires_resume_key,dont_descend,
1759 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1760 &last_name_off);
1763 if (finished && out_of_space)
1764 finished = False;
1766 if (!finished && !out_of_space)
1767 numentries++;
1770 * As an optimisation if we know we aren't looking
1771 * for a wildcard name (ie. the name matches the wildcard exactly)
1772 * then we can finish on any (first) match.
1773 * This speeds up large directory searches. JRA.
1776 if(got_exact_match)
1777 finished = True;
1779 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1782 /* Check if we can close the dirptr */
1783 if(close_after_request || (finished && close_if_end)) {
1784 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1785 dptr_close(&dptr_num); /* This frees up the saved mask */
1788 /* Set up the return parameter block */
1789 SSVAL(params,0,numentries);
1790 SSVAL(params,2,finished);
1791 SSVAL(params,4,0); /* Never an EA error */
1792 SSVAL(params,6,last_name_off);
1794 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1796 if ((! *directory) && dptr_path(dptr_num))
1797 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1799 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1800 smb_fn_name(CVAL(inbuf,smb_com)),
1801 mask, directory, dirtype, numentries ) );
1803 return(-1);
1806 /****************************************************************************
1807 Reply to a TRANS2_QFSINFO (query filesystem info).
1808 ****************************************************************************/
1810 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1811 int length, int bufsize,
1812 char **pparams, int total_params, char **ppdata, int total_data)
1814 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1815 char *pdata = *ppdata;
1816 char *params = *pparams;
1817 uint16 info_level = SVAL(params,0);
1818 int data_len, len;
1819 SMB_STRUCT_STAT st;
1820 char *vname = volume_label(SNUM(conn));
1821 int snum = SNUM(conn);
1822 char *fstype = lp_fstype(SNUM(conn));
1823 int quota_flag = 0;
1825 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1827 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1828 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1829 return ERROR_DOS(ERRSRV,ERRinvdevice);
1832 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1833 if ( pdata == NULL )
1834 return ERROR_DOS(ERRDOS,ERRnomem);
1836 *ppdata = pdata;
1837 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1839 switch (info_level) {
1840 case SMB_INFO_ALLOCATION:
1842 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1843 data_len = 18;
1844 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1845 block_size = lp_block_size(snum);
1846 if (bsize < block_size) {
1847 SMB_BIG_UINT factor = block_size/bsize;
1848 bsize = block_size;
1849 dsize /= factor;
1850 dfree /= factor;
1852 if (bsize > block_size) {
1853 SMB_BIG_UINT factor = bsize/block_size;
1854 bsize = block_size;
1855 dsize *= factor;
1856 dfree *= factor;
1858 bytes_per_sector = 512;
1859 sectors_per_unit = bsize/bytes_per_sector;
1861 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1862 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1863 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1865 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1866 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1867 SIVAL(pdata,l1_cUnit,dsize);
1868 SIVAL(pdata,l1_cUnitAvail,dfree);
1869 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1870 break;
1873 case SMB_INFO_VOLUME:
1874 /* Return volume name */
1876 * Add volume serial number - hash of a combination of
1877 * the called hostname and the service name.
1879 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1880 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1881 SCVAL(pdata,l2_vol_cch,len);
1882 data_len = l2_vol_szVolLabel + len;
1883 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1884 (unsigned)st.st_ctime, len, vname));
1885 break;
1887 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1888 case SMB_FS_ATTRIBUTE_INFORMATION:
1891 #if defined(HAVE_SYS_QUOTAS)
1892 quota_flag = FILE_VOLUME_QUOTAS;
1893 #endif
1895 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1896 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1897 quota_flag); /* FS ATTRIBUTES */
1899 SIVAL(pdata,4,255); /* Max filename component length */
1900 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1901 and will think we can't do long filenames */
1902 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1903 SIVAL(pdata,8,len);
1904 data_len = 12 + len;
1905 break;
1907 case SMB_QUERY_FS_LABEL_INFO:
1908 case SMB_FS_LABEL_INFORMATION:
1909 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1910 data_len = 4 + len;
1911 SIVAL(pdata,0,len);
1912 break;
1914 case SMB_QUERY_FS_VOLUME_INFO:
1915 case SMB_FS_VOLUME_INFORMATION:
1918 * Add volume serial number - hash of a combination of
1919 * the called hostname and the service name.
1921 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1922 (str_checksum(local_machine)<<16));
1924 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1925 SIVAL(pdata,12,len);
1926 data_len = 18+len;
1927 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1928 (int)strlen(vname),vname, lp_servicename(snum)));
1929 break;
1931 case SMB_QUERY_FS_SIZE_INFO:
1932 case SMB_FS_SIZE_INFORMATION:
1934 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1935 data_len = 24;
1936 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1937 block_size = lp_block_size(snum);
1938 if (bsize < block_size) {
1939 SMB_BIG_UINT factor = block_size/bsize;
1940 bsize = block_size;
1941 dsize /= factor;
1942 dfree /= factor;
1944 if (bsize > block_size) {
1945 SMB_BIG_UINT factor = bsize/block_size;
1946 bsize = block_size;
1947 dsize *= factor;
1948 dfree *= factor;
1950 bytes_per_sector = 512;
1951 sectors_per_unit = bsize/bytes_per_sector;
1952 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1953 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1954 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1955 SBIG_UINT(pdata,0,dsize);
1956 SBIG_UINT(pdata,8,dfree);
1957 SIVAL(pdata,16,sectors_per_unit);
1958 SIVAL(pdata,20,bytes_per_sector);
1959 break;
1962 case SMB_FS_FULL_SIZE_INFORMATION:
1964 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1965 data_len = 32;
1966 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1967 block_size = lp_block_size(snum);
1968 if (bsize < block_size) {
1969 SMB_BIG_UINT factor = block_size/bsize;
1970 bsize = block_size;
1971 dsize /= factor;
1972 dfree /= factor;
1974 if (bsize > block_size) {
1975 SMB_BIG_UINT factor = bsize/block_size;
1976 bsize = block_size;
1977 dsize *= factor;
1978 dfree *= factor;
1980 bytes_per_sector = 512;
1981 sectors_per_unit = bsize/bytes_per_sector;
1982 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1983 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1984 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1985 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1986 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1987 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1988 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1989 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1990 break;
1993 case SMB_QUERY_FS_DEVICE_INFO:
1994 case SMB_FS_DEVICE_INFORMATION:
1995 data_len = 8;
1996 SIVAL(pdata,0,0); /* dev type */
1997 SIVAL(pdata,4,0); /* characteristics */
1998 break;
2000 #ifdef HAVE_SYS_QUOTAS
2001 case SMB_FS_QUOTA_INFORMATION:
2003 * what we have to send --metze:
2005 * Unknown1: 24 NULL bytes
2006 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2007 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2008 * Quota Flags: 2 byte :
2009 * Unknown3: 6 NULL bytes
2011 * 48 bytes total
2013 * details for Quota Flags:
2015 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2016 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2017 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2018 * 0x0001 Enable Quotas: enable quota for this fs
2022 /* we need to fake up a fsp here,
2023 * because its not send in this call
2025 files_struct fsp;
2026 SMB_NTQUOTA_STRUCT quotas;
2028 ZERO_STRUCT(fsp);
2029 ZERO_STRUCT(quotas);
2031 fsp.conn = conn;
2032 fsp.fnum = -1;
2033 fsp.fd = -1;
2035 /* access check */
2036 if (current_user.uid != 0) {
2037 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2038 lp_servicename(SNUM(conn)),conn->user));
2039 return ERROR_DOS(ERRDOS,ERRnoaccess);
2042 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2043 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2044 return ERROR_DOS(ERRSRV,ERRerror);
2047 data_len = 48;
2049 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2051 /* Unknown1 24 NULL bytes*/
2052 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2053 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2054 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2056 /* Default Soft Quota 8 bytes */
2057 SBIG_UINT(pdata,24,quotas.softlim);
2059 /* Default Hard Quota 8 bytes */
2060 SBIG_UINT(pdata,32,quotas.hardlim);
2062 /* Quota flag 2 bytes */
2063 SSVAL(pdata,40,quotas.qflags);
2065 /* Unknown3 6 NULL bytes */
2066 SSVAL(pdata,42,0);
2067 SIVAL(pdata,44,0);
2069 break;
2071 #endif /* HAVE_SYS_QUOTAS */
2072 case SMB_FS_OBJECTID_INFORMATION:
2073 data_len = 64;
2074 break;
2077 * Query the version and capabilities of the CIFS UNIX extensions
2078 * in use.
2081 case SMB_QUERY_CIFS_UNIX_INFO:
2082 if (!lp_unix_extensions())
2083 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2084 data_len = 12;
2085 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2086 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2087 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2088 break;
2090 case SMB_MAC_QUERY_FS_INFO:
2092 * Thursby MAC extension... ONLY on NTFS filesystems
2093 * once we do streams then we don't need this
2095 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2096 data_len = 88;
2097 SIVAL(pdata,84,0x100); /* Don't support mac... */
2098 break;
2100 /* drop through */
2101 default:
2102 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2106 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2108 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2110 return -1;
2113 #ifdef HAVE_SYS_QUOTAS
2114 /****************************************************************************
2115 Reply to a TRANS2_SETFSINFO (set filesystem info).
2116 ****************************************************************************/
2118 static int call_trans2setfsinfo(connection_struct *conn,
2119 char *inbuf, char *outbuf, int length, int bufsize,
2120 char **pparams, int total_params, char **ppdata, int total_data)
2122 char *pdata = *ppdata;
2123 char *params = *pparams;
2124 files_struct *fsp = NULL;
2125 uint16 info_level;
2126 int outsize;
2127 SMB_NTQUOTA_STRUCT quotas;
2129 ZERO_STRUCT(quotas);
2131 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2133 /* access check */
2134 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2135 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2136 lp_servicename(SNUM(conn)),conn->user));
2137 return ERROR_DOS(ERRSRV,ERRaccess);
2140 /* */
2141 if (total_params < 4) {
2142 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2143 total_params));
2144 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2147 fsp = file_fsp(params,0);
2149 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2150 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2151 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2154 info_level = SVAL(params,2);
2156 switch(info_level) {
2157 case SMB_FS_QUOTA_INFORMATION:
2158 /* note: normaly there're 48 bytes,
2159 * but we didn't use the last 6 bytes for now
2160 * --metze
2162 if (total_data < 42) {
2163 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2164 total_data));
2165 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2168 /* unknown_1 24 NULL bytes in pdata*/
2170 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2171 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2172 #ifdef LARGE_SMB_OFF_T
2173 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2174 #else /* LARGE_SMB_OFF_T */
2175 if ((IVAL(pdata,28) != 0)&&
2176 ((quotas.softlim != 0xFFFFFFFF)||
2177 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2178 /* more than 32 bits? */
2179 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2181 #endif /* LARGE_SMB_OFF_T */
2183 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2184 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2185 #ifdef LARGE_SMB_OFF_T
2186 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2187 #else /* LARGE_SMB_OFF_T */
2188 if ((IVAL(pdata,36) != 0)&&
2189 ((quotas.hardlim != 0xFFFFFFFF)||
2190 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2191 /* more than 32 bits? */
2192 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2194 #endif /* LARGE_SMB_OFF_T */
2196 /* quota_flags 2 bytes **/
2197 quotas.qflags = SVAL(pdata,40);
2199 /* unknown_2 6 NULL bytes follow*/
2201 /* now set the quotas */
2202 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2203 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2204 return ERROR_DOS(ERRSRV,ERRerror);
2207 break;
2208 default:
2209 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2210 info_level));
2211 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2212 break;
2216 * sending this reply works fine,
2217 * but I'm not sure it's the same
2218 * like windows do...
2219 * --metze
2221 outsize = set_message(outbuf,10,0,True);
2223 return outsize;
2225 #endif /* HAVE_SYS_QUOTAS */
2227 /****************************************************************************
2228 * Utility function to set bad path error.
2229 ****************************************************************************/
2231 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2233 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2234 err, (int)bad_path ));
2236 if(err == ENOENT) {
2237 if (bad_path) {
2238 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2239 } else {
2240 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2243 return UNIXERROR(def_class,def_code);
2246 /****************************************************************************
2247 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2248 file name or file id).
2249 ****************************************************************************/
2251 static int call_trans2qfilepathinfo(connection_struct *conn,
2252 char *inbuf, char *outbuf, int length,
2253 int bufsize,
2254 char **pparams, int total_params, char **ppdata, int total_data)
2256 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2257 char *params = *pparams;
2258 char *pdata = *ppdata;
2259 uint16 tran_call = SVAL(inbuf, smb_setup0);
2260 uint16 info_level;
2261 int mode=0;
2262 SMB_OFF_T file_size=0;
2263 SMB_BIG_UINT allocation_size=0;
2264 unsigned int data_size;
2265 unsigned int param_size = 2;
2266 SMB_STRUCT_STAT sbuf;
2267 pstring fname, dos_fname;
2268 char *fullpathname;
2269 char *base_name;
2270 char *p;
2271 SMB_OFF_T pos = 0;
2272 BOOL bad_path = False;
2273 BOOL delete_pending = False;
2274 int len;
2275 time_t c_time;
2276 files_struct *fsp = NULL;
2277 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2279 if (!params)
2280 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2282 ZERO_STRUCT(sbuf);
2284 if (tran_call == TRANSACT2_QFILEINFO) {
2285 if (total_params < 4)
2286 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2288 fsp = file_fsp(params,0);
2289 info_level = SVAL(params,2);
2291 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2293 if(fsp && (fsp->fake_file_handle)) {
2295 * This is actually for the QUOTA_FAKE_FILE --metze
2298 pstrcpy(fname, fsp->fsp_name);
2299 /* We know this name is ok, it's already passed the checks. */
2301 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2303 * This is actually a QFILEINFO on a directory
2304 * handle (returned from an NT SMB). NT5.0 seems
2305 * to do this call. JRA.
2307 /* We know this name is ok, it's already passed the checks. */
2308 pstrcpy(fname, fsp->fsp_name);
2310 if (INFO_LEVEL_IS_UNIX(info_level)) {
2311 /* Always do lstat for UNIX calls. */
2312 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2313 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2314 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2316 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2317 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2318 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2321 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2322 } else {
2324 * Original code - this is an open file.
2326 CHECK_FSP(fsp,conn);
2328 pstrcpy(fname, fsp->fsp_name);
2329 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2330 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2331 return(UNIXERROR(ERRDOS,ERRbadfid));
2333 pos = fsp->position_information;
2334 delete_pending = fsp->delete_on_close;
2335 desired_access = fsp->desired_access;
2337 } else {
2338 NTSTATUS status = NT_STATUS_OK;
2340 /* qpathinfo */
2341 if (total_params < 6)
2342 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2344 info_level = SVAL(params,0);
2346 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2348 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 return ERROR_NT(status);
2353 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2355 unix_convert(fname,conn,0,&bad_path,&sbuf);
2356 if (bad_path) {
2357 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2359 if (!check_name(fname,conn)) {
2360 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2361 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2364 if (INFO_LEVEL_IS_UNIX(info_level)) {
2365 /* Always do lstat for UNIX calls. */
2366 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2367 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2368 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2370 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2371 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2372 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2376 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2377 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2379 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2380 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2382 p = strrchr_m(fname,'/');
2383 if (!p)
2384 base_name = fname;
2385 else
2386 base_name = p+1;
2388 mode = dos_mode(conn,fname,&sbuf);
2389 if (!mode)
2390 mode = FILE_ATTRIBUTE_NORMAL;
2392 fullpathname = fname;
2393 file_size = get_file_size(sbuf);
2394 allocation_size = get_allocation_size(fsp,&sbuf);
2395 if (mode & aDIR)
2396 file_size = 0;
2398 params = SMB_REALLOC(*pparams,2);
2399 if (params == NULL)
2400 return ERROR_DOS(ERRDOS,ERRnomem);
2401 *pparams = params;
2402 memset((char *)params,'\0',2);
2403 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2404 pdata = SMB_REALLOC(*ppdata, data_size);
2405 if ( pdata == NULL )
2406 return ERROR_DOS(ERRDOS,ERRnomem);
2407 *ppdata = pdata;
2409 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2410 /* uggh, EAs for OS2 */
2411 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2412 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2415 memset((char *)pdata,'\0',data_size);
2417 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2419 if (lp_dos_filetime_resolution(SNUM(conn))) {
2420 c_time &= ~1;
2421 sbuf.st_atime &= ~1;
2422 sbuf.st_ctime &= ~1;
2423 sbuf.st_mtime &= ~1;
2426 /* NT expects the name to be in an exact form of the *full*
2427 filename. See the trans2 torture test */
2428 if (strequal(base_name,".")) {
2429 pstrcpy(dos_fname, "\\");
2430 } else {
2431 pstr_sprintf(dos_fname, "\\%s", fname);
2432 string_replace(dos_fname, '/', '\\');
2435 switch (info_level) {
2436 case SMB_INFO_STANDARD:
2437 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2438 data_size = 22;
2439 put_dos_date2(pdata,l1_fdateCreation,c_time);
2440 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2441 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2442 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2443 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2444 SSVAL(pdata,l1_attrFile,mode);
2445 break;
2447 case SMB_INFO_QUERY_EA_SIZE:
2449 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2450 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2451 data_size = 26;
2452 put_dos_date2(pdata,l1_fdateCreation,c_time);
2453 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2454 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2455 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2456 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2457 SSVAL(pdata,l1_attrFile,mode);
2458 SIVAL(pdata,l1_attrFile+2,ea_size);
2459 break;
2462 case SMB_INFO_IS_NAME_VALID:
2463 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2464 if (tran_call == TRANSACT2_QFILEINFO) {
2465 /* os/2 needs this ? really ?*/
2466 return ERROR_DOS(ERRDOS,ERRbadfunc);
2468 data_size = 0;
2469 param_size = 0;
2470 break;
2472 case SMB_INFO_QUERY_EAS_FROM_LIST:
2473 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2474 data_size = 24;
2475 put_dos_date2(pdata,0,c_time);
2476 put_dos_date2(pdata,4,sbuf.st_atime);
2477 put_dos_date2(pdata,8,sbuf.st_mtime);
2478 SIVAL(pdata,12,(uint32)file_size);
2479 SIVAL(pdata,16,(uint32)allocation_size);
2480 SIVAL(pdata,20,mode);
2481 break;
2483 case SMB_INFO_QUERY_ALL_EAS:
2484 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2485 /* We have data_size bytes to put EA's into. */
2486 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2487 break;
2489 case SMB_FILE_BASIC_INFORMATION:
2490 case SMB_QUERY_FILE_BASIC_INFO:
2492 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2493 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2494 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2495 } else {
2496 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2497 data_size = 40;
2498 SIVAL(pdata,36,0);
2500 put_long_date(pdata,c_time);
2501 put_long_date(pdata+8,sbuf.st_atime);
2502 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2503 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2504 SIVAL(pdata,32,mode);
2506 DEBUG(5,("SMB_QFBI - "));
2508 time_t create_time = c_time;
2509 DEBUG(5,("create: %s ", ctime(&create_time)));
2511 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2512 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2513 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2514 DEBUG(5,("mode: %x\n", mode));
2516 break;
2518 case SMB_FILE_STANDARD_INFORMATION:
2519 case SMB_QUERY_FILE_STANDARD_INFO:
2521 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2522 data_size = 24;
2523 SOFF_T(pdata,0,allocation_size);
2524 SOFF_T(pdata,8,file_size);
2525 if (delete_pending & sbuf.st_nlink)
2526 SIVAL(pdata,16,sbuf.st_nlink - 1);
2527 else
2528 SIVAL(pdata,16,sbuf.st_nlink);
2529 SCVAL(pdata,20,0);
2530 SCVAL(pdata,21,(mode&aDIR)?1:0);
2531 break;
2533 case SMB_FILE_EA_INFORMATION:
2534 case SMB_QUERY_FILE_EA_INFO:
2536 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2537 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2538 data_size = 4;
2539 SIVAL(pdata,0,ea_size);
2540 break;
2543 /* Get the 8.3 name - used if NT SMB was negotiated. */
2544 case SMB_QUERY_FILE_ALT_NAME_INFO:
2545 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2547 pstring short_name;
2549 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2550 pstrcpy(short_name,base_name);
2551 /* Mangle if not already 8.3 */
2552 if(!mangle_is_8_3(short_name, True)) {
2553 mangle_map(short_name,True,True,SNUM(conn));
2555 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2556 data_size = 4 + len;
2557 SIVAL(pdata,0,len);
2558 break;
2561 case SMB_QUERY_FILE_NAME_INFO:
2563 this must be *exactly* right for ACLs on mapped drives to work
2565 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2566 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2567 data_size = 4 + len;
2568 SIVAL(pdata,0,len);
2569 break;
2571 case SMB_FILE_ALLOCATION_INFORMATION:
2572 case SMB_QUERY_FILE_ALLOCATION_INFO:
2573 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2574 data_size = 8;
2575 SOFF_T(pdata,0,allocation_size);
2576 break;
2578 case SMB_FILE_END_OF_FILE_INFORMATION:
2579 case SMB_QUERY_FILE_END_OF_FILEINFO:
2580 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2581 data_size = 8;
2582 SOFF_T(pdata,0,file_size);
2583 break;
2585 case SMB_QUERY_FILE_ALL_INFO:
2586 case SMB_FILE_ALL_INFORMATION:
2588 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2589 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2590 put_long_date(pdata,c_time);
2591 put_long_date(pdata+8,sbuf.st_atime);
2592 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2593 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2594 SIVAL(pdata,32,mode);
2595 pdata += 40;
2596 SOFF_T(pdata,0,allocation_size);
2597 SOFF_T(pdata,8,file_size);
2598 if (delete_pending && sbuf.st_nlink)
2599 SIVAL(pdata,16,sbuf.st_nlink - 1);
2600 else
2601 SIVAL(pdata,16,sbuf.st_nlink);
2602 SCVAL(pdata,20,delete_pending);
2603 SCVAL(pdata,21,(mode&aDIR)?1:0);
2604 pdata += 24;
2605 SIVAL(pdata,0,ea_size);
2606 pdata += 4; /* EA info */
2607 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2608 SIVAL(pdata,0,len);
2609 pdata += 4 + len;
2610 data_size = PTR_DIFF(pdata,(*ppdata));
2611 break;
2613 case SMB_FILE_INTERNAL_INFORMATION:
2614 /* This should be an index number - looks like
2615 dev/ino to me :-)
2617 I think this causes us to fail the IFSKIT
2618 BasicFileInformationTest. -tpot */
2620 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2621 SIVAL(pdata,0,sbuf.st_dev);
2622 SIVAL(pdata,4,sbuf.st_ino);
2623 data_size = 8;
2624 break;
2626 case SMB_FILE_ACCESS_INFORMATION:
2627 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2628 SIVAL(pdata,0,desired_access);
2629 data_size = 4;
2630 break;
2632 case SMB_FILE_NAME_INFORMATION:
2633 /* Pathname with leading '\'. */
2635 size_t byte_len;
2636 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2637 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2638 SIVAL(pdata,0,byte_len);
2639 data_size = 4 + byte_len;
2640 break;
2643 case SMB_FILE_DISPOSITION_INFORMATION:
2644 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2645 data_size = 1;
2646 SCVAL(pdata,0,delete_pending);
2647 break;
2649 case SMB_FILE_POSITION_INFORMATION:
2650 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2651 data_size = 8;
2652 SOFF_T(pdata,0,pos);
2653 break;
2655 case SMB_FILE_MODE_INFORMATION:
2656 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2657 SIVAL(pdata,0,mode);
2658 data_size = 4;
2659 break;
2661 case SMB_FILE_ALIGNMENT_INFORMATION:
2662 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2663 SIVAL(pdata,0,0); /* No alignment needed. */
2664 data_size = 4;
2665 break;
2667 #if 0
2669 * NT4 server just returns "invalid query" to this - if we try to answer
2670 * it then NTws gets a BSOD! (tridge).
2671 * W2K seems to want this. JRA.
2673 case SMB_QUERY_FILE_STREAM_INFO:
2674 #endif
2675 case SMB_FILE_STREAM_INFORMATION:
2676 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2677 if (mode & aDIR) {
2678 data_size = 0;
2679 } else {
2680 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2681 SIVAL(pdata,0,0); /* ??? */
2682 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2683 SOFF_T(pdata,8,file_size);
2684 SIVAL(pdata,16,allocation_size);
2685 SIVAL(pdata,20,0); /* ??? */
2686 data_size = 24 + byte_len;
2688 break;
2690 case SMB_QUERY_COMPRESSION_INFO:
2691 case SMB_FILE_COMPRESSION_INFORMATION:
2692 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2693 SOFF_T(pdata,0,file_size);
2694 SIVAL(pdata,8,0); /* ??? */
2695 SIVAL(pdata,12,0); /* ??? */
2696 data_size = 16;
2697 break;
2699 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2700 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2701 put_long_date(pdata,c_time);
2702 put_long_date(pdata+8,sbuf.st_atime);
2703 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2704 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2705 SIVAL(pdata,32,allocation_size);
2706 SOFF_T(pdata,40,file_size);
2707 SIVAL(pdata,48,mode);
2708 SIVAL(pdata,52,0); /* ??? */
2709 data_size = 56;
2710 break;
2712 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2713 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2714 SIVAL(pdata,0,mode);
2715 SIVAL(pdata,4,0);
2716 data_size = 8;
2717 break;
2720 * CIFS UNIX Extensions.
2723 case SMB_QUERY_FILE_UNIX_BASIC:
2725 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2726 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2728 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2729 pdata += 8;
2731 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2732 pdata += 8;
2734 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2735 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2736 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2737 pdata += 24;
2739 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2740 SIVAL(pdata,4,0);
2741 pdata += 8;
2743 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2744 SIVAL(pdata,4,0);
2745 pdata += 8;
2747 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2748 pdata += 4;
2750 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2751 SIVAL(pdata,4,0);
2752 pdata += 8;
2754 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2755 SIVAL(pdata,4,0);
2756 pdata += 8;
2758 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2759 pdata += 8;
2761 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2762 SIVAL(pdata,4,0);
2763 pdata += 8;
2765 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2766 SIVAL(pdata,4,0);
2767 pdata += 8+1;
2768 data_size = PTR_DIFF(pdata,(*ppdata));
2771 int i;
2772 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2774 for (i=0; i<100; i++)
2775 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2776 DEBUG(4,("\n"));
2779 break;
2781 case SMB_QUERY_FILE_UNIX_LINK:
2783 pstring buffer;
2785 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2786 #ifdef S_ISLNK
2787 if(!S_ISLNK(sbuf.st_mode))
2788 return(UNIXERROR(ERRSRV,ERRbadlink));
2789 #else
2790 return(UNIXERROR(ERRDOS,ERRbadlink));
2791 #endif
2792 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2793 if (len == -1)
2794 return(UNIXERROR(ERRDOS,ERRnoaccess));
2795 buffer[len] = 0;
2796 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2797 pdata += len;
2798 data_size = PTR_DIFF(pdata,(*ppdata));
2800 break;
2803 default:
2804 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2807 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2809 return(-1);
2812 /****************************************************************************
2813 Deal with the internal needs of setting the delete on close flag. Note that
2814 as the tdb locking is recursive, it is safe to call this from within
2815 open_file_shared. JRA.
2816 ****************************************************************************/
2818 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
2820 if (delete_on_close) {
2822 * Only allow delete on close for writable files.
2825 if (dosmode & aRONLY) {
2826 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
2827 fsp->fsp_name ));
2828 return NT_STATUS_CANNOT_DELETE;
2832 * Only allow delete on close for writable shares.
2835 if (!CAN_WRITE(fsp->conn)) {
2836 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2837 fsp->fsp_name ));
2838 return NT_STATUS_ACCESS_DENIED;
2842 * Only allow delete on close for files/directories opened with delete intent.
2845 if (!(fsp->desired_access & DELETE_ACCESS)) {
2846 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2847 fsp->fsp_name ));
2848 return NT_STATUS_ACCESS_DENIED;
2852 if(fsp->is_directory) {
2853 fsp->directory_delete_on_close = delete_on_close;
2854 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2855 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2856 } else {
2857 fsp->delete_on_close = delete_on_close;
2858 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2859 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2862 return NT_STATUS_OK;
2865 /****************************************************************************
2866 Sets the delete on close flag over all share modes on this file.
2867 Modify the share mode entry for all files open
2868 on this device and inode to tell other smbds we have
2869 changed the delete on close flag. This will be noticed
2870 in the close code, the last closer will delete the file
2871 if flag is set.
2872 ****************************************************************************/
2874 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2876 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2877 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2879 if (fsp->is_directory || fsp->is_stat)
2880 return NT_STATUS_OK;
2882 if (lock_share_entry_fsp(fsp) == False)
2883 return NT_STATUS_ACCESS_DENIED;
2885 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2886 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
2887 fsp->fsp_name ));
2888 unlock_share_entry_fsp(fsp);
2889 return NT_STATUS_ACCESS_DENIED;
2892 unlock_share_entry_fsp(fsp);
2893 return NT_STATUS_OK;
2896 /****************************************************************************
2897 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2898 code.
2899 ****************************************************************************/
2901 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2903 BOOL bad_path_oldname = False;
2904 BOOL bad_path_newname = False;
2905 SMB_STRUCT_STAT sbuf1, sbuf2;
2906 pstring last_component_oldname;
2907 pstring last_component_newname;
2908 NTSTATUS status = NT_STATUS_OK;
2910 ZERO_STRUCT(sbuf1);
2911 ZERO_STRUCT(sbuf2);
2913 /* No wildcards. */
2914 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2915 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2918 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2919 if (bad_path_oldname) {
2920 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2923 /* Quick check for "." and ".." */
2924 if (last_component_oldname[0] == '.') {
2925 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2926 return NT_STATUS_OBJECT_NAME_INVALID;
2930 /* source must already exist. */
2931 if (!VALID_STAT(sbuf1)) {
2932 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2935 if (!check_name(oldname,conn)) {
2936 return NT_STATUS_ACCESS_DENIED;
2939 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2940 if (bad_path_newname) {
2941 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2944 /* Quick check for "." and ".." */
2945 if (last_component_newname[0] == '.') {
2946 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2947 return NT_STATUS_OBJECT_NAME_INVALID;
2951 /* Disallow if newname already exists. */
2952 if (VALID_STAT(sbuf2)) {
2953 return NT_STATUS_OBJECT_NAME_COLLISION;
2956 if (!check_name(newname,conn)) {
2957 return NT_STATUS_ACCESS_DENIED;
2960 /* No links from a directory. */
2961 if (S_ISDIR(sbuf1.st_mode)) {
2962 return NT_STATUS_FILE_IS_A_DIRECTORY;
2965 /* Ensure this is within the share. */
2966 if (!reduce_name(conn, oldname) != 0)
2967 return NT_STATUS_ACCESS_DENIED;
2969 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2971 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2972 status = map_nt_error_from_unix(errno);
2973 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2974 nt_errstr(status), newname, oldname));
2977 return status;
2980 /****************************************************************************
2981 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2982 ****************************************************************************/
2984 static int call_trans2setfilepathinfo(connection_struct *conn,
2985 char *inbuf, char *outbuf, int length, int bufsize,
2986 char **pparams, int total_params, char **ppdata, int total_data)
2988 char *params = *pparams;
2989 char *pdata = *ppdata;
2990 uint16 tran_call = SVAL(inbuf, smb_setup0);
2991 uint16 info_level;
2992 int dosmode=0;
2993 SMB_OFF_T size=0;
2994 struct utimbuf tvs;
2995 SMB_STRUCT_STAT sbuf;
2996 pstring fname;
2997 int fd = -1;
2998 BOOL bad_path = False;
2999 files_struct *fsp = NULL;
3000 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3001 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3002 mode_t unixmode = 0;
3003 NTSTATUS status = NT_STATUS_OK;
3005 if (!params)
3006 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3008 ZERO_STRUCT(sbuf);
3010 if (tran_call == TRANSACT2_SETFILEINFO) {
3011 if (total_params < 4)
3012 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3014 fsp = file_fsp(params,0);
3015 info_level = SVAL(params,2);
3017 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3019 * This is actually a SETFILEINFO on a directory
3020 * handle (returned from an NT SMB). NT5.0 seems
3021 * to do this call. JRA.
3023 pstrcpy(fname, fsp->fsp_name);
3024 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3025 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3026 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3028 } else if (fsp && fsp->print_file) {
3030 * Doing a DELETE_ON_CLOSE should cancel a print job.
3032 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3033 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3035 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3037 SSVAL(params,0,0);
3038 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3039 return(-1);
3040 } else
3041 return (UNIXERROR(ERRDOS,ERRbadpath));
3042 } else {
3044 * Original code - this is an open file.
3046 CHECK_FSP(fsp,conn);
3048 pstrcpy(fname, fsp->fsp_name);
3049 fd = fsp->fd;
3051 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3052 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3053 return(UNIXERROR(ERRDOS,ERRbadfid));
3056 } else {
3057 /* set path info */
3058 if (total_params < 6)
3059 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3061 info_level = SVAL(params,0);
3062 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3063 if (!NT_STATUS_IS_OK(status)) {
3064 return ERROR_NT(status);
3066 unix_convert(fname,conn,0,&bad_path,&sbuf);
3067 if (bad_path) {
3068 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3072 * For CIFS UNIX extensions the target name may not exist.
3075 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3076 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3077 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3080 if(!check_name(fname, conn)) {
3081 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3086 if (!CAN_WRITE(conn))
3087 return ERROR_DOS(ERRSRV,ERRaccess);
3089 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3090 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3092 if (VALID_STAT(sbuf))
3093 unixmode = sbuf.st_mode;
3095 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3096 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3098 /* Realloc the parameter and data sizes */
3099 params = SMB_REALLOC(*pparams,2);
3100 if(params == NULL)
3101 return ERROR_DOS(ERRDOS,ERRnomem);
3102 *pparams = params;
3104 SSVAL(params,0,0);
3106 if (fsp) {
3107 /* the pending modtime overrides the current modtime */
3108 sbuf.st_mtime = fsp->pending_modtime;
3111 size = get_file_size(sbuf);
3112 tvs.modtime = sbuf.st_mtime;
3113 tvs.actime = sbuf.st_atime;
3114 dosmode = dos_mode(conn,fname,&sbuf);
3115 unixmode = sbuf.st_mode;
3117 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3118 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3120 switch (info_level) {
3121 case SMB_INFO_STANDARD:
3123 if (total_data < 12)
3124 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3126 /* access time */
3127 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3128 /* write time */
3129 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3130 break;
3133 case SMB_INFO_SET_EA:
3134 status = set_ea(conn, fsp, fname, pdata, total_data);
3135 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3136 return ERROR_NT(status);
3137 break;
3139 /* XXXX um, i don't think this is right.
3140 it's also not in the cifs6.txt spec.
3142 case SMB_INFO_QUERY_EAS_FROM_LIST:
3143 if (total_data < 28)
3144 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3146 tvs.actime = make_unix_date2(pdata+8);
3147 tvs.modtime = make_unix_date2(pdata+12);
3148 size = IVAL(pdata,16);
3149 dosmode = IVAL(pdata,24);
3150 break;
3152 /* XXXX nor this. not in cifs6.txt, either. */
3153 case SMB_INFO_QUERY_ALL_EAS:
3154 if (total_data < 28)
3155 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3157 tvs.actime = make_unix_date2(pdata+8);
3158 tvs.modtime = make_unix_date2(pdata+12);
3159 size = IVAL(pdata,16);
3160 dosmode = IVAL(pdata,24);
3161 break;
3163 case SMB_SET_FILE_BASIC_INFO:
3164 case SMB_FILE_BASIC_INFORMATION:
3166 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3167 time_t write_time;
3168 time_t changed_time;
3170 if (total_data < 36)
3171 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3173 /* Ignore create time at offset pdata. */
3175 /* access time */
3176 tvs.actime = interpret_long_date(pdata+8);
3178 write_time = interpret_long_date(pdata+16);
3179 changed_time = interpret_long_date(pdata+24);
3181 tvs.modtime = MIN(write_time, changed_time);
3183 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3184 tvs.modtime = write_time;
3186 /* Prefer a defined time to an undefined one. */
3187 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3188 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3189 ? changed_time : write_time);
3191 /* attributes */
3192 dosmode = IVAL(pdata,32);
3193 break;
3196 case SMB_FILE_ALLOCATION_INFORMATION:
3197 case SMB_SET_FILE_ALLOCATION_INFO:
3199 int ret = -1;
3200 SMB_BIG_UINT allocation_size;
3202 if (total_data < 8)
3203 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3205 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3206 #ifdef LARGE_SMB_OFF_T
3207 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3208 #else /* LARGE_SMB_OFF_T */
3209 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3210 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3211 #endif /* LARGE_SMB_OFF_T */
3212 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3213 fname, (double)allocation_size ));
3215 if (allocation_size)
3216 allocation_size = smb_roundup(allocation_size);
3218 if(allocation_size != get_file_size(sbuf)) {
3219 SMB_STRUCT_STAT new_sbuf;
3221 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3222 fname, (double)allocation_size ));
3224 if (fd == -1) {
3225 files_struct *new_fsp = NULL;
3226 int access_mode = 0;
3227 int action = 0;
3229 if(global_oplock_break) {
3230 /* Queue this file modify as we are the process of an oplock break. */
3232 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3233 DEBUGADD(2,( "in oplock break state.\n"));
3235 push_oplock_pending_smb_message(inbuf, length);
3236 return -1;
3239 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3240 SET_OPEN_MODE(DOS_OPEN_RDWR),
3241 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3242 FILE_ATTRIBUTE_NORMAL,
3243 INTERNAL_OPEN_ONLY, &access_mode, &action);
3245 if (new_fsp == NULL)
3246 return(UNIXERROR(ERRDOS,ERRbadpath));
3247 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3248 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3249 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3250 new_fsp->fnum, strerror(errno)));
3251 ret = -1;
3253 close_file(new_fsp,True);
3254 } else {
3255 ret = vfs_allocate_file_space(fsp, allocation_size);
3256 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3257 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3258 fsp->fnum, strerror(errno)));
3259 ret = -1;
3262 if (ret == -1)
3263 return ERROR_NT(NT_STATUS_DISK_FULL);
3265 /* Allocate can truncate size... */
3266 size = get_file_size(new_sbuf);
3269 break;
3272 case SMB_FILE_END_OF_FILE_INFORMATION:
3273 case SMB_SET_FILE_END_OF_FILE_INFO:
3275 if (total_data < 8)
3276 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3278 size = IVAL(pdata,0);
3279 #ifdef LARGE_SMB_OFF_T
3280 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3281 #else /* LARGE_SMB_OFF_T */
3282 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3283 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3284 #endif /* LARGE_SMB_OFF_T */
3285 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3286 break;
3289 case SMB_FILE_DISPOSITION_INFORMATION:
3290 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3292 BOOL delete_on_close;
3294 if (total_data < 1)
3295 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3297 delete_on_close = (CVAL(pdata,0) ? True : False);
3299 /* Just ignore this set on a path. */
3300 if (tran_call != TRANSACT2_SETFILEINFO)
3301 break;
3303 if (fsp == NULL)
3304 return(UNIXERROR(ERRDOS,ERRbadfid));
3306 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3308 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3309 return ERROR_NT(status);
3311 /* The set is across all open files on this dev/inode pair. */
3312 status =set_delete_on_close_over_all(fsp, delete_on_close);
3313 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3314 return ERROR_NT(status);
3316 break;
3319 case SMB_FILE_POSITION_INFORMATION:
3321 SMB_BIG_UINT position_information;
3323 if (total_data < 8)
3324 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3326 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3327 #ifdef LARGE_SMB_OFF_T
3328 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3329 #else /* LARGE_SMB_OFF_T */
3330 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3331 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3332 #endif /* LARGE_SMB_OFF_T */
3333 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3334 fname, (double)position_information ));
3335 if (fsp)
3336 fsp->position_information = position_information;
3337 break;
3341 * CIFS UNIX extensions.
3344 case SMB_SET_FILE_UNIX_BASIC:
3346 uint32 raw_unixmode;
3348 if (total_data < 100)
3349 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3351 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3352 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3353 size=IVAL(pdata,0); /* first 8 Bytes are size */
3354 #ifdef LARGE_SMB_OFF_T
3355 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3356 #else /* LARGE_SMB_OFF_T */
3357 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3358 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3359 #endif /* LARGE_SMB_OFF_T */
3361 pdata+=24; /* ctime & st_blocks are not changed */
3362 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3363 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3364 pdata+=16;
3365 set_owner = (uid_t)IVAL(pdata,0);
3366 pdata += 8;
3367 set_grp = (gid_t)IVAL(pdata,0);
3368 pdata += 8;
3369 raw_unixmode = IVAL(pdata,28);
3370 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3371 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3373 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3374 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3375 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3377 if (!VALID_STAT(sbuf)) {
3380 * The only valid use of this is to create character and block
3381 * devices, and named pipes. This is deprecated (IMHO) and
3382 * a new info level should be used for mknod. JRA.
3385 uint32 file_type = IVAL(pdata,0);
3386 #if defined(HAVE_MAKEDEV)
3387 uint32 dev_major = IVAL(pdata,4);
3388 uint32 dev_minor = IVAL(pdata,12);
3389 #endif
3391 uid_t myuid = geteuid();
3392 gid_t mygid = getegid();
3393 SMB_DEV_T dev = (SMB_DEV_T)0;
3395 if (tran_call == TRANSACT2_SETFILEINFO)
3396 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3398 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3399 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3401 #if defined(HAVE_MAKEDEV)
3402 dev = makedev(dev_major, dev_minor);
3403 #endif
3405 /* We can only create as the owner/group we are. */
3407 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3408 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3409 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3410 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3412 switch (file_type) {
3413 #if defined(S_IFIFO)
3414 case UNIX_TYPE_FIFO:
3415 unixmode |= S_IFIFO;
3416 break;
3417 #endif
3418 #if defined(S_IFSOCK)
3419 case UNIX_TYPE_SOCKET:
3420 unixmode |= S_IFSOCK;
3421 break;
3422 #endif
3423 #if defined(S_IFCHR)
3424 case UNIX_TYPE_CHARDEV:
3425 unixmode |= S_IFCHR;
3426 break;
3427 #endif
3428 #if defined(S_IFBLK)
3429 case UNIX_TYPE_BLKDEV:
3430 unixmode |= S_IFBLK;
3431 break;
3432 #endif
3433 default:
3434 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3437 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3438 0%o for file %s\n", (double)dev, unixmode, fname ));
3440 /* Ok - do the mknod. */
3441 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3442 return(UNIXERROR(ERRDOS,ERRnoaccess));
3444 inherit_access_acl(conn, fname, unixmode);
3446 SSVAL(params,0,0);
3447 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3448 return(-1);
3452 * Deal with the UNIX specific mode set.
3455 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3456 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3457 (unsigned int)unixmode, fname ));
3458 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3459 return(UNIXERROR(ERRDOS,ERRnoaccess));
3463 * Deal with the UNIX specific uid set.
3466 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3467 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3468 (unsigned int)set_owner, fname ));
3469 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3470 return(UNIXERROR(ERRDOS,ERRnoaccess));
3474 * Deal with the UNIX specific gid set.
3477 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3478 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3479 (unsigned int)set_owner, fname ));
3480 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3481 return(UNIXERROR(ERRDOS,ERRnoaccess));
3483 break;
3486 case SMB_SET_FILE_UNIX_LINK:
3488 pstring link_target;
3489 char *newname = fname;
3491 /* Set a symbolic link. */
3492 /* Don't allow this if follow links is false. */
3494 if (!lp_symlinks(SNUM(conn)))
3495 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3497 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3499 /* !widelinks forces the target path to be within the share. */
3500 /* This means we can interpret the target as a pathname. */
3501 if (!lp_widelinks(SNUM(conn))) {
3502 pstring rel_name;
3503 char *last_dirp = NULL;
3505 unix_format(link_target);
3506 if (*link_target == '/') {
3507 /* No absolute paths allowed. */
3508 return(UNIXERROR(ERRDOS,ERRnoaccess));
3510 pstrcpy(rel_name, newname);
3511 last_dirp = strrchr_m(rel_name, '/');
3512 if (last_dirp) {
3513 last_dirp[1] = '\0';
3514 } else {
3515 pstrcpy(rel_name, "./");
3517 pstrcat(rel_name, link_target);
3519 if (!check_name(rel_name, conn)) {
3520 return(UNIXERROR(ERRDOS,ERRnoaccess));
3524 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3525 fname, link_target ));
3527 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3528 return(UNIXERROR(ERRDOS,ERRnoaccess));
3529 SSVAL(params,0,0);
3530 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3531 return(-1);
3534 case SMB_SET_FILE_UNIX_HLINK:
3536 pstring oldname;
3537 char *newname = fname;
3539 /* Set a hard link. */
3540 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3541 if (!NT_STATUS_IS_OK(status)) {
3542 return ERROR_NT(status);
3545 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3546 fname, oldname));
3548 status = hardlink_internals(conn, oldname, newname);
3549 if (!NT_STATUS_IS_OK(status)) {
3550 return ERROR_NT(status);
3553 SSVAL(params,0,0);
3554 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3555 return(-1);
3558 case SMB_FILE_RENAME_INFORMATION:
3560 BOOL overwrite;
3561 uint32 root_fid;
3562 uint32 len;
3563 pstring newname;
3564 pstring base_name;
3565 char *p;
3567 if (total_data < 12)
3568 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3570 overwrite = (CVAL(pdata,0) ? True : False);
3571 root_fid = IVAL(pdata,4);
3572 len = IVAL(pdata,8);
3573 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 return ERROR_NT(status);
3578 /* Check the new name has no '/' characters. */
3579 if (strchr_m(newname, '/'))
3580 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3582 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3584 /* Create the base directory. */
3585 pstrcpy(base_name, fname);
3586 p = strrchr_m(base_name, '/');
3587 if (p)
3588 *p = '\0';
3589 /* Append the new name. */
3590 pstrcat(base_name, "/");
3591 pstrcat(base_name, newname);
3593 if (fsp) {
3594 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3595 fsp->fnum, fsp->fsp_name, base_name ));
3596 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3597 } else {
3598 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3599 fname, newname ));
3600 status = rename_internals(conn, fname, base_name, 0, overwrite);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 return ERROR_NT(status);
3605 process_pending_change_notify_queue((time_t)0);
3606 SSVAL(params,0,0);
3607 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3608 return(-1);
3610 default:
3611 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3614 /* get some defaults (no modifications) if any info is zero or -1. */
3615 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3616 tvs.actime = sbuf.st_atime;
3618 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3619 tvs.modtime = sbuf.st_mtime;
3621 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3622 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3623 DEBUG(6,("size: %.0f ", (double)size));
3625 if (dosmode) {
3626 if (S_ISDIR(sbuf.st_mode))
3627 dosmode |= aDIR;
3628 else
3629 dosmode &= ~aDIR;
3632 DEBUG(6,("dosmode: %x\n" , dosmode));
3634 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3635 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3636 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3637 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3640 * Only do this test if we are not explicitly
3641 * changing the size of a file.
3643 if (!size)
3644 size = get_file_size(sbuf);
3648 * Try and set the times, size and mode of this file -
3649 * if they are different from the current values
3651 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3652 if(fsp != NULL) {
3654 * This was a setfileinfo on an open file.
3655 * NT does this a lot. It's actually pointless
3656 * setting the time here, as it will be overwritten
3657 * on the next write, so we save the request
3658 * away and will set it on file close. JRA.
3661 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3662 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3663 fsp->pending_modtime = tvs.modtime;
3666 } else {
3668 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3670 if(file_utime(conn, fname, &tvs)!=0)
3671 return(UNIXERROR(ERRDOS,ERRnoaccess));
3675 /* check the mode isn't different, before changing it */
3676 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3678 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3680 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3681 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3682 return(UNIXERROR(ERRDOS,ERRnoaccess));
3686 if (size != get_file_size(sbuf)) {
3688 int ret;
3690 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3691 fname, (double)size ));
3693 if (fd == -1) {
3694 files_struct *new_fsp = NULL;
3695 int access_mode = 0;
3696 int action = 0;
3698 if(global_oplock_break) {
3699 /* Queue this file modify as we are the process of an oplock break. */
3701 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3702 DEBUGADD(2,( "in oplock break state.\n"));
3704 push_oplock_pending_smb_message(inbuf, length);
3705 return -1;
3708 new_fsp = open_file_shared(conn, fname, &sbuf,
3709 SET_OPEN_MODE(DOS_OPEN_RDWR),
3710 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3711 FILE_ATTRIBUTE_NORMAL,
3712 INTERNAL_OPEN_ONLY, &access_mode, &action);
3714 if (new_fsp == NULL)
3715 return(UNIXERROR(ERRDOS,ERRbadpath));
3716 ret = vfs_set_filelen(new_fsp, size);
3717 close_file(new_fsp,True);
3718 } else {
3719 ret = vfs_set_filelen(fsp, size);
3722 if (ret == -1)
3723 return (UNIXERROR(ERRHRD,ERRdiskfull));
3726 SSVAL(params,0,0);
3727 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3729 return(-1);
3732 /****************************************************************************
3733 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3734 ****************************************************************************/
3736 static int call_trans2mkdir(connection_struct *conn,
3737 char *inbuf, char *outbuf, int length, int bufsize,
3738 char **pparams, int total_params, char **ppdata, int total_data)
3740 char *params = *pparams;
3741 pstring directory;
3742 int ret = -1;
3743 SMB_STRUCT_STAT sbuf;
3744 BOOL bad_path = False;
3745 NTSTATUS status = NT_STATUS_OK;
3747 if (!CAN_WRITE(conn))
3748 return ERROR_DOS(ERRSRV,ERRaccess);
3750 if (total_params < 4)
3751 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3753 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3754 if (!NT_STATUS_IS_OK(status)) {
3755 return ERROR_NT(status);
3758 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3760 unix_convert(directory,conn,0,&bad_path,&sbuf);
3761 if (bad_path) {
3762 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3764 if (check_name(directory,conn))
3765 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3767 if(ret < 0) {
3768 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3769 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3772 /* Realloc the parameter and data sizes */
3773 params = SMB_REALLOC(*pparams,2);
3774 if(params == NULL)
3775 return ERROR_DOS(ERRDOS,ERRnomem);
3776 *pparams = params;
3778 SSVAL(params,0,0);
3780 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3782 return(-1);
3785 /****************************************************************************
3786 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3787 We don't actually do this - we just send a null response.
3788 ****************************************************************************/
3790 static int call_trans2findnotifyfirst(connection_struct *conn,
3791 char *inbuf, char *outbuf, int length, int bufsize,
3792 char **pparams, int total_params, char **ppdata, int total_data)
3794 static uint16 fnf_handle = 257;
3795 char *params = *pparams;
3796 uint16 info_level;
3798 if (total_params < 6)
3799 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3801 info_level = SVAL(params,4);
3802 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3804 switch (info_level) {
3805 case 1:
3806 case 2:
3807 break;
3808 default:
3809 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3812 /* Realloc the parameter and data sizes */
3813 params = SMB_REALLOC(*pparams,6);
3814 if(params == NULL)
3815 return ERROR_DOS(ERRDOS,ERRnomem);
3816 *pparams = params;
3818 SSVAL(params,0,fnf_handle);
3819 SSVAL(params,2,0); /* No changes */
3820 SSVAL(params,4,0); /* No EA errors */
3822 fnf_handle++;
3824 if(fnf_handle == 0)
3825 fnf_handle = 257;
3827 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3829 return(-1);
3832 /****************************************************************************
3833 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3834 changes). Currently this does nothing.
3835 ****************************************************************************/
3837 static int call_trans2findnotifynext(connection_struct *conn,
3838 char *inbuf, char *outbuf, int length, int bufsize,
3839 char **pparams, int total_params, char **ppdata, int total_data)
3841 char *params = *pparams;
3843 DEBUG(3,("call_trans2findnotifynext\n"));
3845 /* Realloc the parameter and data sizes */
3846 params = SMB_REALLOC(*pparams,4);
3847 if(params == NULL)
3848 return ERROR_DOS(ERRDOS,ERRnomem);
3849 *pparams = params;
3851 SSVAL(params,0,0); /* No changes */
3852 SSVAL(params,2,0); /* No EA errors */
3854 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3856 return(-1);
3859 /****************************************************************************
3860 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3861 ****************************************************************************/
3863 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3864 char* outbuf, int length, int bufsize,
3865 char **pparams, int total_params, char **ppdata, int total_data)
3867 char *params = *pparams;
3868 pstring pathname;
3869 int reply_size = 0;
3870 int max_referral_level;
3872 DEBUG(10,("call_trans2getdfsreferral\n"));
3874 if (total_params < 2)
3875 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3877 max_referral_level = SVAL(params,0);
3879 if(!lp_host_msdfs())
3880 return ERROR_DOS(ERRDOS,ERRbadfunc);
3882 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3883 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3884 return UNIXERROR(ERRDOS,ERRbadfile);
3886 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3887 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3889 return(-1);
3892 #define LMCAT_SPL 0x53
3893 #define LMFUNC_GETJOBID 0x60
3895 /****************************************************************************
3896 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3897 ****************************************************************************/
3899 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3900 char* outbuf, int length, int bufsize,
3901 char **pparams, int total_params, char **ppdata, int total_data)
3903 char *pdata = *ppdata;
3904 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3906 /* check for an invalid fid before proceeding */
3908 if (!fsp)
3909 return(ERROR_DOS(ERRDOS,ERRbadfid));
3911 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3912 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3913 pdata = SMB_REALLOC(*ppdata, 32);
3914 if(pdata == NULL)
3915 return ERROR_DOS(ERRDOS,ERRnomem);
3916 *ppdata = pdata;
3918 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3919 CAN ACCEPT THIS IN UNICODE. JRA. */
3921 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3922 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3923 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3924 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3925 return(-1);
3926 } else {
3927 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3928 return ERROR_DOS(ERRSRV,ERRerror);
3932 /****************************************************************************
3933 Reply to a SMBfindclose (stop trans2 directory search).
3934 ****************************************************************************/
3936 int reply_findclose(connection_struct *conn,
3937 char *inbuf,char *outbuf,int length,int bufsize)
3939 int outsize = 0;
3940 int dptr_num=SVALS(inbuf,smb_vwv0);
3941 START_PROFILE(SMBfindclose);
3943 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3945 dptr_close(&dptr_num);
3947 outsize = set_message(outbuf,0,0,True);
3949 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3951 END_PROFILE(SMBfindclose);
3952 return(outsize);
3955 /****************************************************************************
3956 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3957 ****************************************************************************/
3959 int reply_findnclose(connection_struct *conn,
3960 char *inbuf,char *outbuf,int length,int bufsize)
3962 int outsize = 0;
3963 int dptr_num= -1;
3964 START_PROFILE(SMBfindnclose);
3966 dptr_num = SVAL(inbuf,smb_vwv0);
3968 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3970 /* We never give out valid handles for a
3971 findnotifyfirst - so any dptr_num is ok here.
3972 Just ignore it. */
3974 outsize = set_message(outbuf,0,0,True);
3976 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3978 END_PROFILE(SMBfindnclose);
3979 return(outsize);
3982 /****************************************************************************
3983 Reply to a SMBtranss2 - just ignore it!
3984 ****************************************************************************/
3986 int reply_transs2(connection_struct *conn,
3987 char *inbuf,char *outbuf,int length,int bufsize)
3989 START_PROFILE(SMBtranss2);
3990 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3991 END_PROFILE(SMBtranss2);
3992 return(-1);
3995 /****************************************************************************
3996 Reply to a SMBtrans2.
3997 ****************************************************************************/
3999 int reply_trans2(connection_struct *conn,
4000 char *inbuf,char *outbuf,int length,int bufsize)
4002 int outsize = 0;
4003 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4004 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4005 #if 0
4006 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4007 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
4008 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4009 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4010 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4011 int32 timeout = IVALS(inbuf,smb_timeout);
4012 #endif
4013 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4014 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4015 char *params = NULL, *data = NULL;
4016 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4017 START_PROFILE(SMBtrans2);
4019 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4020 /* Queue this open message as we are the process of an
4021 * oplock break. */
4023 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4024 DEBUGADD(2,( "in oplock break state.\n"));
4026 push_oplock_pending_smb_message(inbuf, length);
4027 END_PROFILE(SMBtrans2);
4028 return -1;
4031 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4032 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4033 END_PROFILE(SMBtrans2);
4034 return ERROR_DOS(ERRSRV,ERRaccess);
4037 outsize = set_message(outbuf,0,0,True);
4039 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4040 is so as a sanity check */
4041 if (suwcnt != 1) {
4043 * Need to have rc=0 for ioctl to get job id for OS/2.
4044 * Network printing will fail if function is not successful.
4045 * Similar function in reply.c will be used if protocol
4046 * is LANMAN1.0 instead of LM1.2X002.
4047 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4048 * outbuf doesn't have to be set(only job id is used).
4050 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4051 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4052 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4053 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4054 } else {
4055 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4056 DEBUG(2,("Transaction is %d\n",tran_call));
4057 END_PROFILE(SMBtrans2);
4058 ERROR_DOS(ERRDOS,ERRinvalidparam);
4062 /* Allocate the space for the maximum needed parameters and data */
4063 if (total_params > 0)
4064 params = (char *)SMB_MALLOC(total_params);
4065 if (total_data > 0)
4066 data = (char *)SMB_MALLOC(total_data);
4068 if ((total_params && !params) || (total_data && !data)) {
4069 DEBUG(2,("Out of memory in reply_trans2\n"));
4070 SAFE_FREE(params);
4071 SAFE_FREE(data);
4072 END_PROFILE(SMBtrans2);
4073 return ERROR_DOS(ERRDOS,ERRnomem);
4076 /* Copy the param and data bytes sent with this request into
4077 the params buffer */
4078 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4079 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4081 if (num_params > total_params || num_data > total_data)
4082 exit_server("invalid params in reply_trans2");
4084 if(params) {
4085 unsigned int psoff = SVAL(inbuf, smb_psoff);
4086 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4087 goto bad_param;
4088 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4089 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4090 goto bad_param;
4091 memcpy( params, smb_base(inbuf) + psoff, num_params);
4093 if(data) {
4094 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4095 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4096 goto bad_param;
4097 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4098 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4099 goto bad_param;
4100 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4103 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4105 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4106 /* We need to send an interim response then receive the rest
4107 of the parameter/data bytes */
4108 outsize = set_message(outbuf,0,0,True);
4109 srv_signing_trans_stop();
4110 if (!send_smb(smbd_server_fd(),outbuf))
4111 exit_server("reply_trans2: send_smb failed.");
4113 while (num_data_sofar < total_data ||
4114 num_params_sofar < total_params) {
4115 BOOL ret;
4116 unsigned int param_disp;
4117 unsigned int param_off;
4118 unsigned int data_disp;
4119 unsigned int data_off;
4121 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4124 * The sequence number for the trans reply is always
4125 * based on the last secondary received.
4128 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4130 if ((ret &&
4131 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4132 outsize = set_message(outbuf,0,0,True);
4133 if(ret)
4134 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4135 else
4136 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4137 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4138 goto bad_param;
4141 /* Revise total_params and total_data in case
4142 they have changed downwards */
4143 if (SVAL(inbuf, smb_tpscnt) < total_params)
4144 total_params = SVAL(inbuf, smb_tpscnt);
4145 if (SVAL(inbuf, smb_tdscnt) < total_data)
4146 total_data = SVAL(inbuf, smb_tdscnt);
4148 num_params = SVAL(inbuf,smb_spscnt);
4149 param_off = SVAL(inbuf, smb_spsoff);
4150 param_disp = SVAL(inbuf, smb_spsdisp);
4151 num_params_sofar += num_params;
4153 num_data = SVAL(inbuf, smb_sdscnt);
4154 data_off = SVAL(inbuf, smb_sdsoff);
4155 data_disp = SVAL(inbuf, smb_sdsdisp);
4156 num_data_sofar += num_data;
4158 if (num_params_sofar > total_params || num_data_sofar > total_data)
4159 goto bad_param;
4161 if (num_params) {
4162 if (param_disp + num_params >= total_params)
4163 goto bad_param;
4164 if ((param_disp + num_params < param_disp) ||
4165 (param_disp + num_params < num_params))
4166 goto bad_param;
4167 if (param_disp > total_params)
4168 goto bad_param;
4169 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4170 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4171 goto bad_param;
4172 if (params + param_disp < params)
4173 goto bad_param;
4175 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4177 if (num_data) {
4178 if (data_disp + num_data >= total_data)
4179 goto bad_param;
4180 if ((data_disp + num_data < data_disp) ||
4181 (data_disp + num_data < num_data))
4182 goto bad_param;
4183 if (data_disp > total_data)
4184 goto bad_param;
4185 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4186 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4187 goto bad_param;
4188 if (data + data_disp < data)
4189 goto bad_param;
4191 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4196 if (Protocol >= PROTOCOL_NT1) {
4197 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4200 /* Now we must call the relevant TRANS2 function */
4201 switch(tran_call) {
4202 case TRANSACT2_OPEN:
4203 START_PROFILE_NESTED(Trans2_open);
4204 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4205 &params, total_params, &data, total_data);
4206 END_PROFILE_NESTED(Trans2_open);
4207 break;
4209 case TRANSACT2_FINDFIRST:
4210 START_PROFILE_NESTED(Trans2_findfirst);
4211 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4212 &params, total_params, &data, total_data);
4213 END_PROFILE_NESTED(Trans2_findfirst);
4214 break;
4216 case TRANSACT2_FINDNEXT:
4217 START_PROFILE_NESTED(Trans2_findnext);
4218 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4219 &params, total_params, &data, total_data);
4220 END_PROFILE_NESTED(Trans2_findnext);
4221 break;
4223 case TRANSACT2_QFSINFO:
4224 START_PROFILE_NESTED(Trans2_qfsinfo);
4225 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4226 &params, total_params, &data, total_data);
4227 END_PROFILE_NESTED(Trans2_qfsinfo);
4228 break;
4230 #ifdef HAVE_SYS_QUOTAS
4231 case TRANSACT2_SETFSINFO:
4232 START_PROFILE_NESTED(Trans2_setfsinfo);
4233 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4234 &params, total_params, &data, total_data);
4235 END_PROFILE_NESTED(Trans2_setfsinfo);
4236 break;
4237 #endif
4238 case TRANSACT2_QPATHINFO:
4239 case TRANSACT2_QFILEINFO:
4240 START_PROFILE_NESTED(Trans2_qpathinfo);
4241 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4242 &params, total_params, &data, total_data);
4243 END_PROFILE_NESTED(Trans2_qpathinfo);
4244 break;
4245 case TRANSACT2_SETPATHINFO:
4246 case TRANSACT2_SETFILEINFO:
4247 START_PROFILE_NESTED(Trans2_setpathinfo);
4248 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4249 &params, total_params, &data, total_data);
4250 END_PROFILE_NESTED(Trans2_setpathinfo);
4251 break;
4253 case TRANSACT2_FINDNOTIFYFIRST:
4254 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4255 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4256 &params, total_params, &data, total_data);
4257 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4258 break;
4260 case TRANSACT2_FINDNOTIFYNEXT:
4261 START_PROFILE_NESTED(Trans2_findnotifynext);
4262 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4263 &params, total_params, &data, total_data);
4264 END_PROFILE_NESTED(Trans2_findnotifynext);
4265 break;
4266 case TRANSACT2_MKDIR:
4267 START_PROFILE_NESTED(Trans2_mkdir);
4268 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4269 &params, total_params, &data, total_data);
4270 END_PROFILE_NESTED(Trans2_mkdir);
4271 break;
4273 case TRANSACT2_GET_DFS_REFERRAL:
4274 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4275 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4276 &params, total_params, &data, total_data);
4277 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4278 break;
4279 case TRANSACT2_IOCTL:
4280 START_PROFILE_NESTED(Trans2_ioctl);
4281 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4282 &params, total_params, &data, total_data);
4283 END_PROFILE_NESTED(Trans2_ioctl);
4284 break;
4285 default:
4286 /* Error in request */
4287 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4288 SAFE_FREE(params);
4289 SAFE_FREE(data);
4290 END_PROFILE(SMBtrans2);
4291 srv_signing_trans_stop();
4292 return ERROR_DOS(ERRSRV,ERRerror);
4295 /* As we do not know how many data packets will need to be
4296 returned here the various call_trans2xxxx calls
4297 must send their own. Thus a call_trans2xxx routine only
4298 returns a value other than -1 when it wants to send
4299 an error packet.
4302 srv_signing_trans_stop();
4304 SAFE_FREE(params);
4305 SAFE_FREE(data);
4306 END_PROFILE(SMBtrans2);
4307 return outsize; /* If a correct response was needed the
4308 call_trans2xxx calls have already sent
4309 it. If outsize != -1 then it is returning */
4311 bad_param:
4313 srv_signing_trans_stop();
4314 SAFE_FREE(params);
4315 SAFE_FREE(data);
4316 END_PROFILE(SMBtrans2);
4317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);