r957: Fixup moribund unix extensions mknod code path. Don't add in
[tprouty/samba.git] / source / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6
7    Extensively modified by Andrew Tridgell, 1995
8
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
25
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;
32
33 #define get_file_size(sbuf) ((sbuf).st_size)
34
35 /* given a stat buffer return the allocated size on disk, taking into
36    account sparse files */
37 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
38 {
39         SMB_BIG_UINT ret;
40 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
41         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
42 #else
43         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
44 #endif
45         if (!ret && fsp && fsp->initial_allocation_size)
46                 ret = fsp->initial_allocation_size;
47         ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
48         return ret;
49 }
50
51 /****************************************************************************
52  Utility functions for dealing with extended attributes.
53 ****************************************************************************/
54
55 static const char *prohibited_ea_names[] = {
56         SAMBA_POSIX_INHERITANCE_EA_NAME,
57         SAMBA_XATTR_DOS_ATTRIB,
58         NULL
59 };
60
61 /****************************************************************************
62  Refuse to allow clients to overwrite our private xattrs.
63 ****************************************************************************/
64
65 static BOOL samba_private_attr_name(const char *unix_ea_name)
66 {
67         int i;
68
69         for (i = 0; prohibited_ea_names[i]; i++) {
70                 if (strequal( prohibited_ea_names[i], unix_ea_name))
71                         return True;
72         }
73         return False;
74 }
75
76 struct ea_list {
77         struct ea_list *next, *prev;
78         struct ea_struct ea;
79 };
80
81 /****************************************************************************
82  Get one EA value. Fill in a struct ea_struct.
83 ****************************************************************************/
84
85 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
86                                 const char *fname, char *ea_name, struct ea_struct *pea)
87 {
88         /* Get the value of this xattr. Max size is 64k. */
89         size_t attr_size = 256;
90         char *val = NULL;
91         ssize_t sizeret;
92
93  again:
94
95         val = talloc_realloc(mem_ctx, val, attr_size);
96         if (!val) {
97                 return False;
98         }
99
100         if (fsp && fsp->fd != -1) {
101                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
102         } else {
103                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
104         }
105
106         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
107                 attr_size = 65536;
108                 goto again;
109         }
110
111         if (sizeret == -1) {
112                 return False;
113         }
114
115         DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
116         dump_data(10, val, sizeret);
117
118         pea->flags = 0;
119         if (strnequal(ea_name, "user.", 5)) {
120                 pea->name = &ea_name[5];
121         } else {
122                 pea->name = ea_name;
123         }
124         pea->value.data = val;
125         pea->value.length = (size_t)sizeret;
126         return True;
127 }
128
129 /****************************************************************************
130  Return a linked list of the total EA's. Plus the total size
131 ****************************************************************************/
132
133 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)
134 {
135         /* Get a list of all xattrs. Max namesize is 64k. */
136         size_t ea_namelist_size = 1024;
137         char *ea_namelist;
138         char *p;
139         ssize_t sizeret;
140         int i;
141         struct ea_list *ea_list_head = NULL;
142
143         *pea_total_len = 0;
144
145         if (!lp_ea_support(SNUM(conn))) {
146                 return NULL;
147         }
148
149         for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
150                         ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
151                 if (fsp && fsp->fd != -1) {
152                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
153                 } else {
154                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
155                 }
156
157                 if (sizeret == -1 && errno == ERANGE) {
158                         ea_namelist_size *= 2;
159                 } else {
160                         break;
161                 }
162         }
163
164         if (sizeret == -1)
165                 return NULL;
166
167         DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
168
169         if (sizeret) {
170                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
171                         struct ea_list *listp, *tmp;
172
173                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
174                                 continue;
175                 
176                         listp = talloc(mem_ctx, sizeof(struct ea_list));
177                         if (!listp)
178                                 return NULL;
179
180                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
181                                 return NULL;
182                         }
183
184                         {
185                                 fstring dos_ea_name;
186                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
187                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
188                                 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
189                                         *pea_total_len, dos_ea_name,
190                                         (unsigned int)listp->ea.value.length ));
191                         }
192                         DLIST_ADD_END(ea_list_head, listp, tmp);
193                 }
194                 /* Add on 4 for total length. */
195                 if (*pea_total_len) {
196                         *pea_total_len += 4;
197                 }
198         }
199
200         DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
201         return ea_list_head;
202 }
203
204 /****************************************************************************
205  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
206  that was filled.
207 ****************************************************************************/
208
209 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
210         connection_struct *conn, files_struct *fsp, const char *fname)
211 {
212         unsigned int ret_data_size = 4;
213         char *p = pdata;
214         size_t total_ea_len;
215         TALLOC_CTX *mem_ctx;
216         struct ea_list *ea_list;
217
218         SMB_ASSERT(total_data_size >= 4);
219
220         SIVAL(pdata,0,0);
221         if (!lp_ea_support(SNUM(conn))) {
222                 return 4;
223         }
224         mem_ctx = talloc_init("fill_ea_buffer");
225         if (!mem_ctx) {
226                 return 4;
227         }
228
229         ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
230         if (!ea_list) {
231                 talloc_destroy(mem_ctx);
232                 return 4;
233         }
234
235         if (total_ea_len > total_data_size) {
236                 talloc_destroy(mem_ctx);
237                 return 4;
238         }
239
240         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
241                 size_t dos_namelen;
242                 fstring dos_ea_name;
243                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
244                 dos_namelen = strlen(dos_ea_name);
245                 if (dos_namelen > 255 || dos_namelen == 0) {
246                         break;
247                 }
248                 if (ea_list->ea.value.length > 65535) {
249                         break;
250                 }
251                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
252                         break;
253                 }
254
255                 /* We know we have room. */
256                 SCVAL(p,0,ea_list->ea.flags);
257                 SCVAL(p,1,dos_namelen);
258                 SSVAL(p,2,ea_list->ea.value.length);
259                 fstrcpy(p+4, dos_ea_name);
260                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
261
262                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
263                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
264         }
265
266         ret_data_size = PTR_DIFF(p, pdata);
267         DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
268                         ret_data_size, total_ea_len ));
269         talloc_destroy(mem_ctx);
270         SIVAL(pdata,0,ret_data_size);
271         return ret_data_size;
272 }
273
274 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
275 {
276         size_t total_ea_len = 0;
277         TALLOC_CTX *mem_ctx = NULL;
278
279         if (!lp_ea_support(SNUM(conn))) {
280                 return 0;
281         }
282         mem_ctx = talloc_init("estimate_ea_size");
283         (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
284         talloc_destroy(mem_ctx);
285         return total_ea_len;
286 }
287
288 /****************************************************************************
289  Ensure the EA name is case insensitive by matching any existing EA name.
290 ****************************************************************************/
291
292 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
293 {
294         size_t total_ea_len;
295         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
296         struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
297
298         for (; ea_list; ea_list = ea_list->next) {
299                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
300                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
301                                 &unix_ea_name[5], ea_list->ea.name));
302                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
303                         break;
304                 }
305         }
306         talloc_destroy(mem_ctx);
307 }
308
309 /****************************************************************************
310  Set or delete an extended attribute.
311 ****************************************************************************/
312
313 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
314                         char *pdata, int total_data)
315 {
316         unsigned int namelen;
317         unsigned int ealen;
318         int ret;
319         fstring unix_ea_name;
320
321         if (!lp_ea_support(SNUM(conn))) {
322                 return NT_STATUS_EAS_NOT_SUPPORTED;
323         }
324
325         if (total_data < 8) {
326                 return NT_STATUS_INVALID_PARAMETER;
327         }
328
329         if (IVAL(pdata,0) > total_data) {
330                 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
331                 return NT_STATUS_INVALID_PARAMETER;
332         }
333
334         pdata += 4;
335         namelen = CVAL(pdata,1);
336         ealen = SVAL(pdata,2);
337         pdata += 4;
338         if (total_data < 8 + namelen + 1 + ealen) {
339                 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
340                         (unsigned int)total_data, namelen, ealen));
341                 return NT_STATUS_INVALID_PARAMETER;
342         }
343
344         if (pdata[namelen] != '\0') {
345                 DEBUG(10,("set_ea: ea name not null terminated\n"));
346                 return NT_STATUS_INVALID_PARAMETER;
347         }
348
349         fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
350         pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
351         pdata += (namelen + 1);
352
353         canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
354
355         DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
356         if (ealen) {
357                 DEBUG(10,("set_ea: data :\n"));
358                 dump_data(10, pdata, ealen);
359         }
360
361         if (samba_private_attr_name(unix_ea_name)) {
362                 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
363                 return NT_STATUS_ACCESS_DENIED;
364         }
365
366         if (ealen == 0) {
367                 /* Remove the attribute. */
368                 if (fsp && (fsp->fd != -1)) {
369                         DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
370                                 unix_ea_name, fsp->fsp_name));
371                         ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
372                 } else {
373                         DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
374                                 unix_ea_name, fname));
375                         ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
376                 }
377 #ifdef ENOATTR
378                 /* Removing a non existent attribute always succeeds. */
379                 if (ret == -1 && errno == ENOATTR) {
380                         DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
381                         ret = 0;
382                 }
383 #endif
384         } else {
385                 if (fsp && (fsp->fd != -1)) {
386                         DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
387                                 unix_ea_name, fsp->fsp_name));
388                         ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
389                 } else {
390                         DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
391                                 unix_ea_name, fname));
392                         ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
393                 }
394         }
395
396         if (ret == -1) {
397 #ifdef ENOTSUP
398                 if (errno == ENOTSUP) {
399                         return NT_STATUS_EAS_NOT_SUPPORTED;
400                 }
401 #endif
402                 return map_nt_error_from_unix(errno);
403         }
404
405         return NT_STATUS_OK;
406 }
407
408 /****************************************************************************
409   Send the required number of replies back.
410   We assume all fields other than the data fields are
411   set correctly for the type of call.
412   HACK ! Always assumes smb_setup field is zero.
413 ****************************************************************************/
414
415 static int send_trans2_replies(char *outbuf,
416                         int bufsize,
417                         char *params, 
418                         int paramsize,
419                         char *pdata,
420                         int datasize)
421 {
422         /* As we are using a protocol > LANMAN1 then the max_send
423          variable must have been set in the sessetupX call.
424          This takes precedence over the max_xmit field in the
425          global struct. These different max_xmit variables should
426          be merged as this is now too confusing */
427
428         extern int max_send;
429         int data_to_send = datasize;
430         int params_to_send = paramsize;
431         int useable_space;
432         char *pp = params;
433         char *pd = pdata;
434         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
435         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
436         int data_alignment_offset = 0;
437
438         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
439         
440         set_message(outbuf,10,0,True);
441
442         /* If there genuinely are no parameters or data to send just send the empty packet */
443
444         if(params_to_send == 0 && data_to_send == 0) {
445                 if (!send_smb(smbd_server_fd(),outbuf))
446                         exit_server("send_trans2_replies: send_smb failed.");
447                 return 0;
448         }
449
450         /* When sending params and data ensure that both are nicely aligned */
451         /* Only do this alignment when there is also data to send - else
452                 can cause NT redirector problems. */
453
454         if (((params_to_send % 4) != 0) && (data_to_send != 0))
455                 data_alignment_offset = 4 - (params_to_send % 4);
456
457         /* Space is bufsize minus Netbios over TCP header minus SMB header */
458         /* The alignment_offset is to align the param bytes on an even byte
459                 boundary. NT 4.0 Beta needs this to work correctly. */
460
461         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
462
463         /* useable_space can never be more than max_send minus the alignment offset. */
464
465         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
466
467         while (params_to_send || data_to_send) {
468                 /* Calculate whether we will totally or partially fill this packet */
469
470                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
471
472                 /* We can never send more than useable_space */
473                 /*
474                  * Note that 'useable_space' does not include the alignment offsets,
475                  * but we must include the alignment offsets in the calculation of
476                  * the length of the data we send over the wire, as the alignment offsets
477                  * are sent here. Fix from Marc_Jacobsen@hp.com.
478                  */
479
480                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
481
482                 set_message(outbuf, 10, total_sent_thistime, True);
483
484                 /* Set total params and data to be sent */
485                 SSVAL(outbuf,smb_tprcnt,paramsize);
486                 SSVAL(outbuf,smb_tdrcnt,datasize);
487
488                 /* Calculate how many parameters and data we can fit into
489                  * this packet. Parameters get precedence
490                  */
491
492                 params_sent_thistime = MIN(params_to_send,useable_space);
493                 data_sent_thistime = useable_space - params_sent_thistime;
494                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
495
496                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
497
498                 /* smb_proff is the offset from the start of the SMB header to the
499                         parameter bytes, however the first 4 bytes of outbuf are
500                         the Netbios over TCP header. Thus use smb_base() to subtract
501                         them from the calculation */
502
503                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
504
505                 if(params_sent_thistime == 0)
506                         SSVAL(outbuf,smb_prdisp,0);
507                 else
508                         /* Absolute displacement of param bytes sent in this packet */
509                         SSVAL(outbuf,smb_prdisp,pp - params);
510
511                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
512                 if(data_sent_thistime == 0) {
513                         SSVAL(outbuf,smb_droff,0);
514                         SSVAL(outbuf,smb_drdisp, 0);
515                 } else {
516                         /* The offset of the data bytes is the offset of the
517                                 parameter bytes plus the number of parameters being sent this time */
518                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
519                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
520                         SSVAL(outbuf,smb_drdisp, pd - pdata);
521                 }
522
523                 /* Copy the param bytes into the packet */
524
525                 if(params_sent_thistime)
526                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
527
528                 /* Copy in the data bytes */
529                 if(data_sent_thistime)
530                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
531                                 data_alignment_offset,pd,data_sent_thistime);
532
533                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
534                         params_sent_thistime, data_sent_thistime, useable_space));
535                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
536                         params_to_send, data_to_send, paramsize, datasize));
537
538                 /* Send the packet */
539                 if (!send_smb(smbd_server_fd(),outbuf))
540                         exit_server("send_trans2_replies: send_smb failed.");
541
542                 pp += params_sent_thistime;
543                 pd += data_sent_thistime;
544
545                 params_to_send -= params_sent_thistime;
546                 data_to_send -= data_sent_thistime;
547
548                 /* Sanity check */
549                 if(params_to_send < 0 || data_to_send < 0) {
550                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
551                                 params_to_send, data_to_send));
552                         return -1;
553                 }
554         }
555
556         return 0;
557 }
558
559 /****************************************************************************
560  Reply to a TRANSACT2_OPEN.
561 ****************************************************************************/
562
563 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
564                            char **pparams, int total_params, char **ppdata, int total_data)
565 {
566         char *params = *pparams;
567         int16 open_mode;
568         int16 open_attr;
569         BOOL oplock_request;
570 #if 0
571         BOOL return_additional_info;
572         int16 open_sattr;
573         time_t open_time;
574 #endif
575         int16 open_ofun;
576         int32 open_size;
577         char *pname;
578         pstring fname;
579         SMB_OFF_T size=0;
580         int fmode=0,mtime=0,rmode;
581         SMB_INO_T inode = 0;
582         SMB_STRUCT_STAT sbuf;
583         int smb_action = 0;
584         BOOL bad_path = False;
585         files_struct *fsp;
586         NTSTATUS status;
587
588         /*
589          * Ensure we have enough parameters to perform the operation.
590          */
591
592         if (total_params < 29)
593                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
594
595         open_mode = SVAL(params, 2);
596         open_attr = SVAL(params,6);
597         oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
598 #if 0
599         return_additional_info = BITSETW(params,0);
600         open_sattr = SVAL(params, 4);
601         open_time = make_unix_date3(params+8);
602 #endif
603         open_ofun = SVAL(params,12);
604         open_size = IVAL(params,14);
605         pname = &params[28];
606
607         if (IS_IPC(conn))
608                 return(ERROR_DOS(ERRSRV,ERRaccess));
609
610         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
611         if (!NT_STATUS_IS_OK(status)) {
612                 return ERROR_NT(status);
613         }
614
615         DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
616                 fname,open_mode, open_attr, open_ofun, open_size));
617
618         /* XXXX we need to handle passed times, sattr and flags */
619
620         unix_convert(fname,conn,0,&bad_path,&sbuf);
621     
622         if (!check_name(fname,conn)) {
623                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
624         }
625
626         fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
627                 oplock_request, &rmode,&smb_action);
628       
629         if (!fsp) {
630                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
631         }
632
633         size = get_file_size(sbuf);
634         fmode = dos_mode(conn,fname,&sbuf);
635         mtime = sbuf.st_mtime;
636         inode = sbuf.st_ino;
637         if (fmode & aDIR) {
638                 close_file(fsp,False);
639                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
640         }
641
642         /* Realloc the size of parameters and data we will return */
643         params = Realloc(*pparams, 28);
644         if( params == NULL )
645                 return(ERROR_DOS(ERRDOS,ERRnomem));
646         *pparams = params;
647
648         memset((char *)params,'\0',28);
649         SSVAL(params,0,fsp->fnum);
650         SSVAL(params,2,fmode);
651         put_dos_date2(params,4, mtime);
652         SIVAL(params,8, (uint32)size);
653         SSVAL(params,12,rmode);
654
655         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
656                 smb_action |= EXTENDED_OPLOCK_GRANTED;
657
658         SSVAL(params,18,smb_action);
659
660         /*
661          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
662          */
663         SIVAL(params,20,inode);
664  
665         /* Send the required number of replies */
666         send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
667
668         return -1;
669 }
670
671 /*********************************************************
672  Routine to check if a given string matches exactly.
673  as a special case a mask of "." does NOT match. That
674  is required for correct wildcard semantics
675  Case can be significant or not.
676 **********************************************************/
677
678 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
679 {
680         if (mask[0] == '.' && mask[1] == 0)
681                 return False;
682         if (case_sig)   
683                 return strcmp(str,mask)==0;
684         if (StrCaseCmp(str,mask) != 0) {
685                 return False;
686         }
687         if (ms_has_wild(str)) {
688                 return False;
689         }
690         return True;
691 }
692
693 /****************************************************************************
694  Return the filetype for UNIX extensions.
695 ****************************************************************************/
696
697 static uint32 unix_filetype(mode_t mode)
698 {
699         if(S_ISREG(mode))
700                 return UNIX_TYPE_FILE;
701         else if(S_ISDIR(mode))
702                 return UNIX_TYPE_DIR;
703 #ifdef S_ISLNK
704         else if(S_ISLNK(mode))
705                 return UNIX_TYPE_SYMLINK;
706 #endif
707 #ifdef S_ISCHR
708         else if(S_ISCHR(mode))
709                 return UNIX_TYPE_CHARDEV;
710 #endif
711 #ifdef S_ISBLK
712         else if(S_ISBLK(mode))
713                 return UNIX_TYPE_BLKDEV;
714 #endif
715 #ifdef S_ISFIFO
716         else if(S_ISFIFO(mode))
717                 return UNIX_TYPE_FIFO;
718 #endif
719 #ifdef S_ISSOCK
720         else if(S_ISSOCK(mode))
721                 return UNIX_TYPE_SOCKET;
722 #endif
723
724         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
725         return UNIX_TYPE_UNKNOWN;
726 }
727
728 /****************************************************************************
729  Return the major devicenumber for UNIX extensions.
730 ****************************************************************************/
731
732 static uint32 unix_dev_major(SMB_DEV_T dev)
733 {
734 #if defined(HAVE_DEVICE_MAJOR_FN)
735         return (uint32)major(dev);
736 #else
737         return (uint32)(dev >> 8);
738 #endif
739 }
740
741 /****************************************************************************
742  Return the minor devicenumber for UNIX extensions.
743 ****************************************************************************/
744
745 static uint32 unix_dev_minor(SMB_DEV_T dev)
746 {
747 #if defined(HAVE_DEVICE_MINOR_FN)
748         return (uint32)minor(dev);
749 #else
750         return (uint32)(dev & 0xff);
751 #endif
752 }
753
754 /****************************************************************************
755  Map wire perms onto standard UNIX permissions. Obey share restrictions.
756 ****************************************************************************/
757
758 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
759 {
760         mode_t ret = 0;
761
762         if (perms == SMB_MODE_NO_CHANGE)
763                 return pst->st_mode;
764
765         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
766         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
767         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
768         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
769         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
770         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
771         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
772         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
773         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
774 #ifdef S_ISVTX
775         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
776 #endif
777 #ifdef S_ISGID
778         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
779 #endif
780 #ifdef S_ISUID
781         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
782 #endif
783
784         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
785                 ret &= lp_dir_mask(SNUM(conn));
786                 /* Add in force bits */
787                 ret |= lp_force_dir_mode(SNUM(conn));
788         } else {
789                 /* Apply mode mask */
790                 ret &= lp_create_mask(SNUM(conn));
791                 /* Add in force bits */
792                 ret |= lp_force_create_mode(SNUM(conn));
793         }
794
795         return ret;
796 }
797
798 /****************************************************************************
799  Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
800 ****************************************************************************/
801
802 time_t interpret_long_unix_date(char *p)
803 {
804         DEBUG(10,("interpret_long_unix_date\n"));
805         if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
806            IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
807                 return -1;
808         } else {
809                 return interpret_long_date(p);
810         }
811 }
812
813 /****************************************************************************
814  Get a level dependent lanman2 dir entry.
815 ****************************************************************************/
816
817 static BOOL get_lanman2_dir_entry(connection_struct *conn,
818                                   void *inbuf, void *outbuf,
819                                  char *path_mask,int dirtype,int info_level,
820                                  int requires_resume_key,
821                                  BOOL dont_descend,char **ppdata, 
822                                  char *base_data, int space_remaining, 
823                                  BOOL *out_of_space, BOOL *got_exact_match,
824                                  int *last_name_off)
825 {
826         const char *dname;
827         BOOL found = False;
828         SMB_STRUCT_STAT sbuf;
829         pstring mask;
830         pstring pathreal;
831         pstring fname;
832         char *p, *q, *pdata = *ppdata;
833         uint32 reskey=0;
834         int prev_dirpos=0;
835         int mode=0;
836         SMB_OFF_T file_size = 0;
837         SMB_BIG_UINT allocation_size = 0;
838         uint32 len;
839         time_t mdate=0, adate=0, cdate=0;
840         char *nameptr;
841         BOOL was_8_3;
842         int nt_extmode; /* Used for NT connections instead of mode */
843         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
844
845         *fname = 0;
846         *out_of_space = False;
847         *got_exact_match = False;
848
849         if (!conn->dirptr)
850                 return(False);
851
852         p = strrchr_m(path_mask,'/');
853         if(p != NULL) {
854                 if(p[1] == '\0')
855                         pstrcpy(mask,"*.*");
856                 else
857                         pstrcpy(mask, p+1);
858         } else
859                 pstrcpy(mask, path_mask);
860
861         while (!found) {
862                 BOOL got_match;
863
864                 /* Needed if we run out of space */
865                 prev_dirpos = TellDir(conn->dirptr);
866                 dname = ReadDirName(conn->dirptr);
867
868                 /*
869                  * Due to bugs in NT client redirectors we are not using
870                  * resume keys any more - set them to zero.
871                  * Check out the related comments in findfirst/findnext.
872                  * JRA.
873                  */
874
875                 reskey = 0;
876
877                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
878                         (long)conn->dirptr,TellDir(conn->dirptr)));
879       
880                 if (!dname) 
881                         return(False);
882
883                 pstrcpy(fname,dname);      
884
885                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
886                         got_match = mask_match(fname, mask, conn->case_sensitive);
887
888                 if(!got_match && !mangle_is_8_3(fname, False)) {
889
890                         /*
891                          * It turns out that NT matches wildcards against
892                          * both long *and* short names. This may explain some
893                          * of the wildcard wierdness from old DOS clients
894                          * that some people have been seeing.... JRA.
895                          */
896
897                         pstring newname;
898                         pstrcpy( newname, fname);
899                         mangle_map( newname, True, False, SNUM(conn));
900                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
901                                 got_match = mask_match(newname, mask, conn->case_sensitive);
902                 }
903
904                 if(got_match) {
905                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
906                         if (dont_descend && !isdots)
907                                 continue;
908           
909                         pstrcpy(pathreal,conn->dirpath);
910                         if(needslash)
911                                 pstrcat(pathreal,"/");
912                         pstrcat(pathreal,dname);
913
914                         if (INFO_LEVEL_IS_UNIX(info_level)) {
915                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
916                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
917                                                 pathreal,strerror(errno)));
918                                         continue;
919                                 }
920                         } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
921
922                                 /* Needed to show the msdfs symlinks as 
923                                  * directories */
924
925                                 if(lp_host_msdfs() && 
926                                    lp_msdfs_root(SNUM(conn)) &&
927                                    is_msdfs_link(conn, pathreal, NULL, NULL,
928                                                  &sbuf)) {
929
930                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
931                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
932
933                                 } else {
934
935                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
936                                                 pathreal,strerror(errno)));
937                                         continue;
938                                 }
939                         }
940
941                         mode = dos_mode(conn,pathreal,&sbuf);
942
943                         if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
944                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
945                                 continue;
946                         }
947
948                         file_size = get_file_size(sbuf);
949                         allocation_size = get_allocation_size(NULL,&sbuf);
950                         mdate = sbuf.st_mtime;
951                         adate = sbuf.st_atime;
952                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
953
954                         if (lp_dos_filetime_resolution(SNUM(conn))) {
955                                 cdate &= ~1;
956                                 mdate &= ~1;
957                                 adate &= ~1;
958                         }
959
960                         if(mode & aDIR)
961                                 file_size = 0;
962
963                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
964           
965                         found = True;
966                 }
967         }
968
969         mangle_map(fname,False,True,SNUM(conn));
970
971         p = pdata;
972         nameptr = p;
973
974         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
975
976         switch (info_level) {
977                 case SMB_INFO_STANDARD:
978                         DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
979                         if(requires_resume_key) {
980                                 SIVAL(p,0,reskey);
981                                 p += 4;
982                         }
983                         put_dos_date2(p,l1_fdateCreation,cdate);
984                         put_dos_date2(p,l1_fdateLastAccess,adate);
985                         put_dos_date2(p,l1_fdateLastWrite,mdate);
986                         SIVAL(p,l1_cbFile,(uint32)file_size);
987                         SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
988                         SSVAL(p,l1_attrFile,mode);
989                         p += l1_achName;
990                         nameptr = p;
991                         p += align_string(outbuf, p, 0);
992                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
993                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
994                                 if (len > 2) {
995                                         SCVAL(nameptr, -1, len - 2);
996                                 } else {
997                                         SCVAL(nameptr, -1, 0);
998                                 }
999                         } else {
1000                                 if (len > 1) {
1001                                         SCVAL(nameptr, -1, len - 1);
1002                                 } else {
1003                                         SCVAL(nameptr, -1, 0);
1004                                 }
1005                         }
1006                         p += len;
1007                         break;
1008
1009                 case SMB_INFO_QUERY_EA_SIZE:
1010                         DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1011                         if(requires_resume_key) {
1012                                 SIVAL(p,0,reskey);
1013                                 p += 4;
1014                         }
1015                         put_dos_date2(p,l2_fdateCreation,cdate);
1016                         put_dos_date2(p,l2_fdateLastAccess,adate);
1017                         put_dos_date2(p,l2_fdateLastWrite,mdate);
1018                         SIVAL(p,l2_cbFile,(uint32)file_size);
1019                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1020                         SSVAL(p,l2_attrFile,mode);
1021                         {
1022                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1023                                 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1024                         }
1025                         p += l2_achName;
1026                         nameptr = p - 1;
1027                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1028                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1029                                 if (len > 2) {
1030                                         len -= 2;
1031                                 } else {
1032                                         len = 0;
1033                                 }
1034                         } else {
1035                                 if (len > 1) {
1036                                         len -= 1;
1037                                 } else {
1038                                         len = 0;
1039                                 }
1040                         }
1041                         SCVAL(nameptr,0,len);
1042                         p += len;
1043                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1044                         break;
1045
1046                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1047                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1048                         was_8_3 = mangle_is_8_3(fname, True);
1049                         p += 4;
1050                         SIVAL(p,0,reskey); p += 4;
1051                         put_long_date(p,cdate); p += 8;
1052                         put_long_date(p,adate); p += 8;
1053                         put_long_date(p,mdate); p += 8;
1054                         put_long_date(p,mdate); p += 8;
1055                         SOFF_T(p,0,file_size); p += 8;
1056                         SOFF_T(p,0,allocation_size); p += 8;
1057                         SIVAL(p,0,nt_extmode); p += 4;
1058                         q = p; p += 4; /* q is placeholder for name length. */
1059                         {
1060                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1061                                 SIVAL(p,0,ea_size); /* Extended attributes */
1062                                 p += 4;
1063                         }
1064                         /* Clear the short name buffer. This is
1065                          * IMPORTANT as not doing so will trigger
1066                          * a Win2k client bug. JRA.
1067                          */
1068                         memset(p,'\0',26);
1069                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1070                                 pstring mangled_name;
1071                                 pstrcpy(mangled_name, fname);
1072                                 mangle_map(mangled_name,True,True,SNUM(conn));
1073                                 mangled_name[12] = 0;
1074                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1075                                 SSVAL(p, 0, len);
1076                         } else {
1077                                 SSVAL(p,0,0);
1078                                 *(p+2) = 0;
1079                         }
1080                         p += 2 + 24;
1081                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1082                         SIVAL(q,0,len);
1083                         p += len;
1084                         len = PTR_DIFF(p, pdata);
1085                         len = (len + 3) & ~3;
1086                         SIVAL(pdata,0,len);
1087                         p = pdata + len;
1088                         break;
1089
1090                 case SMB_FIND_FILE_DIRECTORY_INFO:
1091                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1092                         p += 4;
1093                         SIVAL(p,0,reskey); p += 4;
1094                         put_long_date(p,cdate); p += 8;
1095                         put_long_date(p,adate); p += 8;
1096                         put_long_date(p,mdate); p += 8;
1097                         put_long_date(p,mdate); p += 8;
1098                         SOFF_T(p,0,file_size); p += 8;
1099                         SOFF_T(p,0,allocation_size); p += 8;
1100                         SIVAL(p,0,nt_extmode); p += 4;
1101                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1102                         SIVAL(p,0,len);
1103                         p += 4 + len;
1104                         len = PTR_DIFF(p, pdata);
1105                         len = (len + 3) & ~3;
1106                         SIVAL(pdata,0,len);
1107                         p = pdata + len;
1108                         break;
1109       
1110                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1111                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1112                         p += 4;
1113                         SIVAL(p,0,reskey); p += 4;
1114                         put_long_date(p,cdate); p += 8;
1115                         put_long_date(p,adate); p += 8;
1116                         put_long_date(p,mdate); p += 8;
1117                         put_long_date(p,mdate); p += 8;
1118                         SOFF_T(p,0,file_size); p += 8;
1119                         SOFF_T(p,0,allocation_size); p += 8;
1120                         SIVAL(p,0,nt_extmode); p += 4;
1121                         q = p; p += 4; /* q is placeholder for name length. */
1122                         {
1123                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1124                                 SIVAL(p,0,ea_size); /* Extended attributes */
1125                                 p +=4;
1126                         }
1127                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1128                         SIVAL(q, 0, len);
1129                         p += len;
1130
1131                         len = PTR_DIFF(p, pdata);
1132                         len = (len + 3) & ~3;
1133                         SIVAL(pdata,0,len);
1134                         p = pdata + len;
1135                         break;
1136
1137                 case SMB_FIND_FILE_NAMES_INFO:
1138                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1139                         p += 4;
1140                         SIVAL(p,0,reskey); p += 4;
1141                         p += 4;
1142                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1143                            acl on a dir (tridge) */
1144                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1145                         SIVAL(p, -4, len);
1146                         p += len;
1147                         len = PTR_DIFF(p, pdata);
1148                         len = (len + 3) & ~3;
1149                         SIVAL(pdata,0,len);
1150                         p = pdata + len;
1151                         break;
1152
1153                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1154                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1155                         p += 4;
1156                         SIVAL(p,0,reskey); p += 4;
1157                         put_long_date(p,cdate); p += 8;
1158                         put_long_date(p,adate); p += 8;
1159                         put_long_date(p,mdate); p += 8;
1160                         put_long_date(p,mdate); p += 8;
1161                         SOFF_T(p,0,file_size); p += 8;
1162                         SOFF_T(p,0,allocation_size); p += 8;
1163                         SIVAL(p,0,nt_extmode); p += 4;
1164                         q = p; p += 4; /* q is placeholder for name length. */
1165                         {
1166                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1167                                 SIVAL(p,0,ea_size); /* Extended attributes */
1168                                 p +=4;
1169                         }
1170                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1171                         SIVAL(p,0,sbuf.st_dev); p += 4;
1172                         SIVAL(p,0,sbuf.st_ino); p += 4;
1173                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1174                         SIVAL(q, 0, len);
1175                         p += len; 
1176                         len = PTR_DIFF(p, pdata);
1177                         len = (len + 3) & ~3;
1178                         SIVAL(pdata,0,len);
1179                         p = pdata + len;
1180                         break;
1181
1182                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1183                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1184                         was_8_3 = mangle_is_8_3(fname, True);
1185                         p += 4;
1186                         SIVAL(p,0,reskey); p += 4;
1187                         put_long_date(p,cdate); p += 8;
1188                         put_long_date(p,adate); p += 8;
1189                         put_long_date(p,mdate); p += 8;
1190                         put_long_date(p,mdate); p += 8;
1191                         SOFF_T(p,0,file_size); p += 8;
1192                         SOFF_T(p,0,allocation_size); p += 8;
1193                         SIVAL(p,0,nt_extmode); p += 4;
1194                         q = p; p += 4; /* q is placeholder for name length */
1195                         {
1196                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1197                                 SIVAL(p,0,ea_size); /* Extended attributes */
1198                                 p +=4;
1199                         }
1200                         /* Clear the short name buffer. This is
1201                          * IMPORTANT as not doing so will trigger
1202                          * a Win2k client bug. JRA.
1203                          */
1204                         memset(p,'\0',26);
1205                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1206                                 pstring mangled_name;
1207                                 pstrcpy(mangled_name, fname);
1208                                 mangle_map(mangled_name,True,True,SNUM(conn));
1209                                 mangled_name[12] = 0;
1210                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1211                                 SSVAL(p, 0, len);
1212                         } else {
1213                                 SSVAL(p,0,0);
1214                                 *(p+2) = 0;
1215                         }
1216                         p += 26;
1217                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1218                         SIVAL(p,0,sbuf.st_dev); p += 4;
1219                         SIVAL(p,0,sbuf.st_ino); p += 4;
1220                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1221                         SIVAL(q,0,len);
1222                         p += len;
1223                         len = PTR_DIFF(p, pdata);
1224                         len = (len + 3) & ~3;
1225                         SIVAL(pdata,0,len);
1226                         p = pdata + len;
1227                         break;
1228
1229                 /* CIFS UNIX Extension. */
1230
1231                 case SMB_FIND_FILE_UNIX:
1232                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1233                         p+= 4;
1234                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1235
1236                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1237                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1238                         p+= 8;
1239
1240                         SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1241                         p+= 8;
1242
1243                         put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1244                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1245                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1246                         p+= 24;
1247
1248                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1249                         SIVAL(p,4,0);
1250                         p+= 8;
1251
1252                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1253                         SIVAL(p,4,0);
1254                         p+= 8;
1255
1256                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1257                         p+= 4;
1258
1259                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1260                         SIVAL(p,4,0);
1261                         p+= 8;
1262
1263                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1264                         SIVAL(p,4,0);
1265                         p+= 8;
1266
1267                         SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1268                         p+= 8;
1269
1270                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1271                         SIVAL(p,4,0);
1272                         p+= 8;
1273
1274                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1275                         SIVAL(p,4,0);
1276                         p+= 8;
1277
1278                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1279                         p += len;
1280
1281                         len = PTR_DIFF(p, pdata);
1282                         len = (len + 3) & ~3;
1283                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1284                         p = pdata + len;
1285                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1286
1287                         break;
1288
1289                 default:      
1290                         return(False);
1291         }
1292
1293
1294         if (PTR_DIFF(p,pdata) > space_remaining) {
1295                 /* Move the dirptr back to prev_dirpos */
1296                 SeekDir(conn->dirptr, prev_dirpos);
1297                 *out_of_space = True;
1298                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1299                 return False; /* Not finished - just out of space */
1300         }
1301
1302         /* Setup the last_filename pointer, as an offset from base_data */
1303         *last_name_off = PTR_DIFF(nameptr,base_data);
1304         /* Advance the data pointer to the next slot */
1305         *ppdata = p;
1306
1307         return(found);
1308 }
1309
1310 /****************************************************************************
1311  Reply to a TRANS2_FINDFIRST.
1312 ****************************************************************************/
1313
1314 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1315                                 char **pparams, int total_params, char **ppdata, int total_data)
1316 {
1317         /* We must be careful here that we don't return more than the
1318                 allowed number of data bytes. If this means returning fewer than
1319                 maxentries then so be it. We assume that the redirector has
1320                 enough room for the fixed number of parameter bytes it has
1321                 requested. */
1322         uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1323         char *params = *pparams;
1324         char *pdata = *ppdata;
1325         int dirtype = SVAL(params,0);
1326         int maxentries = SVAL(params,2);
1327         BOOL close_after_first = BITSETW(params+4,0);
1328         BOOL close_if_end = BITSETW(params+4,1);
1329         BOOL requires_resume_key = BITSETW(params+4,2);
1330         int info_level = SVAL(params,6);
1331         pstring directory;
1332         pstring mask;
1333         char *p, *wcard;
1334         int last_name_off=0;
1335         int dptr_num = -1;
1336         int numentries = 0;
1337         int i;
1338         BOOL finished = False;
1339         BOOL dont_descend = False;
1340         BOOL out_of_space = False;
1341         int space_remaining;
1342         BOOL bad_path = False;
1343         SMB_STRUCT_STAT sbuf;
1344         NTSTATUS ntstatus = NT_STATUS_OK;
1345
1346         if (total_params < 12)
1347                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1348
1349         *directory = *mask = 0;
1350
1351         DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1352 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1353                 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1354                 info_level, max_data_bytes));
1355   
1356         switch (info_level) {
1357                 case SMB_INFO_STANDARD:
1358                 case SMB_INFO_QUERY_EA_SIZE:
1359                 case SMB_FIND_FILE_DIRECTORY_INFO:
1360                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1361                 case SMB_FIND_FILE_NAMES_INFO:
1362                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1363                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1364                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1365                         break;
1366                 case SMB_FIND_FILE_UNIX:
1367                         if (!lp_unix_extensions())
1368                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1369                         break;
1370                 default:
1371                         return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1372         }
1373
1374         srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1375         if (!NT_STATUS_IS_OK(ntstatus)) {
1376                 return ERROR_NT(ntstatus);
1377         }
1378
1379         RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1380
1381         unix_convert(directory,conn,0,&bad_path,&sbuf);
1382         if(!check_name(directory,conn)) {
1383                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1384         }
1385
1386         p = strrchr_m(directory,'/');
1387         if(p == NULL) {
1388                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1389                 if((directory[0] == '.') && (directory[1] == '\0'))
1390                         pstrcpy(mask,"*");
1391                 else
1392                         pstrcpy(mask,directory);
1393                 pstrcpy(directory,"./");
1394         } else {
1395                 pstrcpy(mask,p+1);
1396                 *p = 0;
1397         }
1398
1399         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1400
1401         pdata = Realloc(*ppdata, max_data_bytes + 1024);
1402         if( pdata == NULL )
1403                 return(ERROR_DOS(ERRDOS,ERRnomem));
1404
1405         *ppdata = pdata;
1406         memset((char *)pdata,'\0',max_data_bytes + 1024);
1407
1408         /* Realloc the params space */
1409         params = Realloc(*pparams, 10);
1410         if (params == NULL)
1411                 return ERROR_DOS(ERRDOS,ERRnomem);
1412         *pparams = params;
1413
1414         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1415         if (dptr_num < 0)
1416                 return(UNIXERROR(ERRDOS,ERRbadfile));
1417
1418         /* Save the wildcard match and attribs we are using on this directory - 
1419                 needed as lanman2 assumes these are being saved between calls */
1420
1421         if(!(wcard = strdup(mask))) {
1422                 dptr_close(&dptr_num);
1423                 return ERROR_DOS(ERRDOS,ERRnomem);
1424         }
1425
1426         dptr_set_wcard(dptr_num, wcard);
1427         dptr_set_attr(dptr_num, dirtype);
1428
1429         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1430
1431         /* We don't need to check for VOL here as this is returned by 
1432                 a different TRANS2 call. */
1433   
1434         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1435         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1436                 dont_descend = True;
1437     
1438         p = pdata;
1439         space_remaining = max_data_bytes;
1440         out_of_space = False;
1441
1442         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1443                 BOOL got_exact_match = False;
1444
1445                 /* this is a heuristic to avoid seeking the dirptr except when 
1446                         absolutely necessary. It allows for a filename of about 40 chars */
1447                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1448                         out_of_space = True;
1449                         finished = False;
1450                 } else {
1451                         finished = !get_lanman2_dir_entry(conn,
1452                                         inbuf, outbuf,
1453                                         mask,dirtype,info_level,
1454                                         requires_resume_key,dont_descend,
1455                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1456                                         &last_name_off);
1457                 }
1458
1459                 if (finished && out_of_space)
1460                         finished = False;
1461
1462                 if (!finished && !out_of_space)
1463                         numentries++;
1464
1465                 /*
1466                  * As an optimisation if we know we aren't looking
1467                  * for a wildcard name (ie. the name matches the wildcard exactly)
1468                  * then we can finish on any (first) match.
1469                  * This speeds up large directory searches. JRA.
1470                  */
1471
1472                 if(got_exact_match)
1473                         finished = True;
1474
1475                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1476         }
1477   
1478         /* Check if we can close the dirptr */
1479         if(close_after_first || (finished && close_if_end)) {
1480                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1481                 dptr_close(&dptr_num);
1482         }
1483
1484         /* 
1485          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1486          * from observation of NT.
1487          */
1488
1489         if(numentries == 0) {
1490                 dptr_close(&dptr_num);
1491                 return ERROR_DOS(ERRDOS,ERRbadfile);
1492         }
1493
1494         /* At this point pdata points to numentries directory entries. */
1495
1496         /* Set up the return parameter block */
1497         SSVAL(params,0,dptr_num);
1498         SSVAL(params,2,numentries);
1499         SSVAL(params,4,finished);
1500         SSVAL(params,6,0); /* Never an EA error */
1501         SSVAL(params,8,last_name_off);
1502
1503         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1504
1505         if ((! *directory) && dptr_path(dptr_num))
1506                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1507
1508         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1509                 smb_fn_name(CVAL(inbuf,smb_com)), 
1510                 mask, directory, dirtype, numentries ) );
1511
1512         /* 
1513          * Force a name mangle here to ensure that the
1514          * mask as an 8.3 name is top of the mangled cache.
1515          * The reasons for this are subtle. Don't remove
1516          * this code unless you know what you are doing
1517          * (see PR#13758). JRA.
1518          */
1519
1520         if(!mangle_is_8_3_wildcards( mask, False))
1521                 mangle_map(mask, True, True, SNUM(conn));
1522
1523         return(-1);
1524 }
1525
1526 /****************************************************************************
1527  Reply to a TRANS2_FINDNEXT.
1528 ****************************************************************************/
1529
1530 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1531                                         char **pparams, int total_params, char **ppdata, int total_data)
1532 {
1533         /* We must be careful here that we don't return more than the
1534                 allowed number of data bytes. If this means returning fewer than
1535                 maxentries then so be it. We assume that the redirector has
1536                 enough room for the fixed number of parameter bytes it has
1537                 requested. */
1538         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1539         char *params = *pparams;
1540         char *pdata = *ppdata;
1541         int dptr_num = SVAL(params,0);
1542         int maxentries = SVAL(params,2);
1543         uint16 info_level = SVAL(params,4);
1544         uint32 resume_key = IVAL(params,6);
1545         BOOL close_after_request = BITSETW(params+10,0);
1546         BOOL close_if_end = BITSETW(params+10,1);
1547         BOOL requires_resume_key = BITSETW(params+10,2);
1548         BOOL continue_bit = BITSETW(params+10,3);
1549         pstring resume_name;
1550         pstring mask;
1551         pstring directory;
1552         char *p;
1553         uint16 dirtype;
1554         int numentries = 0;
1555         int i, last_name_off=0;
1556         BOOL finished = False;
1557         BOOL dont_descend = False;
1558         BOOL out_of_space = False;
1559         int space_remaining;
1560         NTSTATUS ntstatus = NT_STATUS_OK;
1561
1562         if (total_params < 12)
1563                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1564
1565         *mask = *directory = *resume_name = 0;
1566
1567         srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1568         if (!NT_STATUS_IS_OK(ntstatus)) {
1569                 return ERROR_NT(ntstatus);
1570         }
1571
1572         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1573 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1574 resume_key = %d resume name = %s continue=%d level = %d\n",
1575                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1576                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1577
1578         switch (info_level) {
1579                 case SMB_INFO_STANDARD:
1580                 case SMB_INFO_QUERY_EA_SIZE:
1581                 case SMB_FIND_FILE_DIRECTORY_INFO:
1582                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1583                 case SMB_FIND_FILE_NAMES_INFO:
1584                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1585                         break;
1586                 case SMB_FIND_FILE_UNIX:
1587                         if (!lp_unix_extensions())
1588                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1589                         break;
1590                 default:
1591                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1592         }
1593
1594         pdata = Realloc( *ppdata, max_data_bytes + 1024);
1595         if(pdata == NULL)
1596                 return ERROR_DOS(ERRDOS,ERRnomem);
1597
1598         *ppdata = pdata;
1599         memset((char *)pdata,'\0',max_data_bytes + 1024);
1600
1601         /* Realloc the params space */
1602         params = Realloc(*pparams, 6*SIZEOFWORD);
1603         if( params == NULL )
1604                 return ERROR_DOS(ERRDOS,ERRnomem);
1605
1606         *pparams = params;
1607
1608         /* Check that the dptr is valid */
1609         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1610                 return ERROR_DOS(ERRDOS,ERRnofiles);
1611
1612         string_set(&conn->dirpath,dptr_path(dptr_num));
1613
1614         /* Get the wildcard mask from the dptr */
1615         if((p = dptr_wcard(dptr_num))== NULL) {
1616                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1617                 return ERROR_DOS(ERRDOS,ERRnofiles);
1618         }
1619
1620         pstrcpy(mask, p);
1621         pstrcpy(directory,conn->dirpath);
1622
1623         /* Get the attr mask from the dptr */
1624         dirtype = dptr_attr(dptr_num);
1625
1626         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1627                 dptr_num, mask, dirtype, 
1628                 (long)conn->dirptr,
1629                 TellDir(conn->dirptr)));
1630
1631         /* We don't need to check for VOL here as this is returned by 
1632                 a different TRANS2 call. */
1633
1634         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1635         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1636                 dont_descend = True;
1637     
1638         p = pdata;
1639         space_remaining = max_data_bytes;
1640         out_of_space = False;
1641
1642         /* 
1643          * Seek to the correct position. We no longer use the resume key but
1644          * depend on the last file name instead.
1645          */
1646
1647         if(requires_resume_key && *resume_name && !continue_bit) {
1648
1649                 /*
1650                  * Fix for NT redirector problem triggered by resume key indexes
1651                  * changing between directory scans. We now return a resume key of 0
1652                  * and instead look for the filename to continue from (also given
1653                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1654                  * findfirst/findnext (as is usual) then the directory pointer
1655                  * should already be at the correct place. Check this by scanning
1656                  * backwards looking for an exact (ie. case sensitive) filename match. 
1657                  * If we get to the beginning of the directory and haven't found it then scan
1658                  * forwards again looking for a match. JRA.
1659                  */
1660
1661                 int current_pos, start_pos;
1662                 const char *dname = NULL;
1663                 pstring dname_pstring;
1664                 void *dirptr = conn->dirptr;
1665                 start_pos = TellDir(dirptr);
1666                 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1667                         DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1668
1669                         SeekDir(dirptr, current_pos);
1670                         dname = ReadDirName(dirptr);
1671                         if (dname) {
1672                                 /*
1673                                  * Remember, mangle_map is called by
1674                                  * get_lanman2_dir_entry(), so the resume name
1675                                  * could be mangled. Ensure we do the same
1676                                  * here.
1677                                  */
1678                                 
1679                                 /* make sure we get a copy that mangle_map can modify */
1680
1681                                 pstrcpy(dname_pstring, dname);
1682                                 mangle_map( dname_pstring, False, True, SNUM(conn));
1683                                 
1684                                 if(strcsequal( resume_name, dname_pstring)) {
1685                                         SeekDir(dirptr, current_pos+1);
1686                                         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1687                                         break;
1688                                 }
1689                         }
1690                 }
1691
1692                 /*
1693                  * Scan forward from start if not found going backwards.
1694                  */
1695
1696                 if(current_pos < 0) {
1697                         DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1698                         SeekDir(dirptr, start_pos);
1699                         for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1700
1701                                 /*
1702                                  * Remember, mangle_map is called by
1703                                  * get_lanman2_dir_entry(), so the resume name
1704                                  * could be mangled. Ensure we do the same
1705                                  * here.
1706                                  */
1707
1708                                 if(dname) {
1709                                         /* make sure we get a copy that mangle_map can modify */
1710                                         
1711                                         pstrcpy(dname_pstring, dname);
1712                                         mangle_map(dname_pstring, False, True, SNUM(conn));
1713
1714                                         if(strcsequal( resume_name, dname_pstring)) {
1715                                                 SeekDir(dirptr, current_pos+1);
1716                                                 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1717                                                 break;
1718                                         }
1719                                 }
1720                         } /* end for */
1721                 } /* end if current_pos */
1722         } /* end if requires_resume_key && !continue_bit */
1723
1724         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1725                 BOOL got_exact_match = False;
1726
1727                 /* this is a heuristic to avoid seeking the dirptr except when 
1728                         absolutely necessary. It allows for a filename of about 40 chars */
1729                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1730                         out_of_space = True;
1731                         finished = False;
1732                 } else {
1733                         finished = !get_lanman2_dir_entry(conn,
1734                                                 inbuf, outbuf,
1735                                                 mask,dirtype,info_level,
1736                                                 requires_resume_key,dont_descend,
1737                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1738                                                 &last_name_off);
1739                 }
1740
1741                 if (finished && out_of_space)
1742                         finished = False;
1743
1744                 if (!finished && !out_of_space)
1745                         numentries++;
1746
1747                 /*
1748                  * As an optimisation if we know we aren't looking
1749                  * for a wildcard name (ie. the name matches the wildcard exactly)
1750                  * then we can finish on any (first) match.
1751                  * This speeds up large directory searches. JRA.
1752                  */
1753
1754                 if(got_exact_match)
1755                         finished = True;
1756
1757                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1758         }
1759   
1760         /* Check if we can close the dirptr */
1761         if(close_after_request || (finished && close_if_end)) {
1762                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1763                 dptr_close(&dptr_num); /* This frees up the saved mask */
1764         }
1765
1766         /* Set up the return parameter block */
1767         SSVAL(params,0,numentries);
1768         SSVAL(params,2,finished);
1769         SSVAL(params,4,0); /* Never an EA error */
1770         SSVAL(params,6,last_name_off);
1771
1772         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1773
1774         if ((! *directory) && dptr_path(dptr_num))
1775                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1776
1777         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1778                 smb_fn_name(CVAL(inbuf,smb_com)), 
1779                 mask, directory, dirtype, numentries ) );
1780
1781         return(-1);
1782 }
1783
1784 /****************************************************************************
1785  Reply to a TRANS2_QFSINFO (query filesystem info).
1786 ****************************************************************************/
1787
1788 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, 
1789                         int length, int bufsize,
1790                         char **pparams, int total_params, char **ppdata, int total_data)
1791 {
1792         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1793         char *pdata = *ppdata;
1794         char *params = *pparams;
1795         uint16 info_level = SVAL(params,0);
1796         int data_len, len;
1797         SMB_STRUCT_STAT st;
1798         char *vname = volume_label(SNUM(conn));
1799         int snum = SNUM(conn);
1800         char *fstype = lp_fstype(SNUM(conn));
1801         int quota_flag = 0;
1802
1803         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1804
1805         if(SMB_VFS_STAT(conn,".",&st)!=0) {
1806                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1807                 return ERROR_DOS(ERRSRV,ERRinvdevice);
1808         }
1809
1810         pdata = Realloc(*ppdata, max_data_bytes + 1024);
1811         if ( pdata == NULL )
1812                 return ERROR_DOS(ERRDOS,ERRnomem);
1813
1814         *ppdata = pdata;
1815         memset((char *)pdata,'\0',max_data_bytes + 1024);
1816
1817         switch (info_level) {
1818                 case SMB_INFO_ALLOCATION:
1819                 {
1820                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1821                         data_len = 18;
1822                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); 
1823                         block_size = lp_block_size(snum);
1824                         if (bsize < block_size) {
1825                                 SMB_BIG_UINT factor = block_size/bsize;
1826                                 bsize = block_size;
1827                                 dsize /= factor;
1828                                 dfree /= factor;
1829                         }
1830                         if (bsize > block_size) {
1831                                 SMB_BIG_UINT factor = bsize/block_size;
1832                                 bsize = block_size;
1833                                 dsize *= factor;
1834                                 dfree *= factor;
1835                         }
1836                         bytes_per_sector = 512;
1837                         sectors_per_unit = bsize/bytes_per_sector;
1838
1839                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1840 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1841                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1842
1843                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1844                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1845                         SIVAL(pdata,l1_cUnit,dsize);
1846                         SIVAL(pdata,l1_cUnitAvail,dfree);
1847                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
1848                         break;
1849                 }
1850
1851                 case SMB_INFO_VOLUME:
1852                         /* Return volume name */
1853                         /* 
1854                          * Add volume serial number - hash of a combination of
1855                          * the called hostname and the service name.
1856                          */
1857                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1858                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1859                         SCVAL(pdata,l2_vol_cch,len);
1860                         data_len = l2_vol_szVolLabel + len;
1861                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1862                                 (unsigned)st.st_ctime, len, vname));
1863                         break;
1864
1865                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1866                 case SMB_FS_ATTRIBUTE_INFORMATION:
1867
1868
1869 #if defined(HAVE_SYS_QUOTAS)
1870                         quota_flag = FILE_VOLUME_QUOTAS;
1871 #endif
1872
1873                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1874                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1875                                 quota_flag); /* FS ATTRIBUTES */
1876
1877                         SIVAL(pdata,4,255); /* Max filename component length */
1878                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1879                                 and will think we can't do long filenames */
1880                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1881                         SIVAL(pdata,8,len);
1882                         data_len = 12 + len;
1883                         break;
1884
1885                 case SMB_QUERY_FS_LABEL_INFO:
1886                 case SMB_FS_LABEL_INFORMATION:
1887                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1888                         data_len = 4 + len;
1889                         SIVAL(pdata,0,len);
1890                         break;
1891
1892                 case SMB_QUERY_FS_VOLUME_INFO:      
1893                 case SMB_FS_VOLUME_INFORMATION:
1894
1895                         /* 
1896                          * Add volume serial number - hash of a combination of
1897                          * the called hostname and the service name.
1898                          */
1899                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1900                                 (str_checksum(local_machine)<<16));
1901
1902                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1903                         SIVAL(pdata,12,len);
1904                         data_len = 18+len;
1905                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1906                                 (int)strlen(vname),vname, lp_servicename(snum)));
1907                         break;
1908
1909                 case SMB_QUERY_FS_SIZE_INFO:
1910                 case SMB_FS_SIZE_INFORMATION:
1911                 {
1912                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1913                         data_len = 24;
1914                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1915                         block_size = lp_block_size(snum);
1916                         if (bsize < block_size) {
1917                                 SMB_BIG_UINT factor = block_size/bsize;
1918                                 bsize = block_size;
1919                                 dsize /= factor;
1920                                 dfree /= factor;
1921                         }
1922                         if (bsize > block_size) {
1923                                 SMB_BIG_UINT factor = bsize/block_size;
1924                                 bsize = block_size;
1925                                 dsize *= factor;
1926                                 dfree *= factor;
1927                         }
1928                         bytes_per_sector = 512;
1929                         sectors_per_unit = bsize/bytes_per_sector;
1930                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1931 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1932                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1933                         SBIG_UINT(pdata,0,dsize);
1934                         SBIG_UINT(pdata,8,dfree);
1935                         SIVAL(pdata,16,sectors_per_unit);
1936                         SIVAL(pdata,20,bytes_per_sector);
1937                         break;
1938                 }
1939
1940                 case SMB_FS_FULL_SIZE_INFORMATION:
1941                 {
1942                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1943                         data_len = 32;
1944                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1945                         block_size = lp_block_size(snum);
1946                         if (bsize < block_size) {
1947                                 SMB_BIG_UINT factor = block_size/bsize;
1948                                 bsize = block_size;
1949                                 dsize /= factor;
1950                                 dfree /= factor;
1951                         }
1952                         if (bsize > block_size) {
1953                                 SMB_BIG_UINT factor = bsize/block_size;
1954                                 bsize = block_size;
1955                                 dsize *= factor;
1956                                 dfree *= factor;
1957                         }
1958                         bytes_per_sector = 512;
1959                         sectors_per_unit = bsize/bytes_per_sector;
1960                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1962                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1963                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1964                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1965                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1966                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1967                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1968                         break;
1969                 }
1970
1971                 case SMB_QUERY_FS_DEVICE_INFO:
1972                 case SMB_FS_DEVICE_INFORMATION:
1973                         data_len = 8;
1974                         SIVAL(pdata,0,0); /* dev type */
1975                         SIVAL(pdata,4,0); /* characteristics */
1976                         break;
1977
1978 #ifdef HAVE_SYS_QUOTAS
1979                 case SMB_FS_QUOTA_INFORMATION:
1980                 /* 
1981                  * what we have to send --metze:
1982                  *
1983                  * Unknown1:            24 NULL bytes
1984                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1985                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
1986                  * Quota Flags:         2 byte :
1987                  * Unknown3:            6 NULL bytes
1988                  *
1989                  * 48 bytes total
1990                  * 
1991                  * details for Quota Flags:
1992                  * 
1993                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1994                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
1995                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1996                  * 0x0001 Enable Quotas: enable quota for this fs
1997                  *
1998                  */
1999                 {
2000                         /* we need to fake up a fsp here,
2001                          * because its not send in this call
2002                          */
2003                         files_struct fsp;
2004                         SMB_NTQUOTA_STRUCT quotas;
2005                         
2006                         ZERO_STRUCT(fsp);
2007                         ZERO_STRUCT(quotas);
2008                         
2009                         fsp.conn = conn;
2010                         fsp.fnum = -1;
2011                         fsp.fd = -1;
2012                         
2013                         /* access check */
2014                         if (current_user.uid != 0) {
2015                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2016                                         lp_servicename(SNUM(conn)),conn->user));
2017                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2018                         }
2019                         
2020                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2021                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2022                                 return ERROR_DOS(ERRSRV,ERRerror);
2023                         }
2024
2025                         data_len = 48;
2026
2027                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2028                 
2029                         /* Unknown1 24 NULL bytes*/
2030                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2031                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2032                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2033                 
2034                         /* Default Soft Quota 8 bytes */
2035                         SBIG_UINT(pdata,24,quotas.softlim);
2036
2037                         /* Default Hard Quota 8 bytes */
2038                         SBIG_UINT(pdata,32,quotas.hardlim);
2039         
2040                         /* Quota flag 2 bytes */
2041                         SSVAL(pdata,40,quotas.qflags);
2042                 
2043                         /* Unknown3 6 NULL bytes */
2044                         SSVAL(pdata,42,0);
2045                         SIVAL(pdata,44,0);
2046                         
2047                         break;
2048                 }
2049 #endif /* HAVE_SYS_QUOTAS */
2050                 case SMB_FS_OBJECTID_INFORMATION:
2051                         data_len = 64;
2052                         break;
2053
2054                 /*
2055                  * Query the version and capabilities of the CIFS UNIX extensions
2056                  * in use.
2057                  */
2058
2059                 case SMB_QUERY_CIFS_UNIX_INFO:
2060                         if (!lp_unix_extensions())
2061                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2062                         data_len = 12;
2063                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2064                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2065                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2066                         break;
2067
2068                 case SMB_MAC_QUERY_FS_INFO:
2069                         /*
2070                          * Thursby MAC extension... ONLY on NTFS filesystems
2071                          * once we do streams then we don't need this
2072                          */
2073                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2074                                 data_len = 88;
2075                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2076                                 break;
2077                         }
2078                         /* drop through */
2079                 default:
2080                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2081         }
2082
2083
2084         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2085
2086         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2087
2088         return -1;
2089 }
2090
2091 #ifdef HAVE_SYS_QUOTAS
2092 /****************************************************************************
2093  Reply to a TRANS2_SETFSINFO (set filesystem info).
2094 ****************************************************************************/
2095
2096 static int call_trans2setfsinfo(connection_struct *conn,
2097                                 char *inbuf, char *outbuf, int length, int bufsize,
2098                                 char **pparams, int total_params, char **ppdata, int total_data)
2099 {
2100         char *pdata = *ppdata;
2101         char *params = *pparams;
2102         files_struct *fsp = NULL;
2103         uint16 info_level;
2104         int outsize;
2105         SMB_NTQUOTA_STRUCT quotas;
2106         
2107         ZERO_STRUCT(quotas);
2108
2109         DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2110
2111         /* access check */
2112         if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2113                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2114                         lp_servicename(SNUM(conn)),conn->user));
2115                 return ERROR_DOS(ERRSRV,ERRaccess);
2116         }
2117
2118         /*  */
2119         if (total_params < 4) {
2120                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2121                         total_params));
2122                 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2123         }
2124
2125         fsp = file_fsp(params,0);
2126
2127         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2128                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2129                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2130         }
2131
2132         info_level = SVAL(params,2);
2133
2134         switch(info_level) {
2135                 case SMB_FS_QUOTA_INFORMATION:
2136                         /* note: normaly there're 48 bytes,
2137                          * but we didn't use the last 6 bytes for now 
2138                          * --metze 
2139                          */
2140                         if (total_data < 42) {
2141                                 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2142                                         total_data));
2143                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2144                         }
2145                         
2146                         /* unknown_1 24 NULL bytes in pdata*/
2147                 
2148                         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2149                         quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2150 #ifdef LARGE_SMB_OFF_T
2151                         quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2152 #else /* LARGE_SMB_OFF_T */
2153                         if ((IVAL(pdata,28) != 0)&&
2154                                 ((quotas.softlim != 0xFFFFFFFF)||
2155                                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2156                                 /* more than 32 bits? */
2157                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2158                         }
2159 #endif /* LARGE_SMB_OFF_T */
2160                 
2161                         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2162                         quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2163 #ifdef LARGE_SMB_OFF_T
2164                         quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2165 #else /* LARGE_SMB_OFF_T */
2166                         if ((IVAL(pdata,36) != 0)&&
2167                                 ((quotas.hardlim != 0xFFFFFFFF)||
2168                                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2169                                 /* more than 32 bits? */
2170                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2171                         }
2172 #endif /* LARGE_SMB_OFF_T */
2173                 
2174                         /* quota_flags 2 bytes **/
2175                         quotas.qflags = SVAL(pdata,40);
2176                 
2177                         /* unknown_2 6 NULL bytes follow*/
2178                 
2179                         /* now set the quotas */
2180                         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2181                                 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2182                                 return ERROR_DOS(ERRSRV,ERRerror);
2183                         }
2184                         
2185                         break;
2186                 default:
2187                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2188                                 info_level));
2189                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2190                         break;
2191         }
2192
2193         /* 
2194          * sending this reply works fine, 
2195          * but I'm not sure it's the same 
2196          * like windows do...
2197          * --metze
2198          */ 
2199         outsize = set_message(outbuf,10,0,True);
2200
2201         return outsize;
2202 }
2203 #endif /* HAVE_SYS_QUOTAS */
2204
2205 /****************************************************************************
2206  *  Utility function to set bad path error.
2207  ****************************************************************************/
2208
2209 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2210 {
2211         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2212                         err, (int)bad_path ));
2213
2214         if(err == ENOENT) {
2215                 if (bad_path) {
2216                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2217                 } else {
2218                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2219                 }
2220         }
2221         return UNIXERROR(def_class,def_code);
2222 }
2223
2224 /****************************************************************************
2225  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2226  file name or file id).
2227 ****************************************************************************/
2228
2229 static int call_trans2qfilepathinfo(connection_struct *conn,
2230                                     char *inbuf, char *outbuf, int length, 
2231                                     int bufsize,
2232                                         char **pparams, int total_params, char **ppdata, int total_data)
2233 {
2234         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2235         char *params = *pparams;
2236         char *pdata = *ppdata;
2237         uint16 tran_call = SVAL(inbuf, smb_setup0);
2238         uint16 info_level;
2239         int mode=0;
2240         SMB_OFF_T file_size=0;
2241         SMB_BIG_UINT allocation_size=0;
2242         unsigned int data_size;
2243         unsigned int param_size = 2;
2244         SMB_STRUCT_STAT sbuf;
2245         pstring fname, dos_fname;
2246         char *fullpathname;
2247         char *base_name;
2248         char *p;
2249         SMB_OFF_T pos = 0;
2250         BOOL bad_path = False;
2251         BOOL delete_pending = False;
2252         int len;
2253         time_t c_time;
2254         files_struct *fsp = NULL;
2255         uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2256
2257         if (!params)
2258                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2259
2260         if (tran_call == TRANSACT2_QFILEINFO) {
2261                 if (total_params < 4)
2262                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2263
2264                 fsp = file_fsp(params,0);
2265                 info_level = SVAL(params,2);
2266
2267                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2268
2269                 if(fsp && (fsp->fake_file_handle)) {
2270                         /*
2271                          * This is actually for the QUOTA_FAKE_FILE --metze
2272                          */
2273                                                 
2274                         pstrcpy(fname, fsp->fsp_name);
2275                         unix_convert(fname,conn,0,&bad_path,&sbuf);
2276                         if (!check_name(fname,conn)) {
2277                                 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2278                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2279                         }
2280                         
2281                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2282                         /*
2283                          * This is actually a QFILEINFO on a directory
2284                          * handle (returned from an NT SMB). NT5.0 seems
2285                          * to do this call. JRA.
2286                          */
2287                         pstrcpy(fname, fsp->fsp_name);
2288                         unix_convert(fname,conn,0,&bad_path,&sbuf);
2289                         if (!check_name(fname,conn)) {
2290                                 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2291                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2292                         }
2293                   
2294                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2295                                 /* Always do lstat for UNIX calls. */
2296                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2297                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2298                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2299                                 }
2300                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2301                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2302                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2303                         }
2304
2305                         delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2306                 } else {
2307                         /*
2308                          * Original code - this is an open file.
2309                          */
2310                         CHECK_FSP(fsp,conn);
2311
2312                         pstrcpy(fname, fsp->fsp_name);
2313                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2314                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2315                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2316                         }
2317                         pos = fsp->position_information;
2318                         delete_pending = fsp->delete_on_close;
2319                         desired_access = fsp->desired_access;
2320                 }
2321         } else {
2322                 NTSTATUS status = NT_STATUS_OK;
2323
2324                 /* qpathinfo */
2325                 if (total_params < 6)
2326                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2327
2328                 info_level = SVAL(params,0);
2329
2330                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2331
2332                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2333                 if (!NT_STATUS_IS_OK(status)) {
2334                         return ERROR_NT(status);
2335                 }
2336
2337                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2338
2339                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2340                 if (!check_name(fname,conn)) {
2341                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2342                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2343                 }
2344
2345                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2346                         /* Always do lstat for UNIX calls. */
2347                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2348                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2349                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2350                         }
2351                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2352                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2353                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2354                 }
2355         }
2356
2357         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2358                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2359
2360         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2361                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2362
2363         p = strrchr_m(fname,'/'); 
2364         if (!p)
2365                 base_name = fname;
2366         else
2367                 base_name = p+1;
2368
2369         mode = dos_mode(conn,fname,&sbuf);
2370         if (!mode)
2371                 mode = FILE_ATTRIBUTE_NORMAL;
2372
2373         fullpathname = fname;
2374         file_size = get_file_size(sbuf);
2375         allocation_size = get_allocation_size(fsp,&sbuf);
2376         if (mode & aDIR)
2377                 file_size = 0;
2378
2379         params = Realloc(*pparams,2);
2380         if (params == NULL)
2381           return ERROR_DOS(ERRDOS,ERRnomem);
2382         *pparams = params;
2383         memset((char *)params,'\0',2);
2384         data_size = max_data_bytes + 1024;
2385         pdata = Realloc(*ppdata, data_size); 
2386         if ( pdata == NULL )
2387                 return ERROR_DOS(ERRDOS,ERRnomem);
2388         *ppdata = pdata;
2389
2390         if (total_data > 0 && IVAL(pdata,0) == total_data) {
2391                 /* uggh, EAs for OS2 */
2392                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2393                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2394         }
2395
2396         memset((char *)pdata,'\0',data_size);
2397
2398         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2399
2400         if (lp_dos_filetime_resolution(SNUM(conn))) {
2401                 c_time &= ~1;
2402                 sbuf.st_atime &= ~1;
2403                 sbuf.st_ctime &= ~1;
2404                 sbuf.st_mtime &= ~1;
2405         }
2406
2407         /* NT expects the name to be in an exact form of the *full*
2408            filename. See the trans2 torture test */
2409         if (strequal(base_name,".")) {
2410                 pstrcpy(dos_fname, "\\");
2411         } else {
2412                 pstr_sprintf(dos_fname, "\\%s", fname);
2413                 string_replace(dos_fname, '/', '\\');
2414         }
2415
2416         switch (info_level) {
2417                 case SMB_INFO_STANDARD:
2418                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2419                         data_size = 22;
2420                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2421                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2422                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2423                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2424                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2425                         SSVAL(pdata,l1_attrFile,mode);
2426                         break;
2427
2428                 case SMB_INFO_QUERY_EA_SIZE:
2429                 {
2430                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2431                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2432                         data_size = 26;
2433                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2434                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2435                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2436                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2437                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2438                         SSVAL(pdata,l1_attrFile,mode);
2439                         SIVAL(pdata,l1_attrFile+2,ea_size);
2440                         break;
2441                 }
2442
2443                 case SMB_INFO_IS_NAME_VALID:
2444                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2445                         if (tran_call == TRANSACT2_QFILEINFO) {
2446                                 /* os/2 needs this ? really ?*/      
2447                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2448                         }
2449                         data_size = 0;
2450                         param_size = 0;
2451                         break;
2452                         
2453                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2454                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2455                         data_size = 24;
2456                         put_dos_date2(pdata,0,c_time);
2457                         put_dos_date2(pdata,4,sbuf.st_atime);
2458                         put_dos_date2(pdata,8,sbuf.st_mtime);
2459                         SIVAL(pdata,12,(uint32)file_size);
2460                         SIVAL(pdata,16,(uint32)allocation_size);
2461                         SIVAL(pdata,20,mode);
2462                         break;
2463
2464                 case SMB_INFO_QUERY_ALL_EAS:
2465                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2466                         /* We have data_size bytes to put EA's into. */
2467                         data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2468                         break;
2469
2470                 case SMB_FILE_BASIC_INFORMATION:
2471                 case SMB_QUERY_FILE_BASIC_INFO:
2472
2473                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2474                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2475                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2476                         } else {
2477                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2478                                 data_size = 40;
2479                                 SIVAL(pdata,36,0);
2480                         }
2481                         put_long_date(pdata,c_time);
2482                         put_long_date(pdata+8,sbuf.st_atime);
2483                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2484                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2485                         SIVAL(pdata,32,mode);
2486
2487                         DEBUG(5,("SMB_QFBI - "));
2488                         {
2489                                 time_t create_time = c_time;
2490                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2491                         }
2492                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2493                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2494                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2495                         DEBUG(5,("mode: %x\n", mode));
2496
2497                         break;
2498
2499                 case SMB_FILE_STANDARD_INFORMATION:
2500                 case SMB_QUERY_FILE_STANDARD_INFO:
2501
2502                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2503                         data_size = 24;
2504                         SOFF_T(pdata,0,allocation_size);
2505                         SOFF_T(pdata,8,file_size);
2506                         if (delete_pending & sbuf.st_nlink)
2507                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2508                         else
2509                                 SIVAL(pdata,16,sbuf.st_nlink);
2510                         SCVAL(pdata,20,0);
2511                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2512                         break;
2513
2514                 case SMB_FILE_EA_INFORMATION:
2515                 case SMB_QUERY_FILE_EA_INFO:
2516                 {
2517                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2518                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2519                         data_size = 4;
2520                         SIVAL(pdata,0,ea_size);
2521                         break;
2522                 }
2523
2524                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2525                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2526                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2527                 {
2528                         pstring short_name;
2529
2530                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2531                         pstrcpy(short_name,base_name);
2532                         /* Mangle if not already 8.3 */
2533                         if(!mangle_is_8_3(short_name, True)) {
2534                                 mangle_map(short_name,True,True,SNUM(conn));
2535                         }
2536                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2537                         data_size = 4 + len;
2538                         SIVAL(pdata,0,len);
2539                         break;
2540                 }
2541
2542                 case SMB_QUERY_FILE_NAME_INFO:
2543                         /*
2544                           this must be *exactly* right for ACLs on mapped drives to work
2545                          */
2546                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2547                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2548                         data_size = 4 + len;
2549                         SIVAL(pdata,0,len);
2550                         break;
2551
2552                 case SMB_FILE_ALLOCATION_INFORMATION:
2553                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2554                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2555                         data_size = 8;
2556                         SOFF_T(pdata,0,allocation_size);
2557                         break;
2558
2559                 case SMB_FILE_END_OF_FILE_INFORMATION:
2560                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2561                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2562                         data_size = 8;
2563                         SOFF_T(pdata,0,file_size);
2564                         break;
2565
2566                 case SMB_QUERY_FILE_ALL_INFO:
2567                 case SMB_FILE_ALL_INFORMATION:
2568                 {
2569                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2570                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2571                         put_long_date(pdata,c_time);
2572                         put_long_date(pdata+8,sbuf.st_atime);
2573                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2574                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2575                         SIVAL(pdata,32,mode);
2576                         pdata += 40;
2577                         SOFF_T(pdata,0,allocation_size);
2578                         SOFF_T(pdata,8,file_size);
2579                         if (delete_pending && sbuf.st_nlink)
2580                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2581                         else
2582                                 SIVAL(pdata,16,sbuf.st_nlink);
2583                         SCVAL(pdata,20,delete_pending);
2584                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2585                         pdata += 24;
2586                         SIVAL(pdata,0,ea_size);
2587                         pdata += 4; /* EA info */
2588                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2589                         SIVAL(pdata,0,len);
2590                         pdata += 4 + len;
2591                         data_size = PTR_DIFF(pdata,(*ppdata));
2592                         break;
2593                 }
2594                 case SMB_FILE_INTERNAL_INFORMATION:
2595                         /* This should be an index number - looks like
2596                            dev/ino to me :-) 
2597
2598                            I think this causes us to fail the IFSKIT
2599                            BasicFileInformationTest. -tpot */
2600
2601                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2602                         SIVAL(pdata,0,sbuf.st_dev);
2603                         SIVAL(pdata,4,sbuf.st_ino);
2604                         data_size = 8;
2605                         break;
2606
2607                 case SMB_FILE_ACCESS_INFORMATION:
2608                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2609                         SIVAL(pdata,0,desired_access);
2610                         data_size = 4;
2611                         break;
2612
2613                 case SMB_FILE_NAME_INFORMATION:
2614                         /* Pathname with leading '\'. */
2615                         {
2616                                 size_t byte_len;
2617                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2618                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2619                                 SIVAL(pdata,0,byte_len);
2620                                 data_size = 4 + byte_len;
2621                                 break;
2622                         }
2623
2624                 case SMB_FILE_DISPOSITION_INFORMATION:
2625                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2626                         data_size = 1;
2627                         SCVAL(pdata,0,delete_pending);
2628                         break;
2629
2630                 case SMB_FILE_POSITION_INFORMATION:
2631                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2632                         data_size = 8;
2633                         SOFF_T(pdata,0,pos);
2634                         break;
2635
2636                 case SMB_FILE_MODE_INFORMATION:
2637                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2638                         SIVAL(pdata,0,mode);
2639                         data_size = 4;
2640                         break;
2641
2642                 case SMB_FILE_ALIGNMENT_INFORMATION:
2643                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2644                         SIVAL(pdata,0,0); /* No alignment needed. */
2645                         data_size = 4;
2646                         break;
2647
2648 #if 0
2649                 /*
2650                  * NT4 server just returns "invalid query" to this - if we try to answer
2651                  * it then NTws gets a BSOD! (tridge).
2652                  * W2K seems to want this. JRA.
2653                  */
2654                 case SMB_QUERY_FILE_STREAM_INFO:
2655 #endif
2656                 case SMB_FILE_STREAM_INFORMATION:
2657                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2658                         if (mode & aDIR) {
2659                                 data_size = 0;
2660                         } else {
2661                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2662                                 SIVAL(pdata,0,0); /* ??? */
2663                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2664                                 SOFF_T(pdata,8,file_size);
2665                                 SIVAL(pdata,16,allocation_size);
2666                                 SIVAL(pdata,20,0); /* ??? */
2667                                 data_size = 24 + byte_len;
2668                         }
2669                         break;
2670
2671                 case SMB_QUERY_COMPRESSION_INFO:
2672                 case SMB_FILE_COMPRESSION_INFORMATION:
2673                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2674                         SOFF_T(pdata,0,file_size);
2675                         SIVAL(pdata,8,0); /* ??? */
2676                         SIVAL(pdata,12,0); /* ??? */
2677                         data_size = 16;
2678                         break;
2679
2680                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2681                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2682                         put_long_date(pdata,c_time);
2683                         put_long_date(pdata+8,sbuf.st_atime);
2684                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2685                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2686                         SIVAL(pdata,32,allocation_size);
2687                         SOFF_T(pdata,40,file_size);
2688                         SIVAL(pdata,48,mode);
2689                         SIVAL(pdata,52,0); /* ??? */
2690                         data_size = 56;
2691                         break;
2692
2693                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2694                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2695                         SIVAL(pdata,0,mode);
2696                         SIVAL(pdata,4,0);
2697                         data_size = 8;
2698                         break;
2699
2700                 /*
2701                  * CIFS UNIX Extensions.
2702                  */
2703
2704                 case SMB_QUERY_FILE_UNIX_BASIC:
2705
2706                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2707                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2708
2709                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2710                         pdata += 8;
2711
2712                         SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2713                         pdata += 8;
2714
2715                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2716                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2717                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2718                         pdata += 24;
2719
2720                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2721                         SIVAL(pdata,4,0);
2722                         pdata += 8;
2723
2724                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2725                         SIVAL(pdata,4,0);
2726                         pdata += 8;
2727
2728                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2729                         pdata += 4;
2730
2731                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2732                         SIVAL(pdata,4,0);
2733                         pdata += 8;
2734
2735                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2736                         SIVAL(pdata,4,0);
2737                         pdata += 8;
2738
2739                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2740                         pdata += 8;
2741                                 
2742                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2743                         SIVAL(pdata,4,0);
2744                         pdata += 8;
2745
2746                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2747                         SIVAL(pdata,4,0);
2748                         pdata += 8+1;
2749                         data_size = PTR_DIFF(pdata,(*ppdata));
2750
2751                         {
2752                                 int i;
2753                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2754
2755                                 for (i=0; i<100; i++)
2756                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2757                                 DEBUG(4,("\n"));
2758                         }
2759
2760                         break;
2761
2762                 case SMB_QUERY_FILE_UNIX_LINK:
2763                         {
2764                                 pstring buffer;
2765
2766                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2767 #ifdef S_ISLNK
2768                                 if(!S_ISLNK(sbuf.st_mode))
2769                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2770 #else
2771                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2772 #endif
2773                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2774                                 if (len == -1)
2775                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2776                                 buffer[len] = 0;
2777                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2778                                 pdata += len;
2779                                 data_size = PTR_DIFF(pdata,(*ppdata));
2780
2781                                 break;
2782                         }
2783
2784                 default:
2785                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2786         }
2787
2788         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2789
2790         return(-1);
2791 }
2792
2793 /****************************************************************************
2794  Deal with the internal needs of setting the delete on close flag. Note that
2795  as the tdb locking is recursive, it is safe to call this from within 
2796  open_file_shared. JRA.
2797 ****************************************************************************/
2798
2799 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2800 {
2801         /*
2802          * Only allow delete on close for writable shares.
2803          */
2804
2805         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2806                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2807                                 fsp->fsp_name ));
2808                                 return NT_STATUS_ACCESS_DENIED;
2809         }
2810         /*
2811          * Only allow delete on close for files/directories opened with delete intent.
2812          */
2813
2814         if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2815                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2816                                 fsp->fsp_name ));
2817                                 return NT_STATUS_ACCESS_DENIED;
2818         }
2819
2820         if(fsp->is_directory) {
2821                 fsp->directory_delete_on_close = delete_on_close;
2822                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2823                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2824         } else {
2825                 fsp->delete_on_close = delete_on_close;
2826                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2827                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2828         }
2829
2830         return NT_STATUS_OK;
2831 }
2832
2833 /****************************************************************************
2834  Sets the delete on close flag over all share modes on this file.
2835  Modify the share mode entry for all files open
2836  on this device and inode to tell other smbds we have
2837  changed the delete on close flag. This will be noticed
2838  in the close code, the last closer will delete the file
2839  if flag is set.
2840 ****************************************************************************/
2841
2842 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2843 {
2844         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2845                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2846
2847         if (fsp->is_directory || fsp->is_stat)
2848                 return NT_STATUS_OK;
2849
2850         if (lock_share_entry_fsp(fsp) == False)
2851                 return NT_STATUS_ACCESS_DENIED;
2852
2853         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2854                 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2855                         fsp->fsp_name ));
2856                 unlock_share_entry_fsp(fsp);
2857                 return NT_STATUS_ACCESS_DENIED;
2858         }
2859
2860         unlock_share_entry_fsp(fsp);
2861         return NT_STATUS_OK;
2862 }
2863
2864 /****************************************************************************
2865  Set a hard link (called by UNIX extensions and by NT rename with HARD link
2866  code.
2867 ****************************************************************************/
2868
2869 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2870 {
2871         BOOL bad_path_oldname = False;
2872         BOOL bad_path_newname = False;
2873         SMB_STRUCT_STAT sbuf1, sbuf2;
2874         BOOL rc, rcdest;
2875         pstring last_component_oldname;
2876         pstring last_component_newname;
2877         NTSTATUS status = NT_STATUS_OK;
2878
2879         ZERO_STRUCT(sbuf1);
2880         ZERO_STRUCT(sbuf2);
2881
2882         /* No wildcards. */
2883         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2884                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2885         }
2886
2887         rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2888         if (!rc && bad_path_oldname) {
2889                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2890         }
2891
2892         /* Quick check for "." and ".." */
2893         if (last_component_oldname[0] == '.') {
2894                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2895                         return NT_STATUS_OBJECT_NAME_INVALID;
2896                 }
2897         }
2898
2899         /* source must already exist. */
2900         if (!VALID_STAT(sbuf1)) {
2901                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2902         }
2903
2904         if (!check_name(oldname,conn)) {
2905                 return NT_STATUS_ACCESS_DENIED;
2906         }
2907
2908         rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2909         if (!rcdest && bad_path_newname) {
2910                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2911         }
2912
2913         /* Quick check for "." and ".." */
2914         if (last_component_newname[0] == '.') {
2915                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2916                         return NT_STATUS_OBJECT_NAME_INVALID;
2917                 }
2918         }
2919
2920         /* Disallow if newname already exists. */
2921         if (VALID_STAT(sbuf2)) {
2922                 return NT_STATUS_OBJECT_NAME_COLLISION;
2923         }
2924
2925         if (!check_name(newname,conn)) {
2926                 return NT_STATUS_ACCESS_DENIED;
2927         }
2928
2929         /* No links from a directory. */
2930         if (S_ISDIR(sbuf1.st_mode)) {
2931                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2932         }
2933
2934         /* Ensure this is within the share. */
2935         if (!reduce_name(conn, oldname) != 0)
2936                 return NT_STATUS_ACCESS_DENIED;
2937
2938         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2939
2940         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2941                 status = map_nt_error_from_unix(errno);
2942                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2943                                 nt_errstr(status), newname, oldname));
2944         }
2945
2946         return status;
2947 }
2948
2949 /****************************************************************************
2950  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2951 ****************************************************************************/
2952
2953 static int call_trans2setfilepathinfo(connection_struct *conn,
2954                                         char *inbuf, char *outbuf, int length, int bufsize,
2955                                         char **pparams, int total_params, char **ppdata, int total_data)
2956 {
2957         char *params = *pparams;
2958         char *pdata = *ppdata;
2959         uint16 tran_call = SVAL(inbuf, smb_setup0);
2960         uint16 info_level;
2961         int dosmode=0;
2962         SMB_OFF_T size=0;
2963         struct utimbuf tvs;
2964         SMB_STRUCT_STAT sbuf;
2965         pstring fname;
2966         int fd = -1;
2967         BOOL bad_path = False;
2968         files_struct *fsp = NULL;
2969         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2970         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2971         mode_t unixmode = 0;
2972         NTSTATUS status = NT_STATUS_OK;
2973
2974         if (!params)
2975                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2976
2977         if (tran_call == TRANSACT2_SETFILEINFO) {
2978                 if (total_params < 4)
2979                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2980
2981                 fsp = file_fsp(params,0);
2982                 info_level = SVAL(params,2);    
2983
2984                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2985                         /*
2986                          * This is actually a SETFILEINFO on a directory
2987                          * handle (returned from an NT SMB). NT5.0 seems
2988                          * to do this call. JRA.
2989                          */
2990                         pstrcpy(fname, fsp->fsp_name);
2991                         unix_convert(fname,conn,0,&bad_path,&sbuf);
2992                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2993                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2994                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2995                         }
2996                 } else if (fsp && fsp->print_file) {
2997                         /*
2998                          * Doing a DELETE_ON_CLOSE should cancel a print job.
2999                          */
3000                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3001                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3002
3003                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3004         
3005                                 SSVAL(params,0,0);
3006                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3007                                 return(-1);
3008                         } else
3009                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3010             } else {
3011                         /*
3012                          * Original code - this is an open file.
3013                          */
3014                         CHECK_FSP(fsp,conn);
3015
3016                         pstrcpy(fname, fsp->fsp_name);
3017                         fd = fsp->fd;
3018
3019                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3020                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3021                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3022                         }
3023                 }
3024         } else {
3025                 /* set path info */
3026                 if (total_params < 6)
3027                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3028
3029                 info_level = SVAL(params,0);    
3030                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3031                 if (!NT_STATUS_IS_OK(status)) {
3032                         return ERROR_NT(status);
3033                 }
3034                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3035
3036                 /*
3037                  * For CIFS UNIX extensions the target name may not exist.
3038                  */
3039
3040                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3041                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3042                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3043                 }    
3044
3045                 if(!check_name(fname, conn)) {
3046                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3047                 }
3048
3049         }
3050
3051         if (!CAN_WRITE(conn))
3052                 return ERROR_DOS(ERRSRV,ERRaccess);
3053
3054         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3055                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3056
3057         if (VALID_STAT(sbuf))
3058                 unixmode = sbuf.st_mode;
3059
3060         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3061                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3062
3063         /* Realloc the parameter and data sizes */
3064         params = Realloc(*pparams,2);
3065         if(params == NULL)
3066                 return ERROR_DOS(ERRDOS,ERRnomem);
3067         *pparams = params;
3068
3069         SSVAL(params,0,0);
3070
3071         if (fsp) {
3072                 /* the pending modtime overrides the current modtime */
3073                 sbuf.st_mtime = fsp->pending_modtime;
3074         }
3075
3076         size = get_file_size(sbuf);
3077         tvs.modtime = sbuf.st_mtime;
3078         tvs.actime = sbuf.st_atime;
3079         dosmode = dos_mode(conn,fname,&sbuf);
3080         unixmode = sbuf.st_mode;
3081
3082         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3083         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3084
3085         switch (info_level) {
3086                 case SMB_INFO_STANDARD:
3087                 {
3088                         if (total_data < 12)
3089                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3090
3091                         /* access time */
3092                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3093                         /* write time */
3094                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3095                         break;
3096                 }
3097
3098                 case SMB_INFO_SET_EA:
3099                         status = set_ea(conn, fsp, fname, pdata, total_data);
3100                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3101                                 return ERROR_NT(status);
3102                         break;
3103
3104                 /* XXXX um, i don't think this is right.
3105                         it's also not in the cifs6.txt spec.
3106                 */
3107                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3108                         if (total_data < 28)
3109                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3110
3111                         tvs.actime = make_unix_date2(pdata+8);
3112                         tvs.modtime = make_unix_date2(pdata+12);
3113                         size = IVAL(pdata,16);
3114                         dosmode = IVAL(pdata,24);
3115                         break;
3116
3117                 /* XXXX nor this.  not in cifs6.txt, either. */
3118                 case SMB_INFO_QUERY_ALL_EAS:
3119                         if (total_data < 28)
3120                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3121
3122                         tvs.actime = make_unix_date2(pdata+8);
3123                         tvs.modtime = make_unix_date2(pdata+12);
3124                         size = IVAL(pdata,16);
3125                         dosmode = IVAL(pdata,24);
3126                         break;
3127
3128                 case SMB_SET_FILE_BASIC_INFO:
3129                 case SMB_FILE_BASIC_INFORMATION:
3130                 {
3131                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3132                         time_t write_time;
3133                         time_t changed_time;
3134
3135                         if (total_data < 36)
3136                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3137
3138                         /* Ignore create time at offset pdata. */
3139
3140                         /* access time */
3141                         tvs.actime = interpret_long_date(pdata+8);
3142
3143                         write_time = interpret_long_date(pdata+16);
3144                         changed_time = interpret_long_date(pdata+24);
3145
3146                         tvs.modtime = MIN(write_time, changed_time);
3147
3148                         if (write_time > tvs.modtime && write_time != 0xffffffff) {
3149                                 tvs.modtime = write_time;
3150                         }
3151                         /* Prefer a defined time to an undefined one. */
3152                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3153                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3154                                         ? changed_time : write_time);
3155
3156                         /* attributes */
3157                         dosmode = IVAL(pdata,32);
3158                         break;
3159                 }
3160
3161                 case SMB_FILE_ALLOCATION_INFORMATION:
3162                 case SMB_SET_FILE_ALLOCATION_INFO:
3163                 {
3164                         int ret = -1;
3165                         SMB_BIG_UINT allocation_size;
3166
3167                         if (total_data < 8)
3168                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3169
3170                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3171 #ifdef LARGE_SMB_OFF_T
3172                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3173 #else /* LARGE_SMB_OFF_T */
3174                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3175                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3176 #endif /* LARGE_SMB_OFF_T */
3177                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3178                                         fname, (double)allocation_size ));
3179
3180                         if (allocation_size)
3181                                 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3182
3183                         if(allocation_size != get_file_size(sbuf)) {
3184                                 SMB_STRUCT_STAT new_sbuf;
3185  
3186                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3187                                         fname, (double)allocation_size ));
3188  
3189                                 if (fd == -1) {
3190                                         files_struct *new_fsp = NULL;
3191                                         int access_mode = 0;
3192                                         int action = 0;
3193  
3194                                         if(global_oplock_break) {
3195                                                 /* Queue this file modify as we are the process of an oplock break.  */
3196  
3197                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3198                                                 DEBUGADD(2,( "in oplock break state.\n"));
3199  
3200                                                 push_oplock_pending_smb_message(inbuf, length);
3201                                                 return -1;
3202                                         }
3203  
3204                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3205                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3206                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3207                                                                         FILE_ATTRIBUTE_NORMAL,
3208                                                                         0, &access_mode, &action);
3209  
3210                                         if (new_fsp == NULL)
3211                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3212                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3213                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3214                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3215                                                                         new_fsp->fnum, strerror(errno)));
3216                                                 ret = -1;
3217                                         }
3218                                         close_file(new_fsp,True);
3219                                 } else {
3220                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3221                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3222                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3223                                                                         fsp->fnum, strerror(errno)));
3224                                                 ret = -1;
3225                                         }
3226                                 }
3227                                 if (ret == -1)
3228                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3229
3230                                 /* Allocate can truncate size... */
3231                                 size = get_file_size(new_sbuf);
3232                         }
3233
3234                         break;
3235                 }
3236
3237                 case SMB_FILE_END_OF_FILE_INFORMATION:
3238                 case SMB_SET_FILE_END_OF_FILE_INFO:
3239                 {
3240                         if (total_data < 8)
3241                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3242
3243                         size = IVAL(pdata,0);
3244 #ifdef LARGE_SMB_OFF_T
3245                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3246 #else /* LARGE_SMB_OFF_T */
3247                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3248                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3249 #endif /* LARGE_SMB_OFF_T */
3250                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3251                         break;
3252                 }
3253
3254                 case SMB_FILE_DISPOSITION_INFORMATION:
3255                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3256                 {
3257                         BOOL delete_on_close;
3258
3259                         if (total_data < 1)
3260                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3261
3262                         delete_on_close = (CVAL(pdata,0) ? True : False);
3263
3264                         /* Just ignore this set on a path. */
3265                         if (tran_call != TRANSACT2_SETFILEINFO)
3266                                 break;
3267
3268                         if (fsp == NULL)
3269                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3270
3271                         status = set_delete_on_close_internal(fsp, delete_on_close);
3272  
3273                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3274                                 return ERROR_NT(status);
3275
3276                         /* The set is across all open files on this dev/inode pair. */
3277                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3278                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3279                                 return ERROR_NT(status);
3280
3281                         break;
3282                 }
3283
3284                 case SMB_FILE_POSITION_INFORMATION:
3285                 {
3286                         SMB_BIG_UINT position_information;
3287
3288                         if (total_data < 8)
3289                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3290
3291                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3292 #ifdef LARGE_SMB_OFF_T
3293                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3294 #else /* LARGE_SMB_OFF_T */
3295                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3296                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3297 #endif /* LARGE_SMB_OFF_T */
3298                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3299                                         fname, (double)position_information ));
3300                         if (fsp)
3301                                 fsp->position_information = position_information;
3302                         break;
3303                 }
3304
3305                 /*
3306                  * CIFS UNIX extensions.
3307                  */
3308
3309                 case SMB_SET_FILE_UNIX_BASIC:
3310                 {
3311                         uint32 raw_unixmode;
3312
3313                         if (total_data < 100)
3314                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3315
3316                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3317                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3318                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3319 #ifdef LARGE_SMB_OFF_T
3320                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3321 #else /* LARGE_SMB_OFF_T */
3322                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3323                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3324 #endif /* LARGE_SMB_OFF_T */
3325                         }
3326                         pdata+=24;          /* ctime & st_blocks are not changed */
3327                         tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3328                         tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3329                         pdata+=16;
3330                         set_owner = (uid_t)IVAL(pdata,0);
3331                         pdata += 8;
3332                         set_grp = (gid_t)IVAL(pdata,0);
3333                         pdata += 8;
3334                         raw_unixmode = IVAL(pdata,28);
3335                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3336                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
3337
3338                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3339 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3340                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3341
3342                         if (!VALID_STAT(sbuf)) {
3343
3344                                 /*
3345                                  * The only valid use of this is to create character and block
3346                                  * devices, and named pipes. This is deprecated (IMHO) and 
3347                                  * a new info level should be used for mknod. JRA.
3348                                  */
3349
3350 #if !defined(HAVE_MAKEDEV_FN)
3351                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3352 #else /* HAVE_MAKEDEV_FN */
3353                                 uint32 file_type = IVAL(pdata,0);
3354                                 uint32 dev_major = IVAL(pdata,4);
3355                                 uint32 dev_minor = IVAL(pdata,12);
3356
3357                                 uid_t myuid = geteuid();
3358                                 gid_t mygid = getegid();
3359                                 SMB_DEV_T dev;
3360
3361                                 if (tran_call == TRANSACT2_SETFILEINFO)
3362                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3363
3364                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3365                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3366
3367                                 dev = makedev(dev_major, dev_minor);
3368
3369                                 /* We can only create as the owner/group we are. */
3370
3371                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3372                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3373                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3374                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3375
3376                                 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3377                                                 file_type != UNIX_TYPE_FIFO &&
3378                                                 file_type != UNIX_TYPE_SOCKET)
3379                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3380
3381                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3382 0%o for file %s\n", (double)dev, unixmode, fname ));
3383
3384                                 /* Ok - do the mknod. */
3385                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3386                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3387
3388                                 inherit_access_acl(conn, fname, unixmode);
3389
3390                                 SSVAL(params,0,0);
3391                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3392                                 return(-1);
3393 #endif /* HAVE_MAKEDEV_FN */
3394
3395                         }
3396
3397                         /*
3398                          * Deal with the UNIX specific mode set.
3399                          */
3400
3401                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3402                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3403                                         (unsigned int)unixmode, fname ));
3404                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3405                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3406                         }
3407
3408                         /*
3409                          * Deal with the UNIX specific uid set.
3410                          */
3411
3412                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3413                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3414                                         (unsigned int)set_owner, fname ));
3415                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3416                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3417                         }
3418
3419                         /*
3420                          * Deal with the UNIX specific gid set.
3421                          */
3422
3423                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3424                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3425                                         (unsigned int)set_owner, fname ));
3426                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3427                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3428                         }
3429                         break;
3430                 }
3431
3432                 case SMB_SET_FILE_UNIX_LINK:
3433                 {
3434                         pstring link_target;
3435                         char *newname = fname;
3436
3437                         /* Set a symbolic link. */
3438                         /* Don't allow this if follow links is false. */
3439
3440                         if (!lp_symlinks(SNUM(conn)))
3441                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3442
3443                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3444
3445                         /* !widelinks forces the target path to be within the share. */
3446                         /* This means we can interpret the target as a pathname. */
3447                         if (!lp_widelinks(SNUM(conn))) {
3448                                 pstring rel_name;
3449                                 char *last_dirp = NULL;
3450
3451                                 unix_format(link_target);
3452                                 if (*link_target == '/') {
3453                                         /* No absolute paths allowed. */
3454                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3455                                 }
3456                                 pstrcpy(rel_name, newname);
3457                                 last_dirp = strrchr_m(rel_name, '/');
3458                                 if (last_dirp) {
3459                                         last_dirp[1] = '\0';
3460                                 } else {
3461                                         pstrcpy(rel_name, "./");
3462                                 }
3463                                 pstrcat(rel_name, link_target);
3464
3465                                 if (!check_name(rel_name, conn)) {
3466                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3467                                 }
3468                         }
3469
3470                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3471                                 fname, link_target ));
3472
3473                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3474                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3475                         SSVAL(params,0,0);
3476                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3477                         return(-1);
3478                 }
3479
3480                 case SMB_SET_FILE_UNIX_HLINK:
3481                 {
3482                         pstring oldname;
3483                         char *newname = fname;
3484
3485                         /* Set a hard link. */
3486                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3487                         if (!NT_STATUS_IS_OK(status)) {
3488                                 return ERROR_NT(status);
3489                         }
3490
3491                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3492                                 fname, oldname));
3493
3494                         status = hardlink_internals(conn, oldname, newname);
3495                         if (!NT_STATUS_IS_OK(status)) {
3496                                 return ERROR_NT(status);
3497                         }
3498
3499                         SSVAL(params,0,0);
3500                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3501                         return(-1);
3502                 }
3503
3504                 case SMB_FILE_RENAME_INFORMATION:
3505                 {
3506                         BOOL overwrite;
3507                         uint32 root_fid;
3508                         uint32 len;
3509                         pstring newname;
3510                         pstring base_name;
3511                         char *p;
3512
3513                         if (total_data < 12)
3514                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3515
3516                         overwrite = (CVAL(pdata,0) ? True : False);
3517                         root_fid = IVAL(pdata,4);
3518                         len = IVAL(pdata,8);
3519                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3520                         if (!NT_STATUS_IS_OK(status)) {
3521                                 return ERROR_NT(status);
3522                         }
3523
3524                         /* Check the new name has no '/' characters. */
3525                         if (strchr_m(newname, '/'))
3526                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3527
3528                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3529
3530                         /* Create the base directory. */
3531                         pstrcpy(base_name, fname);
3532                         p = strrchr_m(base_name, '/');
3533                         if (p)
3534                                 *p = '\0';
3535                         /* Append the new name. */
3536                         pstrcat(base_name, "/");
3537                         pstrcat(base_name, newname);
3538
3539                         if (fsp) {
3540                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3541                                         fsp->fnum, fsp->fsp_name, base_name ));
3542                                 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3543                         } else {
3544                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3545                                         fname, newname ));
3546                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
3547                         }
3548                         if (!NT_STATUS_IS_OK(status)) {
3549                                 return ERROR_NT(status);
3550                         }
3551                         process_pending_change_notify_queue((time_t)0);
3552                         SSVAL(params,0,0);
3553                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3554                         return(-1);
3555                 }
3556                 default:
3557                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3558         }
3559
3560         /* get some defaults (no modifications) if any info is zero or -1. */
3561         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3562                 tvs.actime = sbuf.st_atime;
3563
3564         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3565                 tvs.modtime = sbuf.st_mtime;
3566
3567         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3568         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3569         DEBUG(6,("size: %.0f ", (double)size));
3570
3571         if (dosmode) {
3572                 if (S_ISDIR(sbuf.st_mode))
3573                         dosmode |= aDIR;
3574                 else
3575                         dosmode &= ~aDIR;
3576         }
3577
3578         DEBUG(6,("dosmode: %x\n"  , dosmode));
3579
3580         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3581                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3582                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3583                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3584
3585                 /*
3586                  * Only do this test if we are not explicitly
3587                  * changing the size of a file.
3588                  */
3589                 if (!size)
3590                         size = get_file_size(sbuf);
3591         }
3592
3593         /*
3594          * Try and set the times, size and mode of this file -
3595          * if they are different from the current values
3596          */
3597         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3598                 if(fsp != NULL) {
3599                         /*
3600                          * This was a setfileinfo on an open file.
3601                          * NT does this a lot. It's actually pointless
3602                          * setting the time here, as it will be overwritten
3603                          * on the next write, so we save the request
3604                          * away and will set it on file close. JRA.
3605                          */
3606
3607                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3608                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3609                                 fsp->pending_modtime = tvs.modtime;
3610                         }
3611
3612                 } else {
3613
3614                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3615
3616                         if(file_utime(conn, fname, &tvs)!=0)
3617                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3618                 }
3619         }
3620
3621         /* check the mode isn't different, before changing it */
3622         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3623
3624                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3625
3626                 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3627                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3628                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3629                 }
3630         }
3631
3632         if (size != get_file_size(sbuf)) {
3633
3634                 int ret;
3635
3636                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3637                         fname, (double)size ));
3638
3639                 if (fd == -1) {
3640                         files_struct *new_fsp = NULL;
3641                         int access_mode = 0;
3642                         int action = 0;
3643
3644                         if(global_oplock_break) {
3645                                 /* Queue this file modify as we are the process of an oplock break.  */
3646
3647                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3648                                 DEBUGADD(2,( "in oplock break state.\n"));
3649
3650                                 push_oplock_pending_smb_message(inbuf, length);
3651                                 return -1;
3652                         }
3653
3654                         new_fsp = open_file_shared(conn, fname, &sbuf,
3655                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3656                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3657                                                 FILE_ATTRIBUTE_NORMAL,
3658                                                 0, &access_mode, &action);
3659         
3660                         if (new_fsp == NULL)
3661                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3662                         ret = vfs_set_filelen(new_fsp, size);
3663                         close_file(new_fsp,True);
3664                 } else {
3665                         ret = vfs_set_filelen(fsp, size);
3666                 }
3667
3668                 if (ret == -1)
3669                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3670         }
3671
3672         SSVAL(params,0,0);
3673         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3674   
3675         return(-1);
3676 }
3677
3678 /****************************************************************************
3679  Reply to a TRANS2_MKDIR (make directory with extended attributes).
3680 ****************************************************************************/
3681
3682 static int call_trans2mkdir(connection_struct *conn,
3683                             char *inbuf, char *outbuf, int length, int bufsize,
3684                                 char **pparams, int total_params, char **ppdata, int total_data)
3685 {
3686         char *params = *pparams;
3687         pstring directory;
3688         int ret = -1;
3689         SMB_STRUCT_STAT sbuf;
3690         BOOL bad_path = False;
3691         NTSTATUS status = NT_STATUS_OK;
3692
3693         if (!CAN_WRITE(conn))
3694                 return ERROR_DOS(ERRSRV,ERRaccess);
3695
3696         if (total_params < 4)
3697                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3698
3699         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3700         if (!NT_STATUS_IS_OK(status)) {
3701                 return ERROR_NT(status);
3702         }
3703
3704         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3705
3706         unix_convert(directory,conn,0,&bad_path,&sbuf);
3707         if (check_name(directory,conn))
3708                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3709   
3710         if(ret < 0) {
3711                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3712                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3713         }
3714
3715         /* Realloc the parameter and data sizes */
3716         params = Realloc(*pparams,2);
3717         if(params == NULL)
3718                 return ERROR_DOS(ERRDOS,ERRnomem);
3719         *pparams = params;
3720
3721         SSVAL(params,0,0);
3722
3723         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3724   
3725         return(-1);
3726 }
3727
3728 /****************************************************************************
3729  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3730  We don't actually do this - we just send a null response.
3731 ****************************************************************************/
3732
3733 static int call_trans2findnotifyfirst(connection_struct *conn,
3734                                         char *inbuf, char *outbuf, int length, int bufsize,
3735                                         char **pparams, int total_params, char **ppdata, int total_data)
3736 {
3737         static uint16 fnf_handle = 257;
3738         char *params = *pparams;
3739         uint16 info_level;
3740
3741         if (total_params < 6)
3742                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3743
3744         info_level = SVAL(params,4);
3745         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3746
3747         switch (info_level) {
3748                 case 1:
3749                 case 2:
3750                         break;
3751                 default:
3752                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3753         }
3754
3755         /* Realloc the parameter and data sizes */
3756         params = Realloc(*pparams,6);
3757         if(params == NULL) 
3758                 return ERROR_DOS(ERRDOS,ERRnomem);
3759         *pparams = params;
3760
3761         SSVAL(params,0,fnf_handle);
3762         SSVAL(params,2,0); /* No changes */
3763         SSVAL(params,4,0); /* No EA errors */
3764
3765         fnf_handle++;
3766
3767         if(fnf_handle == 0)
3768                 fnf_handle = 257;
3769
3770         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3771   
3772         return(-1);
3773 }
3774
3775 /****************************************************************************
3776  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
3777  changes). Currently this does nothing.
3778 ****************************************************************************/
3779
3780 static int call_trans2findnotifynext(connection_struct *conn,
3781                                         char *inbuf, char *outbuf, int length, int bufsize,
3782                                         char **pparams, int total_params, char **ppdata, int total_data)
3783 {
3784         char *params = *pparams;
3785
3786         DEBUG(3,("call_trans2findnotifynext\n"));
3787
3788         /* Realloc the parameter and data sizes */
3789         params = Realloc(*pparams,4);
3790         if(params == NULL)
3791                 return ERROR_DOS(ERRDOS,ERRnomem);
3792         *pparams = params;
3793
3794         SSVAL(params,0,0); /* No changes */
3795         SSVAL(params,2,0); /* No EA errors */
3796
3797         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3798   
3799         return(-1);
3800 }
3801
3802 /****************************************************************************
3803  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3804 ****************************************************************************/
3805
3806 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3807                                         char* outbuf, int length, int bufsize,
3808                                         char **pparams, int total_params, char **ppdata, int total_data)
3809 {
3810         char *params = *pparams;
3811         pstring pathname;
3812         int reply_size = 0;
3813         int max_referral_level;
3814
3815         DEBUG(10,("call_trans2getdfsreferral\n"));
3816
3817         if (total_params < 2)
3818                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3819
3820         max_referral_level = SVAL(params,0);
3821
3822         if(!lp_host_msdfs())
3823                 return ERROR_DOS(ERRDOS,ERRbadfunc);
3824
3825         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3826         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3827                 return UNIXERROR(ERRDOS,ERRbadfile);
3828     
3829         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3830         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3831
3832         return(-1);
3833 }
3834
3835 #define LMCAT_SPL       0x53
3836 #define LMFUNC_GETJOBID 0x60
3837
3838 /****************************************************************************
3839  Reply to a TRANS2_IOCTL - used for OS/2 printing.
3840 ****************************************************************************/
3841
3842 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3843                                         char* outbuf, int length, int bufsize,
3844                                         char **pparams, int total_params, char **ppdata, int total_data)
3845 {
3846         char *pdata = *ppdata;
3847         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3848
3849         /* check for an invalid fid before proceeding */
3850         
3851         if (!fsp)                                
3852                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
3853
3854         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3855                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3856                 pdata = Realloc(*ppdata, 32);
3857                 if(pdata == NULL)
3858                         return ERROR_DOS(ERRDOS,ERRnomem);
3859                 *ppdata = pdata;
3860
3861                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3862                         CAN ACCEPT THIS IN UNICODE. JRA. */
3863
3864                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
3865                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3866                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3867                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3868                 return(-1);
3869         } else {
3870                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3871                 return ERROR_DOS(ERRSRV,ERRerror);
3872         }
3873 }
3874
3875 /****************************************************************************
3876  Reply to a SMBfindclose (stop trans2 directory search).
3877 ****************************************************************************/
3878
3879 int reply_findclose(connection_struct *conn,
3880                     char *inbuf,char *outbuf,int length,int bufsize)
3881 {
3882         int outsize = 0;
3883         int dptr_num=SVALS(inbuf,smb_vwv0);
3884         START_PROFILE(SMBfindclose);
3885
3886         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3887
3888         dptr_close(&dptr_num);
3889
3890         outsize = set_message(outbuf,0,0,True);
3891
3892         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3893
3894         END_PROFILE(SMBfindclose);
3895         return(outsize);
3896 }
3897
3898 /****************************************************************************
3899  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3900 ****************************************************************************/
3901
3902 int reply_findnclose(connection_struct *conn, 
3903                      char *inbuf,char *outbuf,int length,int bufsize)
3904 {
3905         int outsize = 0;
3906         int dptr_num= -1;
3907         START_PROFILE(SMBfindnclose);
3908         
3909         dptr_num = SVAL(inbuf,smb_vwv0);
3910
3911         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3912
3913         /* We never give out valid handles for a 
3914            findnotifyfirst - so any dptr_num is ok here. 
3915            Just ignore it. */
3916
3917         outsize = set_message(outbuf,0,0,True);
3918
3919         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3920
3921         END_PROFILE(SMBfindnclose);
3922         return(outsize);
3923 }
3924
3925 /****************************************************************************
3926  Reply to a SMBtranss2 - just ignore it!
3927 ****************************************************************************/
3928
3929 int reply_transs2(connection_struct *conn,
3930                   char *inbuf,char *outbuf,int length,int bufsize)
3931 {
3932         START_PROFILE(SMBtranss2);
3933         DEBUG(4,("Ignoring transs2 of length %d\n",length));
3934         END_PROFILE(SMBtranss2);
3935         return(-1);
3936 }
3937
3938 /****************************************************************************
3939  Reply to a SMBtrans2.
3940 ****************************************************************************/
3941
3942 int reply_trans2(connection_struct *conn,
3943                  char *inbuf,char *outbuf,int length,int bufsize)
3944 {
3945         int outsize = 0;
3946         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3947         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3948 #if 0
3949         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3950         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3951         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3952         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3953         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3954         int32 timeout = IVALS(inbuf,smb_timeout);
3955 #endif
3956         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3957         unsigned int tran_call = SVAL(inbuf, smb_setup0);
3958         char *params = NULL, *data = NULL;
3959         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3960         START_PROFILE(SMBtrans2);
3961
3962         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3963                 /* Queue this open message as we are the process of an
3964                  * oplock break.  */
3965
3966                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3967                 DEBUGADD(2,( "in oplock break state.\n"));
3968
3969                 push_oplock_pending_smb_message(inbuf, length);
3970                 END_PROFILE(SMBtrans2);
3971                 return -1;
3972         }
3973         
3974         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3975             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3976                 END_PROFILE(SMBtrans2);
3977                 return ERROR_DOS(ERRSRV,ERRaccess);
3978         }
3979
3980         outsize = set_message(outbuf,0,0,True);
3981
3982         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3983            is so as a sanity check */
3984         if (suwcnt != 1) {
3985                 /*
3986                  * Need to have rc=0 for ioctl to get job id for OS/2.
3987                  *  Network printing will fail if function is not successful.
3988                  *  Similar function in reply.c will be used if protocol
3989                  *  is LANMAN1.0 instead of LM1.2X002.
3990                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
3991                  *  outbuf doesn't have to be set(only job id is used).
3992                  */
3993                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3994                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3995                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3996                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3997                 } else {
3998                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3999                         DEBUG(2,("Transaction is %d\n",tran_call));
4000                         END_PROFILE(SMBtrans2);
4001                         ERROR_DOS(ERRDOS,ERRinvalidparam);
4002                 }
4003         }
4004     
4005         /* Allocate the space for the maximum needed parameters and data */
4006         if (total_params > 0)
4007                 params = (char *)malloc(total_params);
4008         if (total_data > 0)
4009                 data = (char *)malloc(total_data);
4010   
4011         if ((total_params && !params)  || (total_data && !data)) {
4012                 DEBUG(2,("Out of memory in reply_trans2\n"));
4013                 SAFE_FREE(params);
4014                 SAFE_FREE(data); 
4015                 END_PROFILE(SMBtrans2);
4016                 return ERROR_DOS(ERRDOS,ERRnomem);
4017         }
4018
4019         /* Copy the param and data bytes sent with this request into
4020            the params buffer */
4021         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4022         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4023
4024         if (num_params > total_params || num_data > total_data)
4025                 exit_server("invalid params in reply_trans2");
4026
4027         if(params) {
4028                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4029                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4030                         goto bad_param;
4031                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4032                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4033                         goto bad_param;
4034                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4035         }
4036         if(data) {
4037                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4038                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4039                         goto bad_param;
4040                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4041                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4042                         goto bad_param;
4043                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4044         }
4045
4046         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4047
4048         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4049                 /* We need to send an interim response then receive the rest
4050                    of the parameter/data bytes */
4051                 outsize = set_message(outbuf,0,0,True);
4052                 srv_signing_trans_stop();
4053                 if (!send_smb(smbd_server_fd(),outbuf))
4054                         exit_server("reply_trans2: send_smb failed.");
4055
4056                 while (num_data_sofar < total_data || 
4057                        num_params_sofar < total_params) {
4058                         BOOL ret;
4059                         unsigned int param_disp;
4060                         unsigned int param_off;
4061                         unsigned int data_disp;
4062                         unsigned int data_off;
4063
4064                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4065                         
4066                         /*
4067                          * The sequence number for the trans reply is always
4068                          * based on the last secondary received.
4069                          */
4070
4071                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4072
4073                         if ((ret && 
4074                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4075                                 outsize = set_message(outbuf,0,0,True);
4076                                 if(ret)
4077                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4078                                 else
4079                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4080                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4081                                 goto bad_param;
4082                         }
4083       
4084                         /* Revise total_params and total_data in case
4085                            they have changed downwards */
4086                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4087                                 total_params = SVAL(inbuf, smb_tpscnt);
4088                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4089                                 total_data = SVAL(inbuf, smb_tdscnt);
4090
4091                         num_params = SVAL(inbuf,smb_spscnt);
4092                         param_off = SVAL(inbuf, smb_spsoff);
4093                         param_disp = SVAL(inbuf, smb_spsdisp);
4094                         num_params_sofar += num_params;
4095
4096                         num_data = SVAL(inbuf, smb_sdscnt);
4097                         data_off = SVAL(inbuf, smb_sdsoff);
4098                         data_disp = SVAL(inbuf, smb_sdsdisp);
4099                         num_data_sofar += num_data;
4100
4101                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4102                                 goto bad_param;
4103                         
4104                         if (num_params) {
4105                                 if (param_disp + num_params >= total_params)
4106                                         goto bad_param;
4107                                 if ((param_disp + num_params < param_disp) ||
4108                                                 (param_disp + num_params < num_params))
4109                                         goto bad_param;
4110                                 if (param_disp > total_params)
4111                                         goto bad_param;
4112                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4113                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4114                                         goto bad_param;
4115                                 if (params + param_disp < params)
4116                                         goto bad_param;
4117
4118                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4119                         }
4120                         if (num_data) {
4121                                 if (data_disp + num_data >= total_data)
4122                                         goto bad_param;
4123                                 if ((data_disp + num_data < data_disp) ||
4124                                                 (data_disp + num_data < num_data))
4125                                         goto bad_param;
4126                                 if (data_disp > total_data)
4127                                         goto bad_param;
4128                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4129                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4130                                         goto bad_param;
4131                                 if (data + data_disp < data)
4132                                         goto bad_param;
4133
4134                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4135                         }
4136                 }
4137         }
4138         
4139         if (Protocol >= PROTOCOL_NT1) {
4140                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4141         }
4142
4143         /* Now we must call the relevant TRANS2 function */
4144         switch(tran_call)  {
4145         case TRANSACT2_OPEN:
4146                 START_PROFILE_NESTED(Trans2_open);
4147                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4148                                           &params, total_params, &data, total_data);
4149                 END_PROFILE_NESTED(Trans2_open);
4150                 break;
4151
4152         case TRANSACT2_FINDFIRST:
4153                 START_PROFILE_NESTED(Trans2_findfirst);
4154                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4155                                           &params, total_params, &data, total_data);
4156                 END_PROFILE_NESTED(Trans2_findfirst);
4157                 break;
4158
4159         case TRANSACT2_FINDNEXT:
4160                 START_PROFILE_NESTED(Trans2_findnext);
4161                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4162                                           &params, total_params, &data, total_data);
4163                 END_PROFILE_NESTED(Trans2_findnext);
4164                 break;
4165
4166         case TRANSACT2_QFSINFO:
4167                 START_PROFILE_NESTED(Trans2_qfsinfo);
4168                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4169                                           &params, total_params, &data, total_data);
4170                 END_PROFILE_NESTED(Trans2_qfsinfo);
4171             break;
4172
4173 #ifdef HAVE_SYS_QUOTAS
4174         case TRANSACT2_SETFSINFO:
4175                 START_PROFILE_NESTED(Trans2_setfsinfo);
4176                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4177                                           &params, total_params, &data, total_data);
4178                 END_PROFILE_NESTED(Trans2_setfsinfo);
4179                 break;
4180 #endif
4181         case TRANSACT2_QPATHINFO:
4182         case TRANSACT2_QFILEINFO:
4183                 START_PROFILE_NESTED(Trans2_qpathinfo);
4184                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4185                                           &params, total_params, &data, total_data);
4186                 END_PROFILE_NESTED(Trans2_qpathinfo);
4187                 break;
4188         case TRANSACT2_SETPATHINFO:
4189         case TRANSACT2_SETFILEINFO:
4190                 START_PROFILE_NESTED(Trans2_setpathinfo);
4191                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4192                                           &params, total_params, &data, total_data);
4193                 END_PROFILE_NESTED(Trans2_setpathinfo);
4194                 break;
4195
4196         case TRANSACT2_FINDNOTIFYFIRST:
4197                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4198                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
4199                                           &params, total_params, &data, total_data);
4200                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4201                 break;
4202
4203         case TRANSACT2_FINDNOTIFYNEXT:
4204                 START_PROFILE_NESTED(Trans2_findnotifynext);
4205                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
4206                                           &params, total_params, &data, total_data);
4207                 END_PROFILE_NESTED(Trans2_findnotifynext);
4208                 break;
4209         case TRANSACT2_MKDIR:
4210                 START_PROFILE_NESTED(Trans2_mkdir);
4211                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4212                                           &params, total_params, &data, total_data);
4213                 END_PROFILE_NESTED(Trans2_mkdir);
4214                 break;
4215
4216         case TRANSACT2_GET_DFS_REFERRAL:
4217                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4218                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4219                                           &params, total_params, &data, total_data);
4220                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4221                 break;
4222         case TRANSACT2_IOCTL:
4223                 START_PROFILE_NESTED(Trans2_ioctl);
4224                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4225                                           &params, total_params, &data, total_data);
4226                 END_PROFILE_NESTED(Trans2_ioctl);
4227                 break;
4228         default:
4229                 /* Error in request */
4230                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4231                 SAFE_FREE(params);
4232                 SAFE_FREE(data);
4233                 END_PROFILE(SMBtrans2);
4234                 srv_signing_trans_stop();
4235                 return ERROR_DOS(ERRSRV,ERRerror);
4236         }
4237         
4238         /* As we do not know how many data packets will need to be
4239            returned here the various call_trans2xxxx calls
4240            must send their own. Thus a call_trans2xxx routine only
4241            returns a value other than -1 when it wants to send
4242            an error packet. 
4243         */
4244         
4245         srv_signing_trans_stop();
4246
4247         SAFE_FREE(params);
4248         SAFE_FREE(data);
4249         END_PROFILE(SMBtrans2);
4250         return outsize; /* If a correct response was needed the
4251                            call_trans2xxx calls have already sent
4252                            it. If outsize != -1 then it is returning */
4253
4254   bad_param:
4255
4256         srv_signing_trans_stop();
4257         SAFE_FREE(params);
4258         SAFE_FREE(data);
4259         END_PROFILE(SMBtrans2);
4260         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4261 }