r6122: Added "hack" fix for broken SMB_INFO_VOLUME level - used by OS/2
[samba.git] / source / 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         if (!lp_ea_support(SNUM(conn))) {
241                 SIVAL(pdata,4,0);
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                         /*
2101                          * Win2k3 and previous mess this up by sending a name length
2102                          * one byte short. I believe only older clients (OS/2 Win9x) use
2103                          * this call so try fixing this by adding a terminating null to
2104                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2105                          */
2106                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2107                         SCVAL(pdata,l2_vol_cch,len);
2108                         data_len = l2_vol_szVolLabel + len;
2109                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2110                                 (unsigned)st.st_ctime, len, vname));
2111                         break;
2112
2113                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2114                 case SMB_FS_ATTRIBUTE_INFORMATION:
2115
2116
2117 #if defined(HAVE_SYS_QUOTAS)
2118                         quota_flag = FILE_VOLUME_QUOTAS;
2119 #endif
2120
2121                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2122                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2123                                 quota_flag); /* FS ATTRIBUTES */
2124
2125                         SIVAL(pdata,4,255); /* Max filename component length */
2126                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2127                                 and will think we can't do long filenames */
2128                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2129                         SIVAL(pdata,8,len);
2130                         data_len = 12 + len;
2131                         break;
2132
2133                 case SMB_QUERY_FS_LABEL_INFO:
2134                 case SMB_FS_LABEL_INFORMATION:
2135                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2136                         data_len = 4 + len;
2137                         SIVAL(pdata,0,len);
2138                         break;
2139
2140                 case SMB_QUERY_FS_VOLUME_INFO:      
2141                 case SMB_FS_VOLUME_INFORMATION:
2142
2143                         /* 
2144                          * Add volume serial number - hash of a combination of
2145                          * the called hostname and the service name.
2146                          */
2147                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2148                                 (str_checksum(get_local_machine_name())<<16));
2149
2150                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2151                         SIVAL(pdata,12,len);
2152                         data_len = 18+len;
2153                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2154                                 (int)strlen(vname),vname, lp_servicename(snum)));
2155                         break;
2156
2157                 case SMB_QUERY_FS_SIZE_INFO:
2158                 case SMB_FS_SIZE_INFORMATION:
2159                 {
2160                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2161                         data_len = 24;
2162                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2163                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2164                         }
2165                         block_size = lp_block_size(snum);
2166                         if (bsize < block_size) {
2167                                 SMB_BIG_UINT factor = block_size/bsize;
2168                                 bsize = block_size;
2169                                 dsize /= factor;
2170                                 dfree /= factor;
2171                         }
2172                         if (bsize > block_size) {
2173                                 SMB_BIG_UINT factor = bsize/block_size;
2174                                 bsize = block_size;
2175                                 dsize *= factor;
2176                                 dfree *= factor;
2177                         }
2178                         bytes_per_sector = 512;
2179                         sectors_per_unit = bsize/bytes_per_sector;
2180                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2181 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2182                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2183                         SBIG_UINT(pdata,0,dsize);
2184                         SBIG_UINT(pdata,8,dfree);
2185                         SIVAL(pdata,16,sectors_per_unit);
2186                         SIVAL(pdata,20,bytes_per_sector);
2187                         break;
2188                 }
2189
2190                 case SMB_FS_FULL_SIZE_INFORMATION:
2191                 {
2192                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2193                         data_len = 32;
2194                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2195                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2196                         }
2197                         block_size = lp_block_size(snum);
2198                         if (bsize < block_size) {
2199                                 SMB_BIG_UINT factor = block_size/bsize;
2200                                 bsize = block_size;
2201                                 dsize /= factor;
2202                                 dfree /= factor;
2203                         }
2204                         if (bsize > block_size) {
2205                                 SMB_BIG_UINT factor = bsize/block_size;
2206                                 bsize = block_size;
2207                                 dsize *= factor;
2208                                 dfree *= factor;
2209                         }
2210                         bytes_per_sector = 512;
2211                         sectors_per_unit = bsize/bytes_per_sector;
2212                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2213 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2214                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2215                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2216                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2217                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2218                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2219                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2220                         break;
2221                 }
2222
2223                 case SMB_QUERY_FS_DEVICE_INFO:
2224                 case SMB_FS_DEVICE_INFORMATION:
2225                         data_len = 8;
2226                         SIVAL(pdata,0,0); /* dev type */
2227                         SIVAL(pdata,4,0); /* characteristics */
2228                         break;
2229
2230 #ifdef HAVE_SYS_QUOTAS
2231                 case SMB_FS_QUOTA_INFORMATION:
2232                 /* 
2233                  * what we have to send --metze:
2234                  *
2235                  * Unknown1:            24 NULL bytes
2236                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2237                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2238                  * Quota Flags:         2 byte :
2239                  * Unknown3:            6 NULL bytes
2240                  *
2241                  * 48 bytes total
2242                  * 
2243                  * details for Quota Flags:
2244                  * 
2245                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2246                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2247                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2248                  * 0x0001 Enable Quotas: enable quota for this fs
2249                  *
2250                  */
2251                 {
2252                         /* we need to fake up a fsp here,
2253                          * because its not send in this call
2254                          */
2255                         files_struct fsp;
2256                         SMB_NTQUOTA_STRUCT quotas;
2257                         
2258                         ZERO_STRUCT(fsp);
2259                         ZERO_STRUCT(quotas);
2260                         
2261                         fsp.conn = conn;
2262                         fsp.fnum = -1;
2263                         fsp.fd = -1;
2264                         
2265                         /* access check */
2266                         if (current_user.uid != 0) {
2267                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2268                                         lp_servicename(SNUM(conn)),conn->user));
2269                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2270                         }
2271                         
2272                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2273                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2274                                 return ERROR_DOS(ERRSRV,ERRerror);
2275                         }
2276
2277                         data_len = 48;
2278
2279                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2280                 
2281                         /* Unknown1 24 NULL bytes*/
2282                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2283                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2284                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2285                 
2286                         /* Default Soft Quota 8 bytes */
2287                         SBIG_UINT(pdata,24,quotas.softlim);
2288
2289                         /* Default Hard Quota 8 bytes */
2290                         SBIG_UINT(pdata,32,quotas.hardlim);
2291         
2292                         /* Quota flag 2 bytes */
2293                         SSVAL(pdata,40,quotas.qflags);
2294                 
2295                         /* Unknown3 6 NULL bytes */
2296                         SSVAL(pdata,42,0);
2297                         SIVAL(pdata,44,0);
2298                         
2299                         break;
2300                 }
2301 #endif /* HAVE_SYS_QUOTAS */
2302                 case SMB_FS_OBJECTID_INFORMATION:
2303                         data_len = 64;
2304                         break;
2305
2306                 /*
2307                  * Query the version and capabilities of the CIFS UNIX extensions
2308                  * in use.
2309                  */
2310
2311                 case SMB_QUERY_CIFS_UNIX_INFO:
2312                         if (!lp_unix_extensions())
2313                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2314                         data_len = 12;
2315                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2316                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2317                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2318                         break;
2319
2320                 case SMB_MAC_QUERY_FS_INFO:
2321                         /*
2322                          * Thursby MAC extension... ONLY on NTFS filesystems
2323                          * once we do streams then we don't need this
2324                          */
2325                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2326                                 data_len = 88;
2327                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2328                                 break;
2329                         }
2330                         /* drop through */
2331                 default:
2332                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2333         }
2334
2335
2336         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2337
2338         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2339
2340         return -1;
2341 }
2342
2343 #ifdef HAVE_SYS_QUOTAS
2344 /****************************************************************************
2345  Reply to a TRANS2_SETFSINFO (set filesystem info).
2346 ****************************************************************************/
2347
2348 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2349                                         char **pparams, int total_params, char **ppdata, int total_data,
2350                                         unsigned int max_data_bytes)
2351 {
2352         char *pdata = *ppdata;
2353         char *params = *pparams;
2354         files_struct *fsp = NULL;
2355         uint16 info_level;
2356         int outsize;
2357         SMB_NTQUOTA_STRUCT quotas;
2358         
2359         ZERO_STRUCT(quotas);
2360
2361         DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2362
2363         /* access check */
2364         if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2365                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2366                         lp_servicename(SNUM(conn)),conn->user));
2367                 return ERROR_DOS(ERRSRV,ERRaccess);
2368         }
2369
2370         /*  */
2371         if (total_params < 4) {
2372                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2373                         total_params));
2374                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2375         }
2376
2377         fsp = file_fsp(params,0);
2378
2379         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2380                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2381                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2382         }
2383
2384         info_level = SVAL(params,2);
2385
2386         switch(info_level) {
2387                 case SMB_FS_QUOTA_INFORMATION:
2388                         /* note: normaly there're 48 bytes,
2389                          * but we didn't use the last 6 bytes for now 
2390                          * --metze 
2391                          */
2392                         if (total_data < 42) {
2393                                 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2394                                         total_data));
2395                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2396                         }
2397                         
2398                         /* unknown_1 24 NULL bytes in pdata*/
2399                 
2400                         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2401                         quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2402 #ifdef LARGE_SMB_OFF_T
2403                         quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2404 #else /* LARGE_SMB_OFF_T */
2405                         if ((IVAL(pdata,28) != 0)&&
2406                                 ((quotas.softlim != 0xFFFFFFFF)||
2407                                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2408                                 /* more than 32 bits? */
2409                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2410                         }
2411 #endif /* LARGE_SMB_OFF_T */
2412                 
2413                         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2414                         quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2415 #ifdef LARGE_SMB_OFF_T
2416                         quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2417 #else /* LARGE_SMB_OFF_T */
2418                         if ((IVAL(pdata,36) != 0)&&
2419                                 ((quotas.hardlim != 0xFFFFFFFF)||
2420                                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2421                                 /* more than 32 bits? */
2422                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2423                         }
2424 #endif /* LARGE_SMB_OFF_T */
2425                 
2426                         /* quota_flags 2 bytes **/
2427                         quotas.qflags = SVAL(pdata,40);
2428                 
2429                         /* unknown_2 6 NULL bytes follow*/
2430                 
2431                         /* now set the quotas */
2432                         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2433                                 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2434                                 return ERROR_DOS(ERRSRV,ERRerror);
2435                         }
2436                         
2437                         break;
2438                 default:
2439                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2440                                 info_level));
2441                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2442                         break;
2443         }
2444
2445         /* 
2446          * sending this reply works fine, 
2447          * but I'm not sure it's the same 
2448          * like windows do...
2449          * --metze
2450          */ 
2451         outsize = set_message(outbuf,10,0,True);
2452
2453         return outsize;
2454 }
2455 #endif /* HAVE_SYS_QUOTAS */
2456
2457 /****************************************************************************
2458  Utility function to set bad path error.
2459 ****************************************************************************/
2460
2461 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2462 {
2463         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2464                         err, (int)bad_path ));
2465
2466         if(err == ENOENT) {
2467                 if (bad_path) {
2468                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2469                 } else {
2470                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2471                 }
2472         }
2473         return UNIXERROR(def_class,def_code);
2474 }
2475
2476 #if defined(HAVE_POSIX_ACLS)
2477 /****************************************************************************
2478  Utility function to count the number of entries in a POSIX acl.
2479 ****************************************************************************/
2480
2481 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2482 {
2483         unsigned int ace_count = 0;
2484         int entry_id = SMB_ACL_FIRST_ENTRY;
2485         SMB_ACL_ENTRY_T entry;
2486
2487         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2488                 /* get_next... */
2489                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2490                         entry_id = SMB_ACL_NEXT_ENTRY;
2491                 }
2492                 ace_count++;
2493         }
2494         return ace_count;
2495 }
2496
2497 /****************************************************************************
2498  Utility function to marshall a POSIX acl into wire format.
2499 ****************************************************************************/
2500
2501 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2502 {
2503         int entry_id = SMB_ACL_FIRST_ENTRY;
2504         SMB_ACL_ENTRY_T entry;
2505
2506         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2507                 SMB_ACL_TAG_T tagtype;
2508                 SMB_ACL_PERMSET_T permset;
2509                 unsigned char perms = 0;
2510                 unsigned int own_grp;
2511
2512                 /* get_next... */
2513                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2514                         entry_id = SMB_ACL_NEXT_ENTRY;
2515                 }
2516
2517                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2518                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2519                         return False;
2520                 }
2521
2522                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2523                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2524                         return False;
2525                 }
2526
2527                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2528                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2529                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2530
2531                 SCVAL(pdata,1,perms);
2532
2533                 switch (tagtype) {
2534                         case SMB_ACL_USER_OBJ:
2535                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2536                                 own_grp = (unsigned int)pst->st_uid;
2537                                 SIVAL(pdata,2,own_grp);
2538                                 SIVAL(pdata,6,0);
2539                                 break;
2540                         case SMB_ACL_USER:
2541                                 {
2542                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2543                                         if (!puid) {
2544                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2545                                         }
2546                                         own_grp = (unsigned int)*puid;
2547                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2548                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2549                                         SIVAL(pdata,2,own_grp);
2550                                         SIVAL(pdata,6,0);
2551                                         break;
2552                                 }
2553                         case SMB_ACL_GROUP_OBJ:
2554                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2555                                 own_grp = (unsigned int)pst->st_gid;
2556                                 SIVAL(pdata,2,own_grp);
2557                                 SIVAL(pdata,6,0);
2558                                 break;
2559                         case SMB_ACL_GROUP:
2560                                 {
2561                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2562                                         if (!pgid) {
2563                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2564                                         }
2565                                         own_grp = (unsigned int)*pgid;
2566                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2567                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2568                                         SIVAL(pdata,2,own_grp);
2569                                         SIVAL(pdata,6,0);
2570                                         break;
2571                                 }
2572                         case SMB_ACL_MASK:
2573                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2574                                 SIVAL(pdata,2,0xFFFFFFFF);
2575                                 SIVAL(pdata,6,0xFFFFFFFF);
2576                                 break;
2577                         case SMB_ACL_OTHER:
2578                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2579                                 SIVAL(pdata,2,0xFFFFFFFF);
2580                                 SIVAL(pdata,6,0xFFFFFFFF);
2581                                 break;
2582                         default:
2583                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2584                                 return False;
2585                 }
2586                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2587         }
2588
2589         return True;
2590 }
2591 #endif
2592
2593 /****************************************************************************
2594  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2595  file name or file id).
2596 ****************************************************************************/
2597
2598 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2599                                         char **pparams, int total_params, char **ppdata, int total_data,
2600                                         unsigned int max_data_bytes)
2601 {
2602         char *params = *pparams;
2603         char *pdata = *ppdata;
2604         uint16 tran_call = SVAL(inbuf, smb_setup0);
2605         uint16 info_level;
2606         int mode=0;
2607         SMB_OFF_T file_size=0;
2608         SMB_BIG_UINT allocation_size=0;
2609         unsigned int data_size = 0;
2610         unsigned int param_size = 2;
2611         SMB_STRUCT_STAT sbuf;
2612         pstring fname, dos_fname;
2613         char *fullpathname;
2614         char *base_name;
2615         char *p;
2616         SMB_OFF_T pos = 0;
2617         BOOL bad_path = False;
2618         BOOL delete_pending = False;
2619         int len;
2620         time_t c_time;
2621         files_struct *fsp = NULL;
2622         TALLOC_CTX *ea_ctx = NULL;
2623         struct ea_list *ea_list = NULL;
2624         uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2625
2626         if (!params)
2627                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2628
2629         ZERO_STRUCT(sbuf);
2630
2631         if (tran_call == TRANSACT2_QFILEINFO) {
2632                 if (total_params < 4) {
2633                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2634                 }
2635
2636                 fsp = file_fsp(params,0);
2637                 info_level = SVAL(params,2);
2638
2639                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2640
2641                 if(fsp && (fsp->fake_file_handle)) {
2642                         /*
2643                          * This is actually for the QUOTA_FAKE_FILE --metze
2644                          */
2645                                                 
2646                         pstrcpy(fname, fsp->fsp_name);
2647                         /* We know this name is ok, it's already passed the checks. */
2648                         
2649                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2650                         /*
2651                          * This is actually a QFILEINFO on a directory
2652                          * handle (returned from an NT SMB). NT5.0 seems
2653                          * to do this call. JRA.
2654                          */
2655                         /* We know this name is ok, it's already passed the checks. */
2656                         pstrcpy(fname, fsp->fsp_name);
2657                   
2658                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2659                                 /* Always do lstat for UNIX calls. */
2660                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2661                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2662                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2663                                 }
2664                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2665                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2666                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2667                         }
2668
2669                         delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2670                 } else {
2671                         /*
2672                          * Original code - this is an open file.
2673                          */
2674                         CHECK_FSP(fsp,conn);
2675
2676                         pstrcpy(fname, fsp->fsp_name);
2677                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2678                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2679                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2680                         }
2681                         pos = fsp->position_information;
2682                         delete_pending = fsp->delete_on_close;
2683                         desired_access = fsp->desired_access;
2684                 }
2685         } else {
2686                 NTSTATUS status = NT_STATUS_OK;
2687
2688                 /* qpathinfo */
2689                 if (total_params < 6) {
2690                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2691                 }
2692
2693                 info_level = SVAL(params,0);
2694
2695                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2696
2697                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2698                 if (!NT_STATUS_IS_OK(status)) {
2699                         return ERROR_NT(status);
2700                 }
2701
2702                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2703
2704                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2705                 if (bad_path) {
2706                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2707                 }
2708                 if (!check_name(fname,conn)) {
2709                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2710                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2711                 }
2712
2713                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2714                         /* Always do lstat for UNIX calls. */
2715                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2716                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2717                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2718                         }
2719                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2720                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2721                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2722                 }
2723         }
2724
2725         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2726                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2727
2728         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2729                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2730
2731         p = strrchr_m(fname,'/'); 
2732         if (!p)
2733                 base_name = fname;
2734         else
2735                 base_name = p+1;
2736
2737         mode = dos_mode(conn,fname,&sbuf);
2738         if (!mode)
2739                 mode = FILE_ATTRIBUTE_NORMAL;
2740
2741         fullpathname = fname;
2742         file_size = get_file_size(sbuf);
2743         allocation_size = get_allocation_size(conn,fsp,&sbuf);
2744         if (mode & aDIR) {
2745                 /* This is necessary, as otherwise the desktop.ini file in
2746                  * this folder is ignored */
2747                 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2748                 file_size = 0;
2749         }
2750
2751         /* Pull any EA list from the data portion. */
2752         if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2753                 uint32 ea_size;
2754
2755                 if (total_data < 4) {
2756                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2757                 }
2758                 ea_size = IVAL(pdata,0);
2759
2760                 if (total_data > 0 && ea_size != total_data) {
2761                         DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2762 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2763                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2764                 }
2765
2766                 if (!lp_ea_support(SNUM(conn))) {
2767                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2768                 }
2769
2770                 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2771                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2772                 }
2773
2774                 /* Pull out the list of names. */
2775                 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
2776                 if (!ea_list) {
2777                         talloc_destroy(ea_ctx);
2778                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2779                 }
2780         }
2781
2782         params = SMB_REALLOC(*pparams,2);
2783         if (params == NULL) {
2784                 talloc_destroy(ea_ctx);
2785                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2786         }
2787         *pparams = params;
2788         memset((char *)params,'\0',2);
2789         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2790         pdata = SMB_REALLOC(*ppdata, data_size); 
2791         if ( pdata == NULL ) {
2792                 talloc_destroy(ea_ctx);
2793                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2794         }
2795         *ppdata = pdata;
2796
2797         memset((char *)pdata,'\0',data_size);
2798
2799         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2800
2801         if (fsp) {
2802                 if (fsp->pending_modtime) {
2803                         /* the pending modtime overrides the current modtime */
2804                         sbuf.st_mtime = fsp->pending_modtime;
2805                 }
2806         } else {
2807                 /* Do we have this path open ? */
2808                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2809                 if (fsp1 && fsp1->pending_modtime) {
2810                         /* the pending modtime overrides the current modtime */
2811                         sbuf.st_mtime = fsp1->pending_modtime;
2812                 }
2813         }
2814
2815         if (lp_dos_filetime_resolution(SNUM(conn))) {
2816                 c_time &= ~1;
2817                 sbuf.st_atime &= ~1;
2818                 sbuf.st_ctime &= ~1;
2819                 sbuf.st_mtime &= ~1;
2820         }
2821
2822         /* NT expects the name to be in an exact form of the *full*
2823            filename. See the trans2 torture test */
2824         if (strequal(base_name,".")) {
2825                 pstrcpy(dos_fname, "\\");
2826         } else {
2827                 pstr_sprintf(dos_fname, "\\%s", fname);
2828                 string_replace(dos_fname, '/', '\\');
2829         }
2830
2831         switch (info_level) {
2832                 case SMB_INFO_STANDARD:
2833                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2834                         data_size = 22;
2835                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2836                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2837                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2838                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2839                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2840                         SSVAL(pdata,l1_attrFile,mode);
2841                         break;
2842
2843                 case SMB_INFO_QUERY_EA_SIZE:
2844                 {
2845                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2846                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2847                         data_size = 26;
2848                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2849                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2850                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2851                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2852                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2853                         SSVAL(pdata,l1_attrFile,mode);
2854                         SIVAL(pdata,l1_attrFile+2,ea_size);
2855                         break;
2856                 }
2857
2858                 case SMB_INFO_IS_NAME_VALID:
2859                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2860                         if (tran_call == TRANSACT2_QFILEINFO) {
2861                                 /* os/2 needs this ? really ?*/      
2862                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2863                         }
2864                         data_size = 0;
2865                         param_size = 0;
2866                         break;
2867                         
2868                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2869                 {
2870                         size_t total_ea_len = 0;
2871                         struct ea_list *ea_file_list = NULL;
2872
2873                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2874
2875                         ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2876                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2877
2878                         if (!ea_list || (total_ea_len > data_size)) {
2879                                 talloc_destroy(ea_ctx);
2880                                 data_size = 4;
2881                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
2882                                 break;
2883                         }
2884
2885                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2886                         talloc_destroy(ea_ctx);
2887                         break;
2888                 }
2889
2890                 case SMB_INFO_QUERY_ALL_EAS:
2891                 {
2892                         /* We have data_size bytes to put EA's into. */
2893                         size_t total_ea_len = 0;
2894
2895                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2896
2897                         ea_ctx = talloc_init("ea_ctx");
2898                         if (!ea_ctx) {
2899                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2900                         }
2901
2902                         ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2903                         if (!ea_list || (total_ea_len > data_size)) {
2904                                 talloc_destroy(ea_ctx);
2905                                 data_size = 4;
2906                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
2907                                 break;
2908                         }
2909
2910                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2911                         talloc_destroy(ea_ctx);
2912                         break;
2913                 }
2914
2915                 case SMB_FILE_BASIC_INFORMATION:
2916                 case SMB_QUERY_FILE_BASIC_INFO:
2917
2918                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2919                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2920                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2921                         } else {
2922                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2923                                 data_size = 40;
2924                                 SIVAL(pdata,36,0);
2925                         }
2926                         put_long_date(pdata,c_time);
2927                         put_long_date(pdata+8,sbuf.st_atime);
2928                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2929                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2930                         SIVAL(pdata,32,mode);
2931
2932                         DEBUG(5,("SMB_QFBI - "));
2933                         {
2934                                 time_t create_time = c_time;
2935                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2936                         }
2937                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2938                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2939                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2940                         DEBUG(5,("mode: %x\n", mode));
2941
2942                         break;
2943
2944                 case SMB_FILE_STANDARD_INFORMATION:
2945                 case SMB_QUERY_FILE_STANDARD_INFO:
2946
2947                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2948                         data_size = 24;
2949                         SOFF_T(pdata,0,allocation_size);
2950                         SOFF_T(pdata,8,file_size);
2951                         if (delete_pending & sbuf.st_nlink)
2952                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2953                         else
2954                                 SIVAL(pdata,16,sbuf.st_nlink);
2955                         SCVAL(pdata,20,0);
2956                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2957                         break;
2958
2959                 case SMB_FILE_EA_INFORMATION:
2960                 case SMB_QUERY_FILE_EA_INFO:
2961                 {
2962                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2963                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2964                         data_size = 4;
2965                         SIVAL(pdata,0,ea_size);
2966                         break;
2967                 }
2968
2969                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2970                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2971                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2972                 {
2973                         pstring short_name;
2974
2975                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2976                         pstrcpy(short_name,base_name);
2977                         /* Mangle if not already 8.3 */
2978                         if(!mangle_is_8_3(short_name, True)) {
2979                                 mangle_map(short_name,True,True,SNUM(conn));
2980                         }
2981                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2982                         data_size = 4 + len;
2983                         SIVAL(pdata,0,len);
2984                         break;
2985                 }
2986
2987                 case SMB_QUERY_FILE_NAME_INFO:
2988                         /*
2989                           this must be *exactly* right for ACLs on mapped drives to work
2990                          */
2991                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2992                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2993                         data_size = 4 + len;
2994                         SIVAL(pdata,0,len);
2995                         break;
2996
2997                 case SMB_FILE_ALLOCATION_INFORMATION:
2998                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2999                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3000                         data_size = 8;
3001                         SOFF_T(pdata,0,allocation_size);
3002                         break;
3003
3004                 case SMB_FILE_END_OF_FILE_INFORMATION:
3005                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3006                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3007                         data_size = 8;
3008                         SOFF_T(pdata,0,file_size);
3009                         break;
3010
3011                 case SMB_QUERY_FILE_ALL_INFO:
3012                 case SMB_FILE_ALL_INFORMATION:
3013                 {
3014                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3015                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3016                         put_long_date(pdata,c_time);
3017                         put_long_date(pdata+8,sbuf.st_atime);
3018                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3019                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3020                         SIVAL(pdata,32,mode);
3021                         pdata += 40;
3022                         SOFF_T(pdata,0,allocation_size);
3023                         SOFF_T(pdata,8,file_size);
3024                         if (delete_pending && sbuf.st_nlink)
3025                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
3026                         else
3027                                 SIVAL(pdata,16,sbuf.st_nlink);
3028                         SCVAL(pdata,20,delete_pending);
3029                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3030                         pdata += 24;
3031                         SIVAL(pdata,0,ea_size);
3032                         pdata += 4; /* EA info */
3033                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3034                         SIVAL(pdata,0,len);
3035                         pdata += 4 + len;
3036                         data_size = PTR_DIFF(pdata,(*ppdata));
3037                         break;
3038                 }
3039                 case SMB_FILE_INTERNAL_INFORMATION:
3040                         /* This should be an index number - looks like
3041                            dev/ino to me :-) 
3042
3043                            I think this causes us to fail the IFSKIT
3044                            BasicFileInformationTest. -tpot */
3045
3046                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3047                         SIVAL(pdata,0,sbuf.st_dev);
3048                         SIVAL(pdata,4,sbuf.st_ino);
3049                         data_size = 8;
3050                         break;
3051
3052                 case SMB_FILE_ACCESS_INFORMATION:
3053                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3054                         SIVAL(pdata,0,desired_access);
3055                         data_size = 4;
3056                         break;
3057
3058                 case SMB_FILE_NAME_INFORMATION:
3059                         /* Pathname with leading '\'. */
3060                         {
3061                                 size_t byte_len;
3062                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3063                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3064                                 SIVAL(pdata,0,byte_len);
3065                                 data_size = 4 + byte_len;
3066                                 break;
3067                         }
3068
3069                 case SMB_FILE_DISPOSITION_INFORMATION:
3070                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3071                         data_size = 1;
3072                         SCVAL(pdata,0,delete_pending);
3073                         break;
3074
3075                 case SMB_FILE_POSITION_INFORMATION:
3076                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3077                         data_size = 8;
3078                         SOFF_T(pdata,0,pos);
3079                         break;
3080
3081                 case SMB_FILE_MODE_INFORMATION:
3082                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3083                         SIVAL(pdata,0,mode);
3084                         data_size = 4;
3085                         break;
3086
3087                 case SMB_FILE_ALIGNMENT_INFORMATION:
3088                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3089                         SIVAL(pdata,0,0); /* No alignment needed. */
3090                         data_size = 4;
3091                         break;
3092
3093 #if 0
3094                 /*
3095                  * NT4 server just returns "invalid query" to this - if we try to answer
3096                  * it then NTws gets a BSOD! (tridge).
3097                  * W2K seems to want this. JRA.
3098                  */
3099                 case SMB_QUERY_FILE_STREAM_INFO:
3100 #endif
3101                 case SMB_FILE_STREAM_INFORMATION:
3102                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3103                         if (mode & aDIR) {
3104                                 data_size = 0;
3105                         } else {
3106                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3107                                 SIVAL(pdata,0,0); /* ??? */
3108                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3109                                 SOFF_T(pdata,8,file_size);
3110                                 SIVAL(pdata,16,allocation_size);
3111                                 SIVAL(pdata,20,0); /* ??? */
3112                                 data_size = 24 + byte_len;
3113                         }
3114                         break;
3115
3116                 case SMB_QUERY_COMPRESSION_INFO:
3117                 case SMB_FILE_COMPRESSION_INFORMATION:
3118                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3119                         SOFF_T(pdata,0,file_size);
3120                         SIVAL(pdata,8,0); /* ??? */
3121                         SIVAL(pdata,12,0); /* ??? */
3122                         data_size = 16;
3123                         break;
3124
3125                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3126                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3127                         put_long_date(pdata,c_time);
3128                         put_long_date(pdata+8,sbuf.st_atime);
3129                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3130                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3131                         SIVAL(pdata,32,allocation_size);
3132                         SOFF_T(pdata,40,file_size);
3133                         SIVAL(pdata,48,mode);
3134                         SIVAL(pdata,52,0); /* ??? */
3135                         data_size = 56;
3136                         break;
3137
3138                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3139                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3140                         SIVAL(pdata,0,mode);
3141                         SIVAL(pdata,4,0);
3142                         data_size = 8;
3143                         break;
3144
3145                 /*
3146                  * CIFS UNIX Extensions.
3147                  */
3148
3149                 case SMB_QUERY_FILE_UNIX_BASIC:
3150
3151                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3152                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3153
3154                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
3155                         pdata += 8;
3156
3157                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3158                         pdata += 8;
3159
3160                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
3161                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
3162                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
3163                         pdata += 24;
3164
3165                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
3166                         SIVAL(pdata,4,0);
3167                         pdata += 8;
3168
3169                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
3170                         SIVAL(pdata,4,0);
3171                         pdata += 8;
3172
3173                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3174                         pdata += 4;
3175
3176                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
3177                         SIVAL(pdata,4,0);
3178                         pdata += 8;
3179
3180                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
3181                         SIVAL(pdata,4,0);
3182                         pdata += 8;
3183
3184                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
3185                         pdata += 8;
3186                                 
3187                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
3188                         SIVAL(pdata,4,0);
3189                         pdata += 8;
3190
3191                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
3192                         SIVAL(pdata,4,0);
3193                         pdata += 8+1;
3194                         data_size = PTR_DIFF(pdata,(*ppdata));
3195
3196                         {
3197                                 int i;
3198                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3199
3200                                 for (i=0; i<100; i++)
3201                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3202                                 DEBUG(4,("\n"));
3203                         }
3204
3205                         break;
3206
3207                 case SMB_QUERY_FILE_UNIX_LINK:
3208                         {
3209                                 pstring buffer;
3210
3211                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3212 #ifdef S_ISLNK
3213                                 if(!S_ISLNK(sbuf.st_mode))
3214                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3215 #else
3216                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3217 #endif
3218                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3219                                 if (len == -1)
3220                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3221                                 buffer[len] = 0;
3222                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3223                                 pdata += len;
3224                                 data_size = PTR_DIFF(pdata,(*ppdata));
3225
3226                                 break;
3227                         }
3228
3229 #if defined(HAVE_POSIX_ACLS)
3230                 case SMB_QUERY_POSIX_ACL:
3231                         {
3232                                 SMB_ACL_T file_acl = NULL;
3233                                 SMB_ACL_T def_acl = NULL;
3234                                 uint16 num_file_acls = 0;
3235                                 uint16 num_def_acls = 0;
3236
3237                                 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3238                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3239                                 } else {
3240                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3241                                 }
3242
3243                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3244                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3245                                                 fname ));
3246                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3247                                 }
3248
3249                                 if (S_ISDIR(sbuf.st_mode)) {
3250                                         if (fsp && fsp->is_directory) {
3251                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3252                                         } else {
3253                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3254                                         }
3255                                         def_acl = free_empty_sys_acl(conn, def_acl);
3256                                 }
3257
3258                                 num_file_acls = count_acl_entries(conn, file_acl);
3259                                 num_def_acls = count_acl_entries(conn, def_acl);
3260
3261                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3262                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3263                                                 data_size,
3264                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3265                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3266                                         if (file_acl) {
3267                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3268                                         }
3269                                         if (def_acl) {
3270                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3271                                         }
3272                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3273                                 }
3274
3275                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3276                                 SSVAL(pdata,2,num_file_acls);
3277                                 SSVAL(pdata,4,num_def_acls);
3278                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3279                                         if (file_acl) {
3280                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3281                                         }
3282                                         if (def_acl) {
3283                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3284                                         }
3285                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3286                                 }
3287                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3288                                         if (file_acl) {
3289                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3290                                         }
3291                                         if (def_acl) {
3292                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3293                                         }
3294                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3295                                 }
3296
3297                                 if (file_acl) {
3298                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3299                                 }
3300                                 if (def_acl) {
3301                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3302                                 }
3303                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3304                                 break;
3305                         }
3306 #endif
3307
3308                 default:
3309                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3310         }
3311
3312         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3313
3314         return(-1);
3315 }
3316
3317 /****************************************************************************
3318  Deal with the internal needs of setting the delete on close flag. Note that
3319  as the tdb locking is recursive, it is safe to call this from within 
3320  open_file_shared. JRA.
3321 ****************************************************************************/
3322
3323 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3324 {
3325         if (delete_on_close) {
3326                 /*
3327                  * Only allow delete on close for writable files.
3328                  */
3329
3330                 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3331                         if (dosmode & aRONLY) {
3332                                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3333                                         fsp->fsp_name ));
3334                                 return NT_STATUS_CANNOT_DELETE;
3335                         }
3336                 }
3337
3338                 /*
3339                  * Only allow delete on close for writable shares.
3340                  */
3341
3342                 if (!CAN_WRITE(fsp->conn)) {
3343                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3344                                 fsp->fsp_name ));
3345                         return NT_STATUS_ACCESS_DENIED;
3346                 }
3347
3348                 /*
3349                  * Only allow delete on close for files/directories opened with delete intent.
3350                  */
3351
3352                 if (!(fsp->desired_access & DELETE_ACCESS)) {
3353                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3354                                 fsp->fsp_name ));
3355                         return NT_STATUS_ACCESS_DENIED;
3356                 }
3357         }
3358
3359         if(fsp->is_directory) {
3360                 fsp->directory_delete_on_close = delete_on_close;
3361                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3362                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3363         } else {
3364                 fsp->delete_on_close = delete_on_close;
3365                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3366                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3367         }
3368
3369         return NT_STATUS_OK;
3370 }
3371
3372 /****************************************************************************
3373  Sets the delete on close flag over all share modes on this file.
3374  Modify the share mode entry for all files open
3375  on this device and inode to tell other smbds we have
3376  changed the delete on close flag. This will be noticed
3377  in the close code, the last closer will delete the file
3378  if flag is set.
3379 ****************************************************************************/
3380
3381 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3382 {
3383         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3384                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3385
3386         if (fsp->is_directory || fsp->is_stat)
3387                 return NT_STATUS_OK;
3388
3389         if (lock_share_entry_fsp(fsp) == False)
3390                 return NT_STATUS_ACCESS_DENIED;
3391
3392         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3393                 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3394                         fsp->fsp_name ));
3395                 unlock_share_entry_fsp(fsp);
3396                 return NT_STATUS_ACCESS_DENIED;
3397         }
3398
3399         unlock_share_entry_fsp(fsp);
3400         return NT_STATUS_OK;
3401 }
3402
3403 /****************************************************************************
3404  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3405  code.
3406 ****************************************************************************/
3407
3408 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3409 {
3410         BOOL bad_path_oldname = False;
3411         BOOL bad_path_newname = False;
3412         SMB_STRUCT_STAT sbuf1, sbuf2;
3413         pstring last_component_oldname;
3414         pstring last_component_newname;
3415         NTSTATUS status = NT_STATUS_OK;
3416
3417         ZERO_STRUCT(sbuf1);
3418         ZERO_STRUCT(sbuf2);
3419
3420         /* No wildcards. */
3421         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3422                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3423         }
3424
3425         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3426         if (bad_path_oldname) {
3427                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3428         }
3429
3430         /* Quick check for "." and ".." */
3431         if (last_component_oldname[0] == '.') {
3432                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3433                         return NT_STATUS_OBJECT_NAME_INVALID;
3434                 }
3435         }
3436
3437         /* source must already exist. */
3438         if (!VALID_STAT(sbuf1)) {
3439                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3440         }
3441
3442         if (!check_name(oldname,conn)) {
3443                 return NT_STATUS_ACCESS_DENIED;
3444         }
3445
3446         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3447         if (bad_path_newname) {
3448                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3449         }
3450
3451         /* Quick check for "." and ".." */
3452         if (last_component_newname[0] == '.') {
3453                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3454                         return NT_STATUS_OBJECT_NAME_INVALID;
3455                 }
3456         }
3457
3458         /* Disallow if newname already exists. */
3459         if (VALID_STAT(sbuf2)) {
3460                 return NT_STATUS_OBJECT_NAME_COLLISION;
3461         }
3462
3463         if (!check_name(newname,conn)) {
3464                 return NT_STATUS_ACCESS_DENIED;
3465         }
3466
3467         /* No links from a directory. */
3468         if (S_ISDIR(sbuf1.st_mode)) {
3469                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3470         }
3471
3472         /* Ensure this is within the share. */
3473         if (!reduce_name(conn, oldname) != 0)
3474                 return NT_STATUS_ACCESS_DENIED;
3475
3476         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3477
3478         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3479                 status = map_nt_error_from_unix(errno);
3480                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3481                                 nt_errstr(status), newname, oldname));
3482         }
3483
3484         return status;
3485 }
3486
3487 /****************************************************************************
3488  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3489 ****************************************************************************/
3490
3491 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3492                                         char **pparams, int total_params, char **ppdata, int total_data,
3493                                         unsigned int max_data_bytes)
3494 {
3495         char *params = *pparams;
3496         char *pdata = *ppdata;
3497         uint16 tran_call = SVAL(inbuf, smb_setup0);
3498         uint16 info_level;
3499         int dosmode=0;
3500         SMB_OFF_T size=0;
3501         struct utimbuf tvs;
3502         SMB_STRUCT_STAT sbuf;
3503         pstring fname;
3504         int fd = -1;
3505         BOOL bad_path = False;
3506         files_struct *fsp = NULL;
3507         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3508         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3509         mode_t unixmode = 0;
3510         NTSTATUS status = NT_STATUS_OK;
3511
3512         if (!params)
3513                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3514
3515         ZERO_STRUCT(sbuf);
3516
3517         if (tran_call == TRANSACT2_SETFILEINFO) {
3518                 if (total_params < 4) {
3519                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3520                 }
3521
3522                 fsp = file_fsp(params,0);
3523                 info_level = SVAL(params,2);    
3524
3525                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3526                         /*
3527                          * This is actually a SETFILEINFO on a directory
3528                          * handle (returned from an NT SMB). NT5.0 seems
3529                          * to do this call. JRA.
3530                          */
3531                         pstrcpy(fname, fsp->fsp_name);
3532                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3533                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3534                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3535                         }
3536                 } else if (fsp && fsp->print_file) {
3537                         /*
3538                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3539                          */
3540                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3541                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3542
3543                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3544         
3545                                 SSVAL(params,0,0);
3546                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3547                                 return(-1);
3548                         } else
3549                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3550             } else {
3551                         /*
3552                          * Original code - this is an open file.
3553                          */
3554                         CHECK_FSP(fsp,conn);
3555
3556                         pstrcpy(fname, fsp->fsp_name);
3557                         fd = fsp->fd;
3558
3559                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3560                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3561                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3562                         }
3563                 }
3564         } else {
3565                 /* set path info */
3566                 if (total_params < 6) {
3567                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3568                 }
3569
3570                 info_level = SVAL(params,0);    
3571                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3572                 if (!NT_STATUS_IS_OK(status)) {
3573                         return ERROR_NT(status);
3574                 }
3575                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3576                 if (bad_path) {
3577                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3578                 }
3579
3580                 /*
3581                  * For CIFS UNIX extensions the target name may not exist.
3582                  */
3583
3584                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3585                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3586                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3587                 }    
3588
3589                 if(!check_name(fname, conn)) {
3590                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3591                 }
3592
3593         }
3594
3595         if (!CAN_WRITE(conn))
3596                 return ERROR_DOS(ERRSRV,ERRaccess);
3597
3598         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3599                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3600
3601         if (VALID_STAT(sbuf))
3602                 unixmode = sbuf.st_mode;
3603
3604         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3605                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3606
3607         /* Realloc the parameter size */
3608         params = SMB_REALLOC(*pparams,2);
3609         if(params == NULL) {
3610                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3611         }
3612         *pparams = params;
3613
3614         SSVAL(params,0,0);
3615
3616         if (fsp && fsp->pending_modtime) {
3617                 /* the pending modtime overrides the current modtime */
3618                 sbuf.st_mtime = fsp->pending_modtime;
3619         }
3620
3621         size = get_file_size(sbuf);
3622         tvs.modtime = sbuf.st_mtime;
3623         tvs.actime = sbuf.st_atime;
3624         dosmode = dos_mode(conn,fname,&sbuf);
3625         unixmode = sbuf.st_mode;
3626
3627         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3628         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3629
3630         switch (info_level) {
3631                 case SMB_INFO_STANDARD:
3632                 {
3633                         if (total_data < 12) {
3634                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3635                         }
3636
3637                         /* access time */
3638                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3639                         /* write time */
3640                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3641                         break;
3642                 }
3643
3644                 case SMB_INFO_SET_EA:
3645                 {
3646                         struct ea_list *ea_list = NULL;
3647                         TALLOC_CTX *ctx = talloc_init("SMB_INFO_SET_EA");
3648                         if (!ctx) {
3649                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3650                         }
3651                         ea_list = read_ea_list(ctx, pdata, total_data);
3652                         if (!ea_list) {
3653                                 talloc_destroy(ctx);
3654                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3655                         }
3656                         status = set_ea(conn, fsp, fname, ea_list);
3657                         talloc_destroy(ctx);
3658
3659                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK)) {
3660                                 return ERROR_NT(status);
3661                         }
3662                         break;
3663                 }
3664
3665 #if 0
3666                 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3667                 /* XXXX um, i don't think this is right.
3668                         it's also not in the cifs6.txt spec.
3669                 */
3670                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3671                         if (total_data < 28)
3672                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3673
3674                         tvs.actime = make_unix_date2(pdata+8);
3675                         tvs.modtime = make_unix_date2(pdata+12);
3676                         size = IVAL(pdata,16);
3677                         dosmode = IVAL(pdata,24);
3678                         break;
3679
3680                 /* XXXX nor this.  not in cifs6.txt, either. */
3681                 case SMB_INFO_QUERY_ALL_EAS:
3682                         if (total_data < 28)
3683                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3684
3685                         tvs.actime = make_unix_date2(pdata+8);
3686                         tvs.modtime = make_unix_date2(pdata+12);
3687                         size = IVAL(pdata,16);
3688                         dosmode = IVAL(pdata,24);
3689                         break;
3690 #endif
3691
3692                 case SMB_SET_FILE_BASIC_INFO:
3693                 case SMB_FILE_BASIC_INFORMATION:
3694                 {
3695                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3696                         time_t write_time;
3697                         time_t changed_time;
3698
3699                         if (total_data < 36) {
3700                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3701                         }
3702
3703                         /* Ignore create time at offset pdata. */
3704
3705                         /* access time */
3706                         tvs.actime = interpret_long_date(pdata+8);
3707
3708                         write_time = interpret_long_date(pdata+16);
3709                         changed_time = interpret_long_date(pdata+24);
3710
3711                         tvs.modtime = MIN(write_time, changed_time);
3712
3713                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
3714                                 tvs.modtime = write_time;
3715                         }
3716                         /* Prefer a defined time to an undefined one. */
3717                         if (null_mtime(tvs.modtime)) {
3718                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3719                         }
3720
3721                         /* attributes */
3722                         dosmode = IVAL(pdata,32);
3723                         break;
3724                 }
3725
3726                 case SMB_FILE_ALLOCATION_INFORMATION:
3727                 case SMB_SET_FILE_ALLOCATION_INFO:
3728                 {
3729                         int ret = -1;
3730                         SMB_BIG_UINT allocation_size;
3731
3732                         if (total_data < 8) {
3733                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3734                         }
3735
3736                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3737 #ifdef LARGE_SMB_OFF_T
3738                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3739 #else /* LARGE_SMB_OFF_T */
3740                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3741                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3742 #endif /* LARGE_SMB_OFF_T */
3743                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3744                                         fname, (double)allocation_size ));
3745
3746                         if (allocation_size) {
3747                                 allocation_size = smb_roundup(conn, allocation_size);
3748                         }
3749
3750                         if(allocation_size != get_file_size(sbuf)) {
3751                                 SMB_STRUCT_STAT new_sbuf;
3752  
3753                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3754                                         fname, (double)allocation_size ));
3755  
3756                                 if (fd == -1) {
3757                                         files_struct *new_fsp = NULL;
3758                                         int access_mode = 0;
3759                                         int action = 0;
3760  
3761                                         if(global_oplock_break) {
3762                                                 /* Queue this file modify as we are the process of an oplock break.  */
3763  
3764                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3765                                                 DEBUGADD(2,( "in oplock break state.\n"));
3766  
3767                                                 push_oplock_pending_smb_message(inbuf, length);
3768                                                 return -1;
3769                                         }
3770  
3771                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3772                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3773                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3774                                                                         FILE_ATTRIBUTE_NORMAL,
3775                                                                         INTERNAL_OPEN_ONLY, &access_mode, &action);
3776  
3777                                         if (new_fsp == NULL)
3778                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3779                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3780                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3781                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3782                                                                         new_fsp->fnum, strerror(errno)));
3783                                                 ret = -1;
3784                                         }
3785                                         close_file(new_fsp,True);
3786                                 } else {
3787                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3788                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3789                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3790                                                                         fsp->fnum, strerror(errno)));
3791                                                 ret = -1;
3792                                         }
3793                                 }
3794                                 if (ret == -1)
3795                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3796
3797                                 /* Allocate can truncate size... */
3798                                 size = get_file_size(new_sbuf);
3799                         }
3800
3801                         break;
3802                 }
3803
3804                 case SMB_FILE_END_OF_FILE_INFORMATION:
3805                 case SMB_SET_FILE_END_OF_FILE_INFO:
3806                 {
3807                         if (total_data < 8) {
3808                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3809                         }
3810
3811                         size = IVAL(pdata,0);
3812 #ifdef LARGE_SMB_OFF_T
3813                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3814 #else /* LARGE_SMB_OFF_T */
3815                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3816                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3817 #endif /* LARGE_SMB_OFF_T */
3818                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3819                         break;
3820                 }
3821
3822                 case SMB_FILE_DISPOSITION_INFORMATION:
3823                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3824                 {
3825                         BOOL delete_on_close;
3826
3827                         if (total_data < 1) {
3828                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3829                         }
3830
3831                         delete_on_close = (CVAL(pdata,0) ? True : False);
3832
3833                         /* Just ignore this set on a path. */
3834                         if (tran_call != TRANSACT2_SETFILEINFO)
3835                                 break;
3836
3837                         if (fsp == NULL)
3838                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3839
3840                         status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3841  
3842                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3843                                 return ERROR_NT(status);
3844
3845                         /* The set is across all open files on this dev/inode pair. */
3846                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3847                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3848                                 return ERROR_NT(status);
3849
3850                         break;
3851                 }
3852
3853                 case SMB_FILE_POSITION_INFORMATION:
3854                 {
3855                         SMB_BIG_UINT position_information;
3856
3857                         if (total_data < 8) {
3858                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3859                         }
3860
3861                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3862 #ifdef LARGE_SMB_OFF_T
3863                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3864 #else /* LARGE_SMB_OFF_T */
3865                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3866                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3867 #endif /* LARGE_SMB_OFF_T */
3868                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3869                                         fname, (double)position_information ));
3870                         if (fsp)
3871                                 fsp->position_information = position_information;
3872                         break;
3873                 }
3874
3875                 /* From tridge Samba4 : 
3876                  * MODE_INFORMATION in setfileinfo (I have no
3877                  * idea what "mode information" on a file is - it takes a value of 0,
3878                  * 2, 4 or 6. What could it be?).
3879                  */
3880
3881                 case SMB_FILE_MODE_INFORMATION:
3882                 {
3883                         uint32 mode;
3884
3885                         if (total_data < 4) {
3886                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3887                         }
3888                         mode = IVAL(pdata,0);
3889                         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3890                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3891                         }
3892                         break;
3893                 }
3894
3895                 /*
3896                  * CIFS UNIX extensions.
3897                  */
3898
3899                 case SMB_SET_FILE_UNIX_BASIC:
3900                 {
3901                         uint32 raw_unixmode;
3902
3903                         if (total_data < 100) {
3904                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3905                         }
3906
3907                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3908                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3909                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3910 #ifdef LARGE_SMB_OFF_T
3911                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3912 #else /* LARGE_SMB_OFF_T */
3913                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3914                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3915 #endif /* LARGE_SMB_OFF_T */
3916                         }
3917                         pdata+=24;          /* ctime & st_blocks are not changed */
3918                         tvs.actime = interpret_long_date(pdata); /* access_time */
3919                         tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3920                         pdata+=16;
3921                         set_owner = (uid_t)IVAL(pdata,0);
3922                         pdata += 8;
3923                         set_grp = (gid_t)IVAL(pdata,0);
3924                         pdata += 8;
3925                         raw_unixmode = IVAL(pdata,28);
3926                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3927                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
3928
3929                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3930 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3931                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3932
3933                         if (!VALID_STAT(sbuf)) {
3934
3935                                 /*
3936                                  * The only valid use of this is to create character and block
3937                                  * devices, and named pipes. This is deprecated (IMHO) and 
3938                                  * a new info level should be used for mknod. JRA.
3939                                  */
3940
3941                                 uint32 file_type = IVAL(pdata,0);
3942 #if defined(HAVE_MAKEDEV)
3943                                 uint32 dev_major = IVAL(pdata,4);
3944                                 uint32 dev_minor = IVAL(pdata,12);
3945 #endif
3946
3947                                 uid_t myuid = geteuid();
3948                                 gid_t mygid = getegid();
3949                                 SMB_DEV_T dev = (SMB_DEV_T)0;
3950
3951                                 if (tran_call == TRANSACT2_SETFILEINFO)
3952                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3953
3954                                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
3955                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3956                                 }
3957
3958 #if defined(HAVE_MAKEDEV)
3959                                 dev = makedev(dev_major, dev_minor);
3960 #endif
3961
3962                                 /* We can only create as the owner/group we are. */
3963
3964                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3965                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3966                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3967                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3968
3969                                 switch (file_type) {
3970 #if defined(S_IFIFO)
3971                                         case UNIX_TYPE_FIFO:
3972                                                 unixmode |= S_IFIFO;
3973                                                 break;
3974 #endif
3975 #if defined(S_IFSOCK)
3976                                         case UNIX_TYPE_SOCKET:
3977                                                 unixmode |= S_IFSOCK;
3978                                                 break;
3979 #endif
3980 #if defined(S_IFCHR)
3981                                         case UNIX_TYPE_CHARDEV:
3982                                                 unixmode |= S_IFCHR;
3983                                                 break;
3984 #endif
3985 #if defined(S_IFBLK)
3986                                         case UNIX_TYPE_BLKDEV:
3987                                                 unixmode |= S_IFBLK;
3988                                                 break;
3989 #endif
3990                                         default:
3991                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3992                                 }
3993
3994                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3995 0%o for file %s\n", (double)dev, unixmode, fname ));
3996
3997                                 /* Ok - do the mknod. */
3998                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3999                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4000
4001                                 inherit_access_acl(conn, fname, unixmode);
4002
4003                                 SSVAL(params,0,0);
4004                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4005                                 return(-1);
4006                         }
4007
4008                         /*
4009                          * Deal with the UNIX specific mode set.
4010                          */
4011
4012                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4013                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4014                                         (unsigned int)unixmode, fname ));
4015                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4016                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4017                         }
4018
4019                         /*
4020                          * Deal with the UNIX specific uid set.
4021                          */
4022
4023                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4024                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4025                                         (unsigned int)set_owner, fname ));
4026                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4027                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4028                         }
4029
4030                         /*
4031                          * Deal with the UNIX specific gid set.
4032                          */
4033
4034                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4035                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4036                                         (unsigned int)set_owner, fname ));
4037                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4038                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4039                         }
4040                         break;
4041                 }
4042
4043                 case SMB_SET_FILE_UNIX_LINK:
4044                 {
4045                         pstring link_target;
4046                         char *newname = fname;
4047
4048                         /* Set a symbolic link. */
4049                         /* Don't allow this if follow links is false. */
4050
4051                         if (!lp_symlinks(SNUM(conn)))
4052                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4053
4054                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4055
4056                         /* !widelinks forces the target path to be within the share. */
4057                         /* This means we can interpret the target as a pathname. */
4058                         if (!lp_widelinks(SNUM(conn))) {
4059                                 pstring rel_name;
4060                                 char *last_dirp = NULL;
4061
4062                                 unix_format(link_target);
4063                                 if (*link_target == '/') {
4064                                         /* No absolute paths allowed. */
4065                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4066                                 }
4067                                 pstrcpy(rel_name, newname);
4068                                 last_dirp = strrchr_m(rel_name, '/');
4069                                 if (last_dirp) {
4070                                         last_dirp[1] = '\0';
4071                                 } else {
4072                                         pstrcpy(rel_name, "./");
4073                                 }
4074                                 pstrcat(rel_name, link_target);
4075
4076                                 if (!check_name(rel_name, conn)) {
4077                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4078                                 }
4079                         }
4080
4081                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4082                                 fname, link_target ));
4083
4084                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4085                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4086                         SSVAL(params,0,0);
4087                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4088                         return(-1);
4089                 }
4090
4091                 case SMB_SET_FILE_UNIX_HLINK:
4092                 {
4093                         pstring oldname;
4094                         char *newname = fname;
4095
4096                         /* Set a hard link. */
4097                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4098                         if (!NT_STATUS_IS_OK(status)) {
4099                                 return ERROR_NT(status);
4100                         }
4101
4102                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4103                                 fname, oldname));
4104
4105                         status = hardlink_internals(conn, oldname, newname);
4106                         if (!NT_STATUS_IS_OK(status)) {
4107                                 return ERROR_NT(status);
4108                         }
4109
4110                         SSVAL(params,0,0);
4111                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4112                         return(-1);
4113                 }
4114
4115                 case SMB_FILE_RENAME_INFORMATION:
4116                 {
4117                         BOOL overwrite;
4118                         uint32 root_fid;
4119                         uint32 len;
4120                         pstring newname;
4121                         pstring base_name;
4122                         char *p;
4123
4124                         if (total_data < 12) {
4125                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4126                         }
4127
4128                         overwrite = (CVAL(pdata,0) ? True : False);
4129                         root_fid = IVAL(pdata,4);
4130                         len = IVAL(pdata,8);
4131                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4132                         if (!NT_STATUS_IS_OK(status)) {
4133                                 return ERROR_NT(status);
4134                         }
4135
4136                         /* Check the new name has no '/' characters. */
4137                         if (strchr_m(newname, '/'))
4138                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4139
4140                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4141
4142                         /* Create the base directory. */
4143                         pstrcpy(base_name, fname);
4144                         p = strrchr_m(base_name, '/');
4145                         if (p)
4146                                 *p = '\0';
4147                         /* Append the new name. */
4148                         pstrcat(base_name, "/");
4149                         pstrcat(base_name, newname);
4150
4151                         if (fsp) {
4152                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4153                                         fsp->fnum, fsp->fsp_name, base_name ));
4154                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4155                         } else {
4156                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4157                                         fname, newname ));
4158                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
4159                         }
4160                         if (!NT_STATUS_IS_OK(status)) {
4161                                 return ERROR_NT(status);
4162                         }
4163                         process_pending_change_notify_queue((time_t)0);
4164                         SSVAL(params,0,0);
4165                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4166                         return(-1);
4167                 }
4168
4169 #if defined(HAVE_POSIX_ACLS)
4170                 case SMB_SET_POSIX_ACL:
4171                 {
4172                         uint16 posix_acl_version;
4173                         uint16 num_file_acls;
4174                         uint16 num_def_acls;
4175                         BOOL valid_file_acls = True;
4176                         BOOL valid_def_acls = True;
4177
4178                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4179                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4180                         }
4181                         posix_acl_version = SVAL(pdata,0);
4182                         num_file_acls = SVAL(pdata,2);
4183                         num_def_acls = SVAL(pdata,4);
4184
4185                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4186                                 valid_file_acls = False;
4187                                 num_file_acls = 0;
4188                         }
4189
4190                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4191                                 valid_def_acls = False;
4192                                 num_def_acls = 0;
4193                         }
4194
4195                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4196                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4197                         }
4198
4199                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4200                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4201                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4202                         }
4203
4204                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4205                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4206                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4207                         }
4208
4209                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4210                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4211                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4212                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4213                         }
4214
4215                         SSVAL(params,0,0);
4216                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4217                         return(-1);
4218                 }
4219 #endif
4220
4221                 default:
4222                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4223         }
4224
4225         /* get some defaults (no modifications) if any info is zero or -1. */
4226         if (null_mtime(tvs.actime)) {
4227                 tvs.actime = sbuf.st_atime;
4228         }
4229
4230         if (null_mtime(tvs.modtime)) {
4231                 tvs.modtime = sbuf.st_mtime;
4232         }
4233
4234         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4235         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4236         DEBUG(6,("size: %.0f ", (double)size));
4237
4238         if (dosmode) {
4239                 if (S_ISDIR(sbuf.st_mode))
4240                         dosmode |= aDIR;
4241                 else
4242                         dosmode &= ~aDIR;
4243         }
4244
4245         DEBUG(6,("dosmode: %x\n"  , dosmode));
4246
4247         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4248                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4249                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4250                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4251
4252                 /*
4253                  * Only do this test if we are not explicitly
4254                  * changing the size of a file.
4255                  */
4256                 if (!size)
4257                         size = get_file_size(sbuf);
4258         }
4259
4260         /*
4261          * Try and set the times, size and mode of this file -
4262          * if they are different from the current values
4263          */
4264
4265         /* check the mode isn't different, before changing it */
4266         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4267
4268                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4269
4270                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4271                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4272                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4273                 }
4274         }
4275
4276         /* Now the size. */
4277         if (size != get_file_size(sbuf)) {
4278
4279                 int ret;
4280
4281                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4282                         fname, (double)size ));
4283
4284                 if (fd == -1) {
4285                         files_struct *new_fsp = NULL;
4286                         int access_mode = 0;
4287                         int action = 0;
4288
4289                         if(global_oplock_break) {
4290                                 /* Queue this file modify as we are the process of an oplock break.  */
4291
4292                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4293                                 DEBUGADD(2,( "in oplock break state.\n"));
4294
4295                                 push_oplock_pending_smb_message(inbuf, length);
4296                                 return -1;
4297                         }
4298
4299                         new_fsp = open_file_shared(conn, fname, &sbuf,
4300                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
4301                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4302                                                 FILE_ATTRIBUTE_NORMAL,
4303                                                 INTERNAL_OPEN_ONLY, &access_mode, &action);
4304         
4305                         if (new_fsp == NULL)
4306                                 return(UNIXERROR(ERRDOS,ERRbadpath));
4307                         ret = vfs_set_filelen(new_fsp, size);
4308                         close_file(new_fsp,True);
4309                 } else {
4310                         ret = vfs_set_filelen(fsp, size);
4311                 }
4312
4313                 if (ret == -1)
4314                         return (UNIXERROR(ERRHRD,ERRdiskfull));
4315         }
4316
4317         /*
4318          * Finally the times.
4319          */
4320         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4321                 if(fsp != NULL) {
4322                         /*
4323                          * This was a setfileinfo on an open file.
4324                          * NT does this a lot. We also need to 
4325                          * set the time here, as it can be read by 
4326                          * FindFirst/FindNext and with the patch for bug #2045
4327                          * in smbd/fileio.c it ensures that this timestamp is
4328                          * kept sticky even after a write. We save the request
4329                          * away and will set it on file close and after a write. JRA.
4330                          */
4331
4332                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4333                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4334                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4335                         }
4336
4337                 }
4338                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4339
4340                 if(file_utime(conn, fname, &tvs)!=0) {
4341                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4342                 }
4343         }
4344
4345         SSVAL(params,0,0);
4346         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4347   
4348         return(-1);
4349 }
4350
4351 /****************************************************************************
4352  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4353 ****************************************************************************/
4354
4355 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4356                                         char **pparams, int total_params, char **ppdata, int total_data,
4357                                         unsigned int max_data_bytes)
4358 {
4359         char *params = *pparams;
4360         pstring directory;
4361         int ret = -1;
4362         SMB_STRUCT_STAT sbuf;
4363         BOOL bad_path = False;
4364         NTSTATUS status = NT_STATUS_OK;
4365
4366         if (!CAN_WRITE(conn))
4367                 return ERROR_DOS(ERRSRV,ERRaccess);
4368
4369         if (total_params < 4) {
4370                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4371         }
4372
4373         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4374         if (!NT_STATUS_IS_OK(status)) {
4375                 return ERROR_NT(status);
4376         }
4377
4378         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4379
4380         unix_convert(directory,conn,0,&bad_path,&sbuf);
4381         if (bad_path) {
4382                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4383         }
4384         if (check_name(directory,conn))
4385                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4386   
4387         if(ret < 0) {
4388                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4389                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4390         }
4391
4392         /* Realloc the parameter and data sizes */
4393         params = SMB_REALLOC(*pparams,2);
4394         if(params == NULL) {
4395                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4396         }
4397         *pparams = params;
4398
4399         SSVAL(params,0,0);
4400
4401         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4402   
4403         return(-1);
4404 }
4405
4406 /****************************************************************************
4407  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4408  We don't actually do this - we just send a null response.
4409 ****************************************************************************/
4410
4411 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4412                                         char **pparams, int total_params, char **ppdata, int total_data,
4413                                         unsigned int max_data_bytes)
4414 {
4415         static uint16 fnf_handle = 257;
4416         char *params = *pparams;
4417         uint16 info_level;
4418
4419         if (total_params < 6) {
4420                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4421         }
4422
4423         info_level = SVAL(params,4);
4424         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4425
4426         switch (info_level) {
4427                 case 1:
4428                 case 2:
4429                         break;
4430                 default:
4431                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4432         }
4433
4434         /* Realloc the parameter and data sizes */
4435         params = SMB_REALLOC(*pparams,6);
4436         if(params == NULL) {
4437                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4438         }
4439         *pparams = params;
4440
4441         SSVAL(params,0,fnf_handle);
4442         SSVAL(params,2,0); /* No changes */
4443         SSVAL(params,4,0); /* No EA errors */
4444
4445         fnf_handle++;
4446
4447         if(fnf_handle == 0)
4448                 fnf_handle = 257;
4449
4450         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4451   
4452         return(-1);
4453 }
4454
4455 /****************************************************************************
4456  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4457  changes). Currently this does nothing.
4458 ****************************************************************************/
4459
4460 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4461                                         char **pparams, int total_params, char **ppdata, int total_data,
4462                                         unsigned int max_data_bytes)
4463 {
4464         char *params = *pparams;
4465
4466         DEBUG(3,("call_trans2findnotifynext\n"));
4467
4468         /* Realloc the parameter and data sizes */
4469         params = SMB_REALLOC(*pparams,4);
4470         if(params == NULL) {
4471                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4472         }
4473         *pparams = params;
4474
4475         SSVAL(params,0,0); /* No changes */
4476         SSVAL(params,2,0); /* No EA errors */
4477
4478         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4479   
4480         return(-1);
4481 }
4482
4483 /****************************************************************************
4484  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4485 ****************************************************************************/
4486
4487 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4488                                         char **pparams, int total_params, char **ppdata, int total_data,
4489                                         unsigned int max_data_bytes)
4490 {
4491         char *params = *pparams;
4492         pstring pathname;
4493         int reply_size = 0;
4494         int max_referral_level;
4495
4496         DEBUG(10,("call_trans2getdfsreferral\n"));
4497
4498         if (total_params < 2) {
4499                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4500         }
4501
4502         max_referral_level = SVAL(params,0);
4503
4504         if(!lp_host_msdfs())
4505                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4506
4507         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4508         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4509                 return UNIXERROR(ERRDOS,ERRbadfile);
4510     
4511         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4512         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4513
4514         return(-1);
4515 }
4516
4517 #define LMCAT_SPL       0x53
4518 #define LMFUNC_GETJOBID 0x60
4519
4520 /****************************************************************************
4521  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4522 ****************************************************************************/
4523
4524 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4525                                         char **pparams, int total_params, char **ppdata, int total_data,
4526                                         unsigned int max_data_bytes)
4527 {
4528         char *pdata = *ppdata;
4529         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4530
4531         /* check for an invalid fid before proceeding */
4532         
4533         if (!fsp)                                
4534                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4535
4536         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4537                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4538                 pdata = SMB_REALLOC(*ppdata, 32);
4539                 if(pdata == NULL) {
4540                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4541                 }
4542                 *ppdata = pdata;
4543
4544                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4545                         CAN ACCEPT THIS IN UNICODE. JRA. */
4546
4547                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4548                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4549                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4550                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4551                 return(-1);
4552         } else {
4553                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4554                 return ERROR_DOS(ERRSRV,ERRerror);
4555         }
4556 }
4557
4558 /****************************************************************************
4559  Reply to a SMBfindclose (stop trans2 directory search).
4560 ****************************************************************************/
4561
4562 int reply_findclose(connection_struct *conn,
4563                     char *inbuf,char *outbuf,int length,int bufsize)
4564 {
4565         int outsize = 0;
4566         int dptr_num=SVALS(inbuf,smb_vwv0);
4567         START_PROFILE(SMBfindclose);
4568
4569         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4570
4571         dptr_close(&dptr_num);
4572
4573         outsize = set_message(outbuf,0,0,True);
4574
4575         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4576
4577         END_PROFILE(SMBfindclose);
4578         return(outsize);
4579 }
4580
4581 /****************************************************************************
4582  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4583 ****************************************************************************/
4584
4585 int reply_findnclose(connection_struct *conn, 
4586                      char *inbuf,char *outbuf,int length,int bufsize)
4587 {
4588         int outsize = 0;
4589         int dptr_num= -1;
4590         START_PROFILE(SMBfindnclose);
4591         
4592         dptr_num = SVAL(inbuf,smb_vwv0);
4593
4594         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4595
4596         /* We never give out valid handles for a 
4597            findnotifyfirst - so any dptr_num is ok here. 
4598            Just ignore it. */
4599
4600         outsize = set_message(outbuf,0,0,True);
4601
4602         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4603
4604         END_PROFILE(SMBfindnclose);
4605         return(outsize);
4606 }
4607
4608 /****************************************************************************
4609  Reply to a SMBtranss2 - just ignore it!
4610 ****************************************************************************/
4611
4612 int reply_transs2(connection_struct *conn,
4613                   char *inbuf,char *outbuf,int length,int bufsize)
4614 {
4615         START_PROFILE(SMBtranss2);
4616         DEBUG(4,("Ignoring transs2 of length %d\n",length));
4617         END_PROFILE(SMBtranss2);
4618         return(-1);
4619 }
4620
4621 /****************************************************************************
4622  Reply to a SMBtrans2.
4623 ****************************************************************************/
4624
4625 int reply_trans2(connection_struct *conn,
4626                  char *inbuf,char *outbuf,int length,int bufsize)
4627 {
4628         int outsize = 0;
4629         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4630         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4631         unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4632 #if 0
4633         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4634         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4635         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4636         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4637         int32 timeout = IVALS(inbuf,smb_timeout);
4638 #endif
4639         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4640         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4641         char *params = NULL, *data = NULL;
4642         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4643         START_PROFILE(SMBtrans2);
4644
4645         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4646                 /* Queue this open message as we are the process of an
4647                  * oplock break.  */
4648
4649                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4650                 DEBUGADD(2,( "in oplock break state.\n"));
4651
4652                 push_oplock_pending_smb_message(inbuf, length);
4653                 END_PROFILE(SMBtrans2);
4654                 return -1;
4655         }
4656         
4657         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4658             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4659                 END_PROFILE(SMBtrans2);
4660                 return ERROR_DOS(ERRSRV,ERRaccess);
4661         }
4662
4663         outsize = set_message(outbuf,0,0,True);
4664
4665         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4666            is so as a sanity check */
4667         if (suwcnt != 1) {
4668                 /*
4669                  * Need to have rc=0 for ioctl to get job id for OS/2.
4670                  *  Network printing will fail if function is not successful.
4671                  *  Similar function in reply.c will be used if protocol
4672                  *  is LANMAN1.0 instead of LM1.2X002.
4673                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4674                  *  outbuf doesn't have to be set(only job id is used).
4675                  */
4676                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4677                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4678                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4679                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4680                 } else {
4681                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4682                         DEBUG(2,("Transaction is %d\n",tran_call));
4683                         END_PROFILE(SMBtrans2);
4684                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4685                 }
4686         }
4687     
4688         /* Allocate the space for the maximum needed parameters and data */
4689         if (total_params > 0)
4690                 params = (char *)SMB_MALLOC(total_params);
4691         if (total_data > 0)
4692                 data = (char *)SMB_MALLOC(total_data);
4693   
4694         if ((total_params && !params)  || (total_data && !data)) {
4695                 DEBUG(2,("Out of memory in reply_trans2\n"));
4696                 SAFE_FREE(params);
4697                 SAFE_FREE(data); 
4698                 END_PROFILE(SMBtrans2);
4699                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4700         }
4701
4702         /* Copy the param and data bytes sent with this request into
4703            the params buffer */
4704         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4705         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4706
4707         if (num_params > total_params || num_data > total_data)
4708                 exit_server("invalid params in reply_trans2");
4709
4710         if(params) {
4711                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4712                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4713                         goto bad_param;
4714                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4715                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4716                         goto bad_param;
4717                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4718         }
4719         if(data) {
4720                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4721                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4722                         goto bad_param;
4723                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4724                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4725                         goto bad_param;
4726                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4727         }
4728
4729         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4730
4731         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4732                 /* We need to send an interim response then receive the rest
4733                    of the parameter/data bytes */
4734                 outsize = set_message(outbuf,0,0,True);
4735                 srv_signing_trans_stop();
4736                 if (!send_smb(smbd_server_fd(),outbuf))
4737                         exit_server("reply_trans2: send_smb failed.");
4738
4739                 while (num_data_sofar < total_data || 
4740                        num_params_sofar < total_params) {
4741                         BOOL ret;
4742                         unsigned int param_disp;
4743                         unsigned int param_off;
4744                         unsigned int data_disp;
4745                         unsigned int data_off;
4746
4747                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4748                         
4749                         /*
4750                          * The sequence number for the trans reply is always
4751                          * based on the last secondary received.
4752                          */
4753
4754                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4755
4756                         if ((ret && 
4757                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4758                                 outsize = set_message(outbuf,0,0,True);
4759                                 if(ret)
4760                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4761                                 else
4762                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4763                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4764                                 goto bad_param;
4765                         }
4766       
4767                         /* Revise total_params and total_data in case
4768                            they have changed downwards */
4769                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4770                                 total_params = SVAL(inbuf, smb_tpscnt);
4771                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4772                                 total_data = SVAL(inbuf, smb_tdscnt);
4773
4774                         num_params = SVAL(inbuf,smb_spscnt);
4775                         param_off = SVAL(inbuf, smb_spsoff);
4776                         param_disp = SVAL(inbuf, smb_spsdisp);
4777                         num_params_sofar += num_params;
4778
4779                         num_data = SVAL(inbuf, smb_sdscnt);
4780                         data_off = SVAL(inbuf, smb_sdsoff);
4781                         data_disp = SVAL(inbuf, smb_sdsdisp);
4782                         num_data_sofar += num_data;
4783
4784                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4785                                 goto bad_param;
4786                         
4787                         if (num_params) {
4788                                 if (param_disp + num_params > total_params)
4789                                         goto bad_param;
4790                                 if ((param_disp + num_params < param_disp) ||
4791                                                 (param_disp + num_params < num_params))
4792                                         goto bad_param;
4793                                 if (param_disp > total_params)
4794                                         goto bad_param;
4795                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4796                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4797                                         goto bad_param;
4798                                 if (params + param_disp < params)
4799                                         goto bad_param;
4800
4801                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4802                         }
4803                         if (num_data) {
4804                                 if (data_disp + num_data > total_data)
4805                                         goto bad_param;
4806                                 if ((data_disp + num_data < data_disp) ||
4807                                                 (data_disp + num_data < num_data))
4808                                         goto bad_param;
4809                                 if (data_disp > total_data)
4810                                         goto bad_param;
4811                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4812                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4813                                         goto bad_param;
4814                                 if (data + data_disp < data)
4815                                         goto bad_param;
4816
4817                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4818                         }
4819                 }
4820         }
4821         
4822         if (Protocol >= PROTOCOL_NT1) {
4823                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4824         }
4825
4826         /* Now we must call the relevant TRANS2 function */
4827         switch(tran_call)  {
4828         case TRANSACT2_OPEN:
4829                 START_PROFILE_NESTED(Trans2_open);
4830                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4831                                           &params, total_params, &data, total_data, max_data_bytes);
4832                 END_PROFILE_NESTED(Trans2_open);
4833                 break;
4834
4835         case TRANSACT2_FINDFIRST:
4836                 START_PROFILE_NESTED(Trans2_findfirst);
4837                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4838                                           &params, total_params, &data, total_data, max_data_bytes);
4839                 END_PROFILE_NESTED(Trans2_findfirst);
4840                 break;
4841
4842         case TRANSACT2_FINDNEXT:
4843                 START_PROFILE_NESTED(Trans2_findnext);
4844                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4845                                           &params, total_params, &data, total_data, max_data_bytes);
4846                 END_PROFILE_NESTED(Trans2_findnext);
4847                 break;
4848
4849         case TRANSACT2_QFSINFO:
4850                 START_PROFILE_NESTED(Trans2_qfsinfo);
4851                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4852                                           &params, total_params, &data, total_data, max_data_bytes);
4853                 END_PROFILE_NESTED(Trans2_qfsinfo);
4854             break;
4855
4856 #ifdef HAVE_SYS_QUOTAS
4857         case TRANSACT2_SETFSINFO:
4858                 START_PROFILE_NESTED(Trans2_setfsinfo);
4859                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4860                                           &params, total_params, &data, total_data, max_data_bytes);
4861                 END_PROFILE_NESTED(Trans2_setfsinfo);
4862                 break;
4863 #endif
4864         case TRANSACT2_QPATHINFO:
4865         case TRANSACT2_QFILEINFO:
4866                 START_PROFILE_NESTED(Trans2_qpathinfo);
4867                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4868                                           &params, total_params, &data, total_data, max_data_bytes);
4869                 END_PROFILE_NESTED(Trans2_qpathinfo);
4870                 break;
4871         case TRANSACT2_SETPATHINFO:
4872         case TRANSACT2_SETFILEINFO:
4873                 START_PROFILE_NESTED(Trans2_setpathinfo);
4874                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4875                                           &params, total_params, &data, total_data, max_data_bytes);
4876                 END_PROFILE_NESTED(Trans2_setpathinfo);
4877                 break;
4878
4879         case TRANSACT2_FINDNOTIFYFIRST:
4880                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4881                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
4882                                           &params, total_params, &data, total_data, max_data_bytes);
4883                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4884                 break;
4885
4886         case TRANSACT2_FINDNOTIFYNEXT:
4887                 START_PROFILE_NESTED(Trans2_findnotifynext);
4888                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
4889                                           &params, total_params, &data, total_data, max_data_bytes);
4890                 END_PROFILE_NESTED(Trans2_findnotifynext);
4891                 break;
4892         case TRANSACT2_MKDIR:
4893                 START_PROFILE_NESTED(Trans2_mkdir);
4894                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4895                                           &params, total_params, &data, total_data, max_data_bytes);
4896                 END_PROFILE_NESTED(Trans2_mkdir);
4897                 break;
4898
4899         case TRANSACT2_GET_DFS_REFERRAL:
4900                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4901                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4902                                           &params, total_params, &data, total_data, max_data_bytes);
4903                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4904                 break;
4905         case TRANSACT2_IOCTL:
4906                 START_PROFILE_NESTED(Trans2_ioctl);
4907                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4908                                           &params, total_params, &data, total_data, max_data_bytes);
4909                 END_PROFILE_NESTED(Trans2_ioctl);
4910                 break;
4911         default:
4912                 /* Error in request */
4913                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4914                 SAFE_FREE(params);
4915                 SAFE_FREE(data);
4916                 END_PROFILE(SMBtrans2);
4917                 srv_signing_trans_stop();
4918                 return ERROR_DOS(ERRSRV,ERRerror);
4919         }
4920         
4921         /* As we do not know how many data packets will need to be
4922            returned here the various call_trans2xxxx calls
4923            must send their own. Thus a call_trans2xxx routine only
4924            returns a value other than -1 when it wants to send
4925            an error packet. 
4926         */
4927         
4928         srv_signing_trans_stop();
4929
4930         SAFE_FREE(params);
4931         SAFE_FREE(data);
4932         END_PROFILE(SMBtrans2);
4933         return outsize; /* If a correct response was needed the
4934                            call_trans2xxx calls have already sent
4935                            it. If outsize != -1 then it is returning */
4936
4937   bad_param:
4938
4939         srv_signing_trans_stop();
4940         SAFE_FREE(params);
4941         SAFE_FREE(data);
4942         END_PROFILE(SMBtrans2);
4943         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4944 }