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