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