r706: Fix erroneous commit... I've not finished testing the
[jra/samba/.git] / source3 / 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->directory_delete_on_close;
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_mtime &= ~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  Returns true if this pathname is within the share, and thus safe.
2866 ****************************************************************************/
2867
2868 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in)
2869 {
2870 #ifdef PATH_MAX
2871         char resolved_name[PATH_MAX+1];
2872 #else
2873         pstring resolved_name;
2874 #endif
2875         fstring last_component;
2876         pstring link_dest;
2877         pstring link_test;
2878         char *p;
2879         BOOL bad_path = False;
2880         SMB_STRUCT_STAT sbuf;
2881
2882         pstrcpy(link_dest, link_dest_in);
2883         unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2884
2885         p = strrchr_m(link_dest, '/');
2886         if (p) {
2887                 fstrcpy(last_component, p+1);
2888                 *p = '\0';
2889         } else {
2890                 fstrcpy(last_component, link_dest);
2891                 pstrcpy(link_dest, "./");
2892         }
2893                 
2894         if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2895                 return -1;
2896
2897         DEBUG(10,("ensure_link_is_safe: realpath: link_dest (%s) -> real name (%s)\n",
2898                         link_dest, resolved_name ));
2899
2900         pstrcpy(link_dest, resolved_name);
2901         pstrcat(link_dest, "/");
2902         pstrcat(link_dest, last_component);
2903
2904         if (*link_dest != '/') {
2905                 /* Relative path. */
2906                 pstrcpy(link_test, conn->connectpath);
2907                 pstrcat(link_test, "/");
2908                 pstrcat(link_test, link_dest);
2909         } else {
2910                 pstrcpy(link_test, link_dest);
2911         }
2912
2913         DEBUG(10,("ensure_link_is_safe: connectpath = %s, absolute resolved path = %s\n",
2914                 conn->connectpath, link_test ));
2915
2916         /*
2917          * Check if the link is within the share.
2918          */
2919
2920         if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2921                 errno = EACCES;
2922                 return -1;
2923         }
2924
2925         return 0;
2926 }
2927
2928 /****************************************************************************
2929  Set a hard link (called by UNIX extensions and by NT rename with HARD link
2930  code.
2931 ****************************************************************************/
2932
2933 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2934 {
2935         BOOL bad_path_oldname = False;
2936         BOOL bad_path_newname = False;
2937         SMB_STRUCT_STAT sbuf1, sbuf2;
2938         BOOL rc, rcdest;
2939         pstring last_component_oldname;
2940         pstring last_component_newname;
2941         NTSTATUS status = NT_STATUS_OK;
2942
2943         ZERO_STRUCT(sbuf1);
2944         ZERO_STRUCT(sbuf2);
2945
2946         /* No wildcards. */
2947         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2948                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2949         }
2950
2951         rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2952         if (!rc && bad_path_oldname) {
2953                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2954         }
2955
2956         /* Quick check for "." and ".." */
2957         if (last_component_oldname[0] == '.') {
2958                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2959                         return NT_STATUS_OBJECT_NAME_INVALID;
2960                 }
2961         }
2962
2963         /* source must already exist. */
2964         if (!VALID_STAT(sbuf1)) {
2965                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2966         }
2967
2968         if (!check_name(oldname,conn)) {
2969                 return NT_STATUS_ACCESS_DENIED;
2970         }
2971
2972         rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2973         if (!rcdest && bad_path_newname) {
2974                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2975         }
2976
2977         /* Quick check for "." and ".." */
2978         if (last_component_newname[0] == '.') {
2979                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2980                         return NT_STATUS_OBJECT_NAME_INVALID;
2981                 }
2982         }
2983
2984         /* Disallow if newname already exists. */
2985         if (VALID_STAT(sbuf2)) {
2986                 return NT_STATUS_OBJECT_NAME_COLLISION;
2987         }
2988
2989         if (!check_name(newname,conn)) {
2990                 return NT_STATUS_ACCESS_DENIED;
2991         }
2992
2993         /* No links from a directory. */
2994         if (S_ISDIR(sbuf1.st_mode)) {
2995                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2996         }
2997
2998         /* Ensure this is within the share. */
2999         if (!reduce_name(conn, oldname) != 0)
3000                 return NT_STATUS_ACCESS_DENIED;
3001
3002         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3003
3004         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3005                 status = map_nt_error_from_unix(errno);
3006                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3007                                 nt_errstr(status), newname, oldname));
3008         }
3009
3010         return status;
3011 }
3012
3013 /****************************************************************************
3014  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3015 ****************************************************************************/
3016
3017 static int call_trans2setfilepathinfo(connection_struct *conn,
3018                                         char *inbuf, char *outbuf, int length, int bufsize,
3019                                         char **pparams, int total_params, char **ppdata, int total_data)
3020 {
3021         char *params = *pparams;
3022         char *pdata = *ppdata;
3023         uint16 tran_call = SVAL(inbuf, smb_setup0);
3024         uint16 info_level;
3025         int dosmode=0;
3026         SMB_OFF_T size=0;
3027         struct utimbuf tvs;
3028         SMB_STRUCT_STAT sbuf;
3029         pstring fname;
3030         int fd = -1;
3031         BOOL bad_path = False;
3032         files_struct *fsp = NULL;
3033         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3034         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3035         mode_t unixmode = 0;
3036         NTSTATUS status = NT_STATUS_OK;
3037
3038         if (!params)
3039                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3040
3041         if (tran_call == TRANSACT2_SETFILEINFO) {
3042                 if (total_params < 4)
3043                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3044
3045                 fsp = file_fsp(params,0);
3046                 info_level = SVAL(params,2);    
3047
3048                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3049                         /*
3050                          * This is actually a SETFILEINFO on a directory
3051                          * handle (returned from an NT SMB). NT5.0 seems
3052                          * to do this call. JRA.
3053                          */
3054                         pstrcpy(fname, fsp->fsp_name);
3055                         unix_convert(fname,conn,0,&bad_path,&sbuf);
3056                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
3057                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3058                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3059                         }
3060                 } else if (fsp && fsp->print_file) {
3061                         /*
3062                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3063                          */
3064                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3065                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3066
3067                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3068         
3069                                 SSVAL(params,0,0);
3070                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3071                                 return(-1);
3072                         } else
3073                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3074             } else {
3075                         /*
3076                          * Original code - this is an open file.
3077                          */
3078                         CHECK_FSP(fsp,conn);
3079
3080                         pstrcpy(fname, fsp->fsp_name);
3081                         fd = fsp->fd;
3082
3083                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3084                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3085                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3086                         }
3087                 }
3088         } else {
3089                 /* set path info */
3090                 if (total_params < 6)
3091                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3092
3093                 info_level = SVAL(params,0);    
3094                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3095                 if (!NT_STATUS_IS_OK(status)) {
3096                         return ERROR_NT(status);
3097                 }
3098                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3099
3100                 /*
3101                  * For CIFS UNIX extensions the target name may not exist.
3102                  */
3103
3104                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3105                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3106                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3107                 }    
3108
3109                 if(!check_name(fname, conn)) {
3110                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3111                 }
3112
3113         }
3114
3115         if (!CAN_WRITE(conn))
3116                 return ERROR_DOS(ERRSRV,ERRaccess);
3117
3118         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3119                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3120
3121         if (VALID_STAT(sbuf))
3122                 unixmode = sbuf.st_mode;
3123
3124         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3125                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3126
3127         /* Realloc the parameter and data sizes */
3128         params = Realloc(*pparams,2);
3129         if(params == NULL)
3130                 return ERROR_DOS(ERRDOS,ERRnomem);
3131         *pparams = params;
3132
3133         SSVAL(params,0,0);
3134
3135         if (fsp) {
3136                 /* the pending modtime overrides the current modtime */
3137                 sbuf.st_mtime = fsp->pending_modtime;
3138         }
3139
3140         size = get_file_size(sbuf);
3141         tvs.modtime = sbuf.st_mtime;
3142         tvs.actime = sbuf.st_atime;
3143         dosmode = dos_mode(conn,fname,&sbuf);
3144         unixmode = sbuf.st_mode;
3145
3146         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3147         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3148
3149         switch (info_level) {
3150                 case SMB_INFO_STANDARD:
3151                 {
3152                         if (total_data < 12)
3153                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3154
3155                         /* access time */
3156                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3157                         /* write time */
3158                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3159                         break;
3160                 }
3161
3162                 case SMB_INFO_SET_EA:
3163                         status = set_ea(conn, fsp, fname, pdata, total_data);
3164                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3165                                 return ERROR_NT(status);
3166                         break;
3167
3168                 /* XXXX um, i don't think this is right.
3169                         it's also not in the cifs6.txt spec.
3170                 */
3171                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3172                         if (total_data < 28)
3173                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3174
3175                         tvs.actime = make_unix_date2(pdata+8);
3176                         tvs.modtime = make_unix_date2(pdata+12);
3177                         size = IVAL(pdata,16);
3178                         dosmode = IVAL(pdata,24);
3179                         break;
3180
3181                 /* XXXX nor this.  not in cifs6.txt, either. */
3182                 case SMB_INFO_QUERY_ALL_EAS:
3183                         if (total_data < 28)
3184                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3185
3186                         tvs.actime = make_unix_date2(pdata+8);
3187                         tvs.modtime = make_unix_date2(pdata+12);
3188                         size = IVAL(pdata,16);
3189                         dosmode = IVAL(pdata,24);
3190                         break;
3191
3192                 case SMB_SET_FILE_BASIC_INFO:
3193                 case SMB_FILE_BASIC_INFORMATION:
3194                 {
3195                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3196                         time_t write_time;
3197                         time_t changed_time;
3198
3199                         if (total_data < 36)
3200                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3201
3202                         /* Ignore create time at offset pdata. */
3203
3204                         /* access time */
3205                         tvs.actime = interpret_long_date(pdata+8);
3206
3207                         write_time = interpret_long_date(pdata+16);
3208                         changed_time = interpret_long_date(pdata+24);
3209
3210                         tvs.modtime = MIN(write_time, changed_time);
3211
3212                         if (write_time > tvs.modtime && write_time != 0xffffffff) {
3213                                 tvs.modtime = write_time;
3214                         }
3215                         /* Prefer a defined time to an undefined one. */
3216                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3217                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3218                                         ? changed_time : write_time);
3219
3220                         /* attributes */
3221                         dosmode = IVAL(pdata,32);
3222                         break;
3223                 }
3224
3225                 case SMB_FILE_ALLOCATION_INFORMATION:
3226                 case SMB_SET_FILE_ALLOCATION_INFO:
3227                 {
3228                         int ret = -1;
3229                         SMB_BIG_UINT allocation_size;
3230
3231                         if (total_data < 8)
3232                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3233
3234                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3235 #ifdef LARGE_SMB_OFF_T
3236                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3237 #else /* LARGE_SMB_OFF_T */
3238                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3239                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3240 #endif /* LARGE_SMB_OFF_T */
3241                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3242                                         fname, (double)allocation_size ));
3243
3244                         if (allocation_size)
3245                                 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3246
3247                         if(allocation_size != get_file_size(sbuf)) {
3248                                 SMB_STRUCT_STAT new_sbuf;
3249  
3250                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3251                                         fname, (double)allocation_size ));
3252  
3253                                 if (fd == -1) {
3254                                         files_struct *new_fsp = NULL;
3255                                         int access_mode = 0;
3256                                         int action = 0;
3257  
3258                                         if(global_oplock_break) {
3259                                                 /* Queue this file modify as we are the process of an oplock break.  */
3260  
3261                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3262                                                 DEBUGADD(2,( "in oplock break state.\n"));
3263  
3264                                                 push_oplock_pending_smb_message(inbuf, length);
3265                                                 return -1;
3266                                         }
3267  
3268                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3269                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3270                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3271                                                                         FILE_ATTRIBUTE_NORMAL,
3272                                                                         0, &access_mode, &action);
3273  
3274                                         if (new_fsp == NULL)
3275                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3276                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3277                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3278                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3279                                                                         new_fsp->fnum, strerror(errno)));
3280                                                 ret = -1;
3281                                         }
3282                                         close_file(new_fsp,True);
3283                                 } else {
3284                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3285                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3286                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3287                                                                         fsp->fnum, strerror(errno)));
3288                                                 ret = -1;
3289                                         }
3290                                 }
3291                                 if (ret == -1)
3292                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3293
3294                                 /* Allocate can truncate size... */
3295                                 size = get_file_size(new_sbuf);
3296                         }
3297
3298                         break;
3299                 }
3300
3301                 case SMB_FILE_END_OF_FILE_INFORMATION:
3302                 case SMB_SET_FILE_END_OF_FILE_INFO:
3303                 {
3304                         if (total_data < 8)
3305                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3306
3307                         size = IVAL(pdata,0);
3308 #ifdef LARGE_SMB_OFF_T
3309                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3310 #else /* LARGE_SMB_OFF_T */
3311                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3312                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3313 #endif /* LARGE_SMB_OFF_T */
3314                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3315                         break;
3316                 }
3317
3318                 case SMB_FILE_DISPOSITION_INFORMATION:
3319                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3320                 {
3321                         BOOL delete_on_close;
3322
3323                         if (total_data < 1)
3324                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3325
3326                         delete_on_close = (CVAL(pdata,0) ? True : False);
3327
3328                         /* Just ignore this set on a path. */
3329                         if (tran_call != TRANSACT2_SETFILEINFO)
3330                                 break;
3331
3332                         if (fsp == NULL)
3333                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3334
3335                         status = set_delete_on_close_internal(fsp, delete_on_close);
3336  
3337                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3338                                 return ERROR_NT(status);
3339
3340                         /* The set is across all open files on this dev/inode pair. */
3341                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3342                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3343                                 return ERROR_NT(status);
3344
3345                         break;
3346                 }
3347
3348                 case SMB_FILE_POSITION_INFORMATION:
3349                 {
3350                         SMB_BIG_UINT position_information;
3351
3352                         if (total_data < 8)
3353                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3354
3355                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3356 #ifdef LARGE_SMB_OFF_T
3357                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3358 #else /* LARGE_SMB_OFF_T */
3359                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3360                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3361 #endif /* LARGE_SMB_OFF_T */
3362                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3363                                         fname, (double)position_information ));
3364                         if (fsp)
3365                                 fsp->position_information = position_information;
3366                         break;
3367                 }
3368
3369                 /*
3370                  * CIFS UNIX extensions.
3371                  */
3372
3373                 case SMB_SET_FILE_UNIX_BASIC:
3374                 {
3375                         uint32 raw_unixmode;
3376
3377                         if (total_data < 100)
3378                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3379
3380                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3381                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3382                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3383 #ifdef LARGE_SMB_OFF_T
3384                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3385 #else /* LARGE_SMB_OFF_T */
3386                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3387                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3388 #endif /* LARGE_SMB_OFF_T */
3389                         }
3390                         pdata+=24;          /* ctime & st_blocks are not changed */
3391                         tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3392                         tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3393                         pdata+=16;
3394                         set_owner = (uid_t)IVAL(pdata,0);
3395                         pdata += 8;
3396                         set_grp = (gid_t)IVAL(pdata,0);
3397                         pdata += 8;
3398                         raw_unixmode = IVAL(pdata,28);
3399                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3400                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
3401
3402                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3403 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3404                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3405
3406                         if (!VALID_STAT(sbuf)) {
3407
3408                                 /*
3409                                  * The only valid use of this is to create character and block
3410                                  * devices, and named pipes. This is deprecated (IMHO) and 
3411                                  * a new info level should be used for mknod. JRA.
3412                                  */
3413
3414 #if !defined(HAVE_MAKEDEV_FN)
3415                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3416 #else /* HAVE_MAKEDEV_FN */
3417                                 uint32 file_type = IVAL(pdata,0);
3418                                 uint32 dev_major = IVAL(pdata,4);
3419                                 uint32 dev_minor = IVAL(pdata,12);
3420
3421                                 uid_t myuid = geteuid();
3422                                 gid_t mygid = getegid();
3423                                 SMB_DEV_T dev;
3424
3425                                 if (tran_call == TRANSACT2_SETFILEINFO)
3426                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3427
3428                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3429                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3430
3431                                 dev = makedev(dev_major, dev_minor);
3432
3433                                 /* We can only create as the owner/group we are. */
3434
3435                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3436                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3437                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3438                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3439
3440                                 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3441                                                 file_type != UNIX_TYPE_FIFO)
3442                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3443
3444                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3445 0%o for file %s\n", (double)dev, unixmode, fname ));
3446
3447                                 /* Ok - do the mknod. */
3448                                 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3449                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3450
3451                                 inherit_access_acl(conn, fname, unixmode);
3452
3453                                 SSVAL(params,0,0);
3454                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3455                                 return(-1);
3456 #endif /* HAVE_MAKEDEV_FN */
3457
3458                         }
3459
3460                         /*
3461                          * Deal with the UNIX specific mode set.
3462                          */
3463
3464                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3465                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3466                                         (unsigned int)unixmode, fname ));
3467                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3468                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3469                         }
3470
3471                         /*
3472                          * Deal with the UNIX specific uid set.
3473                          */
3474
3475                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3476                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3477                                         (unsigned int)set_owner, fname ));
3478                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3479                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3480                         }
3481
3482                         /*
3483                          * Deal with the UNIX specific gid set.
3484                          */
3485
3486                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3487                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3488                                         (unsigned int)set_owner, fname ));
3489                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3490                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3491                         }
3492                         break;
3493                 }
3494
3495                 case SMB_SET_FILE_UNIX_LINK:
3496                 {
3497                         pstring link_target;
3498                         char *newname = fname;
3499
3500                         /* Set a symbolic link. */
3501                         /* Don't allow this if follow links is false. */
3502
3503                         if (!lp_symlinks(SNUM(conn)))
3504                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3505
3506                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3507
3508                         /* !widelinks forces the target path to be within the share. */
3509                         if (!lp_widelinks(SNUM(conn))) {
3510                                 pstring rel_name;
3511                                 char *last_dirp = NULL;
3512
3513                                 unix_format(link_target);
3514
3515                                 pstrcpy(rel_name, newname);
3516                                 last_dirp = strrchr_m(rel_name, '/');
3517                                 if (last_dirp) {
3518                                         last_dirp[1] = '\0';
3519                                 } else {
3520                                         pstrcpy(rel_name, "./");
3521                                 }
3522                                 pstrcat(rel_name, link_target);
3523                                 if (ensure_link_is_safe(conn, rel_name) != 0) {
3524                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3525                                 }
3526
3527                                 if (check_name(link_target, conn)) {
3528                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3529                                 }
3530                         }
3531
3532                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3533                                 fname, link_target ));
3534
3535                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3536                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3537                         SSVAL(params,0,0);
3538                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3539                         return(-1);
3540                 }
3541
3542                 case SMB_SET_FILE_UNIX_HLINK:
3543                 {
3544                         pstring oldname;
3545                         char *newname = fname;
3546
3547                         /* Set a hard link. */
3548                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3549                         if (!NT_STATUS_IS_OK(status)) {
3550                                 return ERROR_NT(status);
3551                         }
3552
3553                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3554                                 fname, oldname));
3555
3556                         status = hardlink_internals(conn, oldname, newname);
3557                         if (!NT_STATUS_IS_OK(status)) {
3558                                 return ERROR_NT(status);
3559                         }
3560
3561                         SSVAL(params,0,0);
3562                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3563                         return(-1);
3564                 }
3565
3566                 case SMB_FILE_RENAME_INFORMATION:
3567                 {
3568                         BOOL overwrite;
3569                         uint32 root_fid;
3570                         uint32 len;
3571                         pstring newname;
3572                         pstring base_name;
3573                         char *p;
3574
3575                         if (total_data < 12)
3576                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3577
3578                         overwrite = (CVAL(pdata,0) ? True : False);
3579                         root_fid = IVAL(pdata,4);
3580                         len = IVAL(pdata,8);
3581                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3582                         if (!NT_STATUS_IS_OK(status)) {
3583                                 return ERROR_NT(status);
3584                         }
3585
3586                         /* Check the new name has no '/' characters. */
3587                         if (strchr_m(newname, '/'))
3588                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3589
3590                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3591
3592                         /* Create the base directory. */
3593                         pstrcpy(base_name, fname);
3594                         p = strrchr_m(base_name, '/');
3595                         if (p)
3596                                 *p = '\0';
3597                         /* Append the new name. */
3598                         pstrcat(base_name, "/");
3599                         pstrcat(base_name, newname);
3600
3601                         if (fsp) {
3602                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3603                                         fsp->fnum, fsp->fsp_name, base_name ));
3604                                 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3605                         } else {
3606                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3607                                         fname, newname ));
3608                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
3609                         }
3610                         if (!NT_STATUS_IS_OK(status)) {
3611                                 return ERROR_NT(status);
3612                         }
3613                         process_pending_change_notify_queue((time_t)0);
3614                         SSVAL(params,0,0);
3615                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3616                         return(-1);
3617                 }
3618                 default:
3619                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3620         }
3621
3622         /* get some defaults (no modifications) if any info is zero or -1. */
3623         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3624                 tvs.actime = sbuf.st_atime;
3625
3626         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3627                 tvs.modtime = sbuf.st_mtime;
3628
3629         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3630         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3631         DEBUG(6,("size: %.0f ", (double)size));
3632
3633         if (dosmode) {
3634                 if (S_ISDIR(sbuf.st_mode))
3635                         dosmode |= aDIR;
3636                 else
3637                         dosmode &= ~aDIR;
3638         }
3639
3640         DEBUG(6,("dosmode: %x\n"  , dosmode));
3641
3642         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3643                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3644                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3645                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3646
3647                 /*
3648                  * Only do this test if we are not explicitly
3649                  * changing the size of a file.
3650                  */
3651                 if (!size)
3652                         size = get_file_size(sbuf);
3653         }
3654
3655         /*
3656          * Try and set the times, size and mode of this file -
3657          * if they are different from the current values
3658          */
3659         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3660                 if(fsp != NULL) {
3661                         /*
3662                          * This was a setfileinfo on an open file.
3663                          * NT does this a lot. It's actually pointless
3664                          * setting the time here, as it will be overwritten
3665                          * on the next write, so we save the request
3666                          * away and will set it on file close. JRA.
3667                          */
3668
3669                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3670                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3671                                 fsp->pending_modtime = tvs.modtime;
3672                         }
3673
3674                 } else {
3675
3676                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3677
3678                         if(file_utime(conn, fname, &tvs)!=0)
3679                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3680                 }
3681         }
3682
3683         /* check the mode isn't different, before changing it */
3684         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3685
3686                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3687
3688                 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3689                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3690                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3691                 }
3692         }
3693
3694         if (size != get_file_size(sbuf)) {
3695
3696                 int ret;
3697
3698                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3699                         fname, (double)size ));
3700
3701                 if (fd == -1) {
3702                         files_struct *new_fsp = NULL;
3703                         int access_mode = 0;
3704                         int action = 0;
3705
3706                         if(global_oplock_break) {
3707                                 /* Queue this file modify as we are the process of an oplock break.  */
3708
3709                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3710                                 DEBUGADD(2,( "in oplock break state.\n"));
3711
3712                                 push_oplock_pending_smb_message(inbuf, length);
3713                                 return -1;
3714                         }
3715
3716                         new_fsp = open_file_shared(conn, fname, &sbuf,
3717                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3718                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3719                                                 FILE_ATTRIBUTE_NORMAL,
3720                                                 0, &access_mode, &action);
3721         
3722                         if (new_fsp == NULL)
3723                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3724                         ret = vfs_set_filelen(new_fsp, size);
3725                         close_file(new_fsp,True);
3726                 } else {
3727                         ret = vfs_set_filelen(fsp, size);
3728                 }
3729
3730                 if (ret == -1)
3731                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3732         }
3733
3734         SSVAL(params,0,0);
3735         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3736   
3737         return(-1);
3738 }
3739
3740 /****************************************************************************
3741  Reply to a TRANS2_MKDIR (make directory with extended attributes).
3742 ****************************************************************************/
3743
3744 static int call_trans2mkdir(connection_struct *conn,
3745                             char *inbuf, char *outbuf, int length, int bufsize,
3746                                 char **pparams, int total_params, char **ppdata, int total_data)
3747 {
3748         char *params = *pparams;
3749         pstring directory;
3750         int ret = -1;
3751         SMB_STRUCT_STAT sbuf;
3752         BOOL bad_path = False;
3753         NTSTATUS status = NT_STATUS_OK;
3754
3755         if (!CAN_WRITE(conn))
3756                 return ERROR_DOS(ERRSRV,ERRaccess);
3757
3758         if (total_params < 4)
3759                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3760
3761         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3762         if (!NT_STATUS_IS_OK(status)) {
3763                 return ERROR_NT(status);
3764         }
3765
3766         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3767
3768         unix_convert(directory,conn,0,&bad_path,&sbuf);
3769         if (check_name(directory,conn))
3770                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3771   
3772         if(ret < 0) {
3773                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3774                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3775         }
3776
3777         /* Realloc the parameter and data sizes */
3778         params = Realloc(*pparams,2);
3779         if(params == NULL)
3780                 return ERROR_DOS(ERRDOS,ERRnomem);
3781         *pparams = params;
3782
3783         SSVAL(params,0,0);
3784
3785         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3786   
3787         return(-1);
3788 }
3789
3790 /****************************************************************************
3791  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3792  We don't actually do this - we just send a null response.
3793 ****************************************************************************/
3794
3795 static int call_trans2findnotifyfirst(connection_struct *conn,
3796                                         char *inbuf, char *outbuf, int length, int bufsize,
3797                                         char **pparams, int total_params, char **ppdata, int total_data)
3798 {
3799         static uint16 fnf_handle = 257;
3800         char *params = *pparams;
3801         uint16 info_level;
3802
3803         if (total_params < 6)
3804                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3805
3806         info_level = SVAL(params,4);
3807         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3808
3809         switch (info_level) {
3810                 case 1:
3811                 case 2:
3812                         break;
3813                 default:
3814                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3815         }
3816
3817         /* Realloc the parameter and data sizes */
3818         params = Realloc(*pparams,6);
3819         if(params == NULL) 
3820                 return ERROR_DOS(ERRDOS,ERRnomem);
3821         *pparams = params;
3822
3823         SSVAL(params,0,fnf_handle);
3824         SSVAL(params,2,0); /* No changes */
3825         SSVAL(params,4,0); /* No EA errors */
3826
3827         fnf_handle++;
3828
3829         if(fnf_handle == 0)
3830                 fnf_handle = 257;
3831
3832         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3833   
3834         return(-1);
3835 }
3836
3837 /****************************************************************************
3838  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
3839  changes). Currently this does nothing.
3840 ****************************************************************************/
3841
3842 static int call_trans2findnotifynext(connection_struct *conn,
3843                                         char *inbuf, char *outbuf, int length, int bufsize,
3844                                         char **pparams, int total_params, char **ppdata, int total_data)
3845 {
3846         char *params = *pparams;
3847
3848         DEBUG(3,("call_trans2findnotifynext\n"));
3849
3850         /* Realloc the parameter and data sizes */
3851         params = Realloc(*pparams,4);
3852         if(params == NULL)
3853                 return ERROR_DOS(ERRDOS,ERRnomem);
3854         *pparams = params;
3855
3856         SSVAL(params,0,0); /* No changes */
3857         SSVAL(params,2,0); /* No EA errors */
3858
3859         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3860   
3861         return(-1);
3862 }
3863
3864 /****************************************************************************
3865  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3866 ****************************************************************************/
3867
3868 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3869                                         char* outbuf, int length, int bufsize,
3870                                         char **pparams, int total_params, char **ppdata, int total_data)
3871 {
3872         char *params = *pparams;
3873         pstring pathname;
3874         int reply_size = 0;
3875         int max_referral_level;
3876
3877         DEBUG(10,("call_trans2getdfsreferral\n"));
3878
3879         if (total_params < 2)
3880                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3881
3882         max_referral_level = SVAL(params,0);
3883
3884         if(!lp_host_msdfs())
3885                 return ERROR_DOS(ERRDOS,ERRbadfunc);
3886
3887         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3888         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3889                 return UNIXERROR(ERRDOS,ERRbadfile);
3890     
3891         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3892         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3893
3894         return(-1);
3895 }
3896
3897 #define LMCAT_SPL       0x53
3898 #define LMFUNC_GETJOBID 0x60
3899
3900 /****************************************************************************
3901  Reply to a TRANS2_IOCTL - used for OS/2 printing.
3902 ****************************************************************************/
3903
3904 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3905                                         char* outbuf, int length, int bufsize,
3906                                         char **pparams, int total_params, char **ppdata, int total_data)
3907 {
3908         char *pdata = *ppdata;
3909         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3910
3911         /* check for an invalid fid before proceeding */
3912         
3913         if (!fsp)                                
3914                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
3915
3916         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3917                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3918                 pdata = Realloc(*ppdata, 32);
3919                 if(pdata == NULL)
3920                         return ERROR_DOS(ERRDOS,ERRnomem);
3921                 *ppdata = pdata;
3922
3923                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3924                         CAN ACCEPT THIS IN UNICODE. JRA. */
3925
3926                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
3927                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3928                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3929                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3930                 return(-1);
3931         } else {
3932                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3933                 return ERROR_DOS(ERRSRV,ERRerror);
3934         }
3935 }
3936
3937 /****************************************************************************
3938  Reply to a SMBfindclose (stop trans2 directory search).
3939 ****************************************************************************/
3940
3941 int reply_findclose(connection_struct *conn,
3942                     char *inbuf,char *outbuf,int length,int bufsize)
3943 {
3944         int outsize = 0;
3945         int dptr_num=SVALS(inbuf,smb_vwv0);
3946         START_PROFILE(SMBfindclose);
3947
3948         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3949
3950         dptr_close(&dptr_num);
3951
3952         outsize = set_message(outbuf,0,0,True);
3953
3954         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3955
3956         END_PROFILE(SMBfindclose);
3957         return(outsize);
3958 }
3959
3960 /****************************************************************************
3961  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3962 ****************************************************************************/
3963
3964 int reply_findnclose(connection_struct *conn, 
3965                      char *inbuf,char *outbuf,int length,int bufsize)
3966 {
3967         int outsize = 0;
3968         int dptr_num= -1;
3969         START_PROFILE(SMBfindnclose);
3970         
3971         dptr_num = SVAL(inbuf,smb_vwv0);
3972
3973         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3974
3975         /* We never give out valid handles for a 
3976            findnotifyfirst - so any dptr_num is ok here. 
3977            Just ignore it. */
3978
3979         outsize = set_message(outbuf,0,0,True);
3980
3981         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3982
3983         END_PROFILE(SMBfindnclose);
3984         return(outsize);
3985 }
3986
3987 /****************************************************************************
3988  Reply to a SMBtranss2 - just ignore it!
3989 ****************************************************************************/
3990
3991 int reply_transs2(connection_struct *conn,
3992                   char *inbuf,char *outbuf,int length,int bufsize)
3993 {
3994         START_PROFILE(SMBtranss2);
3995         DEBUG(4,("Ignoring transs2 of length %d\n",length));
3996         END_PROFILE(SMBtranss2);
3997         return(-1);
3998 }
3999
4000 /****************************************************************************
4001  Reply to a SMBtrans2.
4002 ****************************************************************************/
4003
4004 int reply_trans2(connection_struct *conn,
4005                  char *inbuf,char *outbuf,int length,int bufsize)
4006 {
4007         int outsize = 0;
4008         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4009         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4010 #if 0
4011         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4012         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
4013         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4014         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4015         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4016         int32 timeout = IVALS(inbuf,smb_timeout);
4017 #endif
4018         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4019         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4020         char *params = NULL, *data = NULL;
4021         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4022         START_PROFILE(SMBtrans2);
4023
4024         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4025                 /* Queue this open message as we are the process of an
4026                  * oplock break.  */
4027
4028                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4029                 DEBUGADD(2,( "in oplock break state.\n"));
4030
4031                 push_oplock_pending_smb_message(inbuf, length);
4032                 END_PROFILE(SMBtrans2);
4033                 return -1;
4034         }
4035         
4036         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4037             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4038                 END_PROFILE(SMBtrans2);
4039                 return ERROR_DOS(ERRSRV,ERRaccess);
4040         }
4041
4042         outsize = set_message(outbuf,0,0,True);
4043
4044         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4045            is so as a sanity check */
4046         if (suwcnt != 1) {
4047                 /*
4048                  * Need to have rc=0 for ioctl to get job id for OS/2.
4049                  *  Network printing will fail if function is not successful.
4050                  *  Similar function in reply.c will be used if protocol
4051                  *  is LANMAN1.0 instead of LM1.2X002.
4052                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4053                  *  outbuf doesn't have to be set(only job id is used).
4054                  */
4055                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4056                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4057                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4058                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4059                 } else {
4060                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4061                         DEBUG(2,("Transaction is %d\n",tran_call));
4062                         END_PROFILE(SMBtrans2);
4063                         ERROR_DOS(ERRDOS,ERRinvalidparam);
4064                 }
4065         }
4066     
4067         /* Allocate the space for the maximum needed parameters and data */
4068         if (total_params > 0)
4069                 params = (char *)malloc(total_params);
4070         if (total_data > 0)
4071                 data = (char *)malloc(total_data);
4072   
4073         if ((total_params && !params)  || (total_data && !data)) {
4074                 DEBUG(2,("Out of memory in reply_trans2\n"));
4075                 SAFE_FREE(params);
4076                 SAFE_FREE(data); 
4077                 END_PROFILE(SMBtrans2);
4078                 return ERROR_DOS(ERRDOS,ERRnomem);
4079         }
4080
4081         /* Copy the param and data bytes sent with this request into
4082            the params buffer */
4083         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4084         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4085
4086         if (num_params > total_params || num_data > total_data)
4087                 exit_server("invalid params in reply_trans2");
4088
4089         if(params) {
4090                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4091                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4092                         goto bad_param;
4093                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4094                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4095                         goto bad_param;
4096                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4097         }
4098         if(data) {
4099                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4100                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4101                         goto bad_param;
4102                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4103                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4104                         goto bad_param;
4105                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4106         }
4107
4108         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4109
4110         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4111                 /* We need to send an interim response then receive the rest
4112                    of the parameter/data bytes */
4113                 outsize = set_message(outbuf,0,0,True);
4114                 srv_signing_trans_stop();
4115                 if (!send_smb(smbd_server_fd(),outbuf))
4116                         exit_server("reply_trans2: send_smb failed.");
4117
4118                 while (num_data_sofar < total_data || 
4119                        num_params_sofar < total_params) {
4120                         BOOL ret;
4121                         unsigned int param_disp;
4122                         unsigned int param_off;
4123                         unsigned int data_disp;
4124                         unsigned int data_off;
4125
4126                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4127                         
4128                         /*
4129                          * The sequence number for the trans reply is always
4130                          * based on the last secondary received.
4131                          */
4132
4133                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4134
4135                         if ((ret && 
4136                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4137                                 outsize = set_message(outbuf,0,0,True);
4138                                 if(ret)
4139                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4140                                 else
4141                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4142                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4143                                 goto bad_param;
4144                         }
4145       
4146                         /* Revise total_params and total_data in case
4147                            they have changed downwards */
4148                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4149                                 total_params = SVAL(inbuf, smb_tpscnt);
4150                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4151                                 total_data = SVAL(inbuf, smb_tdscnt);
4152
4153                         num_params = SVAL(inbuf,smb_spscnt);
4154                         param_off = SVAL(inbuf, smb_spsoff);
4155                         param_disp = SVAL(inbuf, smb_spsdisp);
4156                         num_params_sofar += num_params;
4157
4158                         num_data = SVAL(inbuf, smb_sdscnt);
4159                         data_off = SVAL(inbuf, smb_sdsoff);
4160                         data_disp = SVAL(inbuf, smb_sdsdisp);
4161                         num_data_sofar += num_data;
4162
4163                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4164                                 goto bad_param;
4165                         
4166                         if (num_params) {
4167                                 if (param_disp + num_params >= total_params)
4168                                         goto bad_param;
4169                                 if ((param_disp + num_params < param_disp) ||
4170                                                 (param_disp + num_params < num_params))
4171                                         goto bad_param;
4172                                 if (param_disp > total_params)
4173                                         goto bad_param;
4174                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4175                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4176                                         goto bad_param;
4177                                 if (params + param_disp < params)
4178                                         goto bad_param;
4179
4180                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4181                         }
4182                         if (num_data) {
4183                                 if (data_disp + num_data >= total_data)
4184                                         goto bad_param;
4185                                 if ((data_disp + num_data < data_disp) ||
4186                                                 (data_disp + num_data < num_data))
4187                                         goto bad_param;
4188                                 if (data_disp > total_data)
4189                                         goto bad_param;
4190                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4191                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4192                                         goto bad_param;
4193                                 if (data + data_disp < data)
4194                                         goto bad_param;
4195
4196                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4197                         }
4198                 }
4199         }
4200         
4201         if (Protocol >= PROTOCOL_NT1) {
4202                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4203         }
4204
4205         /* Now we must call the relevant TRANS2 function */
4206         switch(tran_call)  {
4207         case TRANSACT2_OPEN:
4208                 START_PROFILE_NESTED(Trans2_open);
4209                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4210                                           &params, total_params, &data, total_data);
4211                 END_PROFILE_NESTED(Trans2_open);
4212                 break;
4213
4214         case TRANSACT2_FINDFIRST:
4215                 START_PROFILE_NESTED(Trans2_findfirst);
4216                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4217                                           &params, total_params, &data, total_data);
4218                 END_PROFILE_NESTED(Trans2_findfirst);
4219                 break;
4220
4221         case TRANSACT2_FINDNEXT:
4222                 START_PROFILE_NESTED(Trans2_findnext);
4223                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4224                                           &params, total_params, &data, total_data);
4225                 END_PROFILE_NESTED(Trans2_findnext);
4226                 break;
4227
4228         case TRANSACT2_QFSINFO:
4229                 START_PROFILE_NESTED(Trans2_qfsinfo);
4230                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4231                                           &params, total_params, &data, total_data);
4232                 END_PROFILE_NESTED(Trans2_qfsinfo);
4233             break;
4234
4235 #ifdef HAVE_SYS_QUOTAS
4236         case TRANSACT2_SETFSINFO:
4237                 START_PROFILE_NESTED(Trans2_setfsinfo);
4238                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4239                                           &params, total_params, &data, total_data);
4240                 END_PROFILE_NESTED(Trans2_setfsinfo);
4241                 break;
4242 #endif
4243         case TRANSACT2_QPATHINFO:
4244         case TRANSACT2_QFILEINFO:
4245                 START_PROFILE_NESTED(Trans2_qpathinfo);
4246                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4247                                           &params, total_params, &data, total_data);
4248                 END_PROFILE_NESTED(Trans2_qpathinfo);
4249                 break;
4250         case TRANSACT2_SETPATHINFO:
4251         case TRANSACT2_SETFILEINFO:
4252                 START_PROFILE_NESTED(Trans2_setpathinfo);
4253                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4254                                           &params, total_params, &data, total_data);
4255                 END_PROFILE_NESTED(Trans2_setpathinfo);
4256                 break;
4257
4258         case TRANSACT2_FINDNOTIFYFIRST:
4259                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4260                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
4261                                           &params, total_params, &data, total_data);
4262                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4263                 break;
4264
4265         case TRANSACT2_FINDNOTIFYNEXT:
4266                 START_PROFILE_NESTED(Trans2_findnotifynext);
4267                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
4268                                           &params, total_params, &data, total_data);
4269                 END_PROFILE_NESTED(Trans2_findnotifynext);
4270                 break;
4271         case TRANSACT2_MKDIR:
4272                 START_PROFILE_NESTED(Trans2_mkdir);
4273                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4274                                           &params, total_params, &data, total_data);
4275                 END_PROFILE_NESTED(Trans2_mkdir);
4276                 break;
4277
4278         case TRANSACT2_GET_DFS_REFERRAL:
4279                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4280                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4281                                           &params, total_params, &data, total_data);
4282                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4283                 break;
4284         case TRANSACT2_IOCTL:
4285                 START_PROFILE_NESTED(Trans2_ioctl);
4286                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4287                                           &params, total_params, &data, total_data);
4288                 END_PROFILE_NESTED(Trans2_ioctl);
4289                 break;
4290         default:
4291                 /* Error in request */
4292                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4293                 SAFE_FREE(params);
4294                 SAFE_FREE(data);
4295                 END_PROFILE(SMBtrans2);
4296                 srv_signing_trans_stop();
4297                 return ERROR_DOS(ERRSRV,ERRerror);
4298         }
4299         
4300         /* As we do not know how many data packets will need to be
4301            returned here the various call_trans2xxxx calls
4302            must send their own. Thus a call_trans2xxx routine only
4303            returns a value other than -1 when it wants to send
4304            an error packet. 
4305         */
4306         
4307         srv_signing_trans_stop();
4308
4309         SAFE_FREE(params);
4310         SAFE_FREE(data);
4311         END_PROFILE(SMBtrans2);
4312         return outsize; /* If a correct response was needed the
4313                            call_trans2xxx calls have already sent
4314                            it. If outsize != -1 then it is returning */
4315
4316   bad_param:
4317
4318         srv_signing_trans_stop();
4319         SAFE_FREE(params);
4320         SAFE_FREE(data);
4321         END_PROFILE(SMBtrans2);
4322         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4323 }