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