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